Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

243 feature add checkbox input in create form template flow #268

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Rnd, RndResizeCallback } from 'react-rnd';
DonnyLe marked this conversation as resolved.
Show resolved Hide resolved
import { DraggableEventHandler } from 'react-draggable';
import { TextFieldPosition } from './FormEditor';
import { FieldType, TextFieldPosition } from './FormEditor';
import { FaTimes } from 'react-icons/fa';

export default function DraggableText({
Expand All @@ -10,6 +10,8 @@ export default function DraggableText({
onRemove,
currentPosition,
disableEdit,
type,
disableDelete,
}: {
onStop: DraggableEventHandler;
onResizeStop: RndResizeCallback;
Expand All @@ -18,14 +20,22 @@ export default function DraggableText({
onRemove: () => void;
currentPosition: TextFieldPosition;
disableEdit: boolean;
type: FieldType;
disableDelete: boolean;
}) {
return (
<Rnd
lockAspectRatio={type == FieldType.Checkbox ? true : false}
bounds="parent"
position={{ x: currentPosition.x, y: currentPosition.y }}
size={{ height: currentPosition.height, width: currentPosition.width }}
minWidth="50px"
minHeight="40px"
minWidth={type == FieldType.Checkbox ? '10px' : '50px'}
enableResizing={
DonnyLe marked this conversation as resolved.
Show resolved Hide resolved
type == FieldType.Checkbox
? { left: false, right: false, top: false, bottom: false }
: {}
}
minHeight={type == FieldType.Checkbox ? '10px' : '40px'}
style={{
position: 'absolute',
zIndex: 100000,
Expand All @@ -45,7 +55,7 @@ export default function DraggableText({
borderRadius: 4,
}}
>
{!disableEdit && (
{!disableEdit && disableDelete && (
<div
style={{
display: 'inline-block',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useRef, useState } from 'react';
import { Document, Page, pdfjs } from 'react-pdf';
import { Box, Text, Button } from '@chakra-ui/react';
import { TextIcon, PlusSign } from 'apps/web/src/static/icons';
import { TextIcon, PlusSign, Checkbox } from 'apps/web/src/static/icons';
import { DraggableData, DraggableEvent } from 'react-draggable';
import PagingControl from './PagingControl';
import { v4 as uuidv4 } from 'uuid';
Expand All @@ -17,6 +17,12 @@ export type TextFieldPosition = {
height: number;
};

export enum FieldType {
DonnyLe marked this conversation as resolved.
Show resolved Hide resolved
Text,
Checkbox,
Signature,
}

type FieldGroupColor = {
border: string;
background: string;
Expand All @@ -29,7 +35,10 @@ export type FieldGroups = Map<groupId, FieldGroupColor>;
// index = page num (zero indexing)
export type FormFields = Record<
number,
Map<fieldId, { position: TextFieldPosition; groupId: string }>
Map<
fieldId,
{ position: TextFieldPosition; groupId: string; type: FieldType }
>
>;

export const FormEditor = ({
Expand All @@ -50,6 +59,7 @@ export const FormEditor = ({
const [totalPages, setTotalPages] = useState(0);
const documentRef = useRef<HTMLDivElement>(null);
const [groupNum, setGroupNum] = useState(fieldGroups.size);
const [deleteFields, setDeleteFields] = useState(false);

//colors for group buttons: colors[0] = border/text color, colors[1] = background color
const groupColors = [
Expand All @@ -60,13 +70,9 @@ export const FormEditor = ({
['#A16308', '#FFFDDB'],
];

const handleAddField = () => {
const handleAddTextField = () => {
if (fieldGroups.size > 0 && documentRef.current && !disableEdit) {
const container = documentRef.current;
const { scrollLeft, scrollTop, clientWidth, clientHeight } = container;

const centerX = scrollLeft + clientWidth / 2;
const centerY = scrollTop + clientHeight / 2;
const { centerX, centerY } = convertCoordinates(documentRef.current);

setFormFields({
...formFields,
Expand All @@ -82,6 +88,33 @@ export const FormEditor = ({
height: 30,
},
groupId: currentGroup,
type: FieldType.Text,
},
],
]),
});
}
};

const handleAddCheckbox = () => {
if (fieldGroups.size > 0 && documentRef.current && !disableEdit) {
const { centerX, centerY } = convertCoordinates(documentRef.current);

setFormFields({
...formFields,
[pageNum]: new Map([
...formFields[pageNum],
[
uuidv4(),
{
position: {
x: centerX - 40,
y: centerY - 15,
width: 10,
height: 10,
},
groupId: currentGroup,
type: FieldType.Checkbox,
},
],
]),
Expand All @@ -108,11 +141,15 @@ export const FormEditor = ({
pos: TextFieldPosition,
) => {
if (disableEdit) return;

console.log(pos.x, pos.y);
setFormFields({
...formFields,
[pageNum]: new Map([
...formFields[pageNum].set(fieldId, { position: pos, groupId }),
...formFields[pageNum].set(fieldId, {
position: pos,
groupId: groupId,
type: formFields[pageNum].get(fieldId)?.type ?? FieldType.Text,
}),
]),
});
};
Expand All @@ -133,6 +170,13 @@ export const FormEditor = ({
}
};

const convertCoordinates = (container: HTMLDivElement) => {
const { scrollLeft, scrollTop, clientWidth, clientHeight } = container;
const centerX = scrollLeft + clientWidth / 2;
const centerY = scrollTop + clientHeight / 2;
return { centerX, centerY };
};

return (
<Box
background="white"
Expand Down Expand Up @@ -229,10 +273,38 @@ export const FormEditor = ({
justifyContent="center"
alignItems="center"
isDisabled={fieldGroups.size == 0 || disableEdit}
onClick={handleAddField}
onClick={handleAddTextField}
>
<div>{TextIcon}</div>
</Button>
<Button
DonnyLe marked this conversation as resolved.
Show resolved Hide resolved
position="relative"
width="40px"
height="40px"
backgroundColor="white"
borderRadius="4px"
display="flex"
justifyContent="center"
alignItems="center"
isDisabled={fieldGroups.size == 0 || disableEdit}
onClick={handleAddCheckbox}
>
<div>{Checkbox}</div>
</Button>
<Button
position="relative"
width="40px"
height="40px"
backgroundColor="white"
borderRadius="4px"
display="flex"
justifyContent="center"
alignItems="center"
isDisabled={fieldGroups.size == 0 || disableEdit}
onClick={() => setDeleteFields(!deleteFields)}
>
<div>X</div>
</Button>
</Box>
<Box
height="474px"
Expand Down Expand Up @@ -271,6 +343,11 @@ export const FormEditor = ({
Array.from(formFields[pageNum].entries()).map(
([fieldId, { position, groupId }], index) => (
<DraggableText
disableDelete={deleteFields}
type={
formFields[pageNum].get(fieldId)?.type ??
FieldType.Text
}
currentPosition={position}
onRemove={() => {
handleRemoveField(fieldId);
Expand Down Expand Up @@ -299,9 +376,9 @@ export const FormEditor = ({
width: Number.isNaN(newWidth)
? position.width
: newWidth,
height: Number.isNaN(newHeight)
? position.height
: newHeight,
height: Number.isNaN(newWidth)
? position.width
: newWidth,
x: pos.x,
y: pos.y,
});
Expand Down
18 changes: 18 additions & 0 deletions apps/web/src/static/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,24 @@ export const CalendarClockIcon = (
<path d="M200-640h560v-80H200v80Zm0 0v-80 80Zm0 560q-33 0-56.5-23.5T120-160v-560q0-33 23.5-56.5T200-800h40v-80h80v80h320v-80h80v80h40q33 0 56.5 23.5T840-720v227q-19-9-39-15t-41-9v-43H200v400h252q7 22 16.5 42T491-80H200Zm520 40q-83 0-141.5-58.5T520-240q0-83 58.5-141.5T720-440q83 0 141.5 58.5T920-240q0 83-58.5 141.5T720-40Zm67-105 28-28-75-75v-112h-40v128l87 87Z" />
</svg>
);
export const Checkbox = (
<svg
width="18"
height="18"
viewBox="0 0 18 18"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g id="flowbite:check-outline">
<rect x="1" y="1" width="16" height="16" rx="1.5" stroke="#808080" />
<path
id="Vector"
d="M6.89585 12.0815L4.61773 9.32207C4.36168 9.01193 3.94808 9.01193 3.69203 9.32207C3.43599 9.63221 3.43599 10.1332 3.69203 10.4433L6.43629 13.7674C6.69233 14.0775 7.10594 14.0775 7.36198 13.7674L14.308 5.35388C14.564 5.04374 14.564 4.54274 14.308 4.2326C14.0519 3.92247 13.6383 3.92247 13.3823 4.2326L6.89585 12.0815Z"
fill="#808080"
/>
</g>
</svg>
);

export const UploadIcon = createIcon({
displayName: 'UploadIcon',
Expand Down
Loading