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 all 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
3 changes: 2 additions & 1 deletion apps/web/src/components/createFormTemplate/ReviewBox.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Box, Text, Flex } from '@chakra-ui/react';
import { FormEditor, FieldGroups } from './createFormTemplateEditor/FormEditor';
import { FormEditor } from './createFormTemplateEditor/FormEditor';
import { FieldGroups } from './types';
import { useCreateFormTemplate } from '../../context/CreateFormTemplateContext';

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { Rnd, RndResizeCallback } from 'react-rnd';
import { DraggableEventHandler } from 'react-draggable';
import { FieldType, TextFieldPosition } from '../types';
import { FaTimes } from 'react-icons/fa';

export default function Checkbox({
onStop,
onResizeStop,
color,
onRemove,
currentPosition,
disableEdit,
disableDelete,
}: {
onStop: DraggableEventHandler;
onResizeStop: RndResizeCallback;
color: string;
onRemove: () => void;
currentPosition: TextFieldPosition;
disableEdit: boolean;
disableDelete: boolean;
}) {
return (
<Rnd
lockAspectRatio={true}
bounds="parent"
position={{ x: currentPosition.x, y: currentPosition.y }}
size={{ height: currentPosition.height, width: currentPosition.width }}
minWidth={'10px'}
minHeight={'10px'}
enableResizing={{
bottom: false,
bottomLeft: false,
bottomRight: false,
left: false,
right: false,
top: false,
topLeft: false,
topRight: false,
}}
style={{
position: 'absolute',
zIndex: 100000,
background: `${color}`,
opacity: '10px',
border: `solid 1px grey`,
padding: 4,
}}
onDragStop={onStop}
onResizeStop={onResizeStop}
disableDragging={disableEdit}
>
<div
style={{
position: 'absolute',
display: 'inline-block',
borderRadius: 4,
}}
>
{!disableEdit && disableDelete && (
<div
style={{
display: 'inline-block',
cursor: 'pointer',
padding: 4,
}}
onClick={onRemove}
>
<FaTimes color={'#ef6565'} />
</div>
)}
</div>
</Rnd>
);
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { Rnd, RndResizeCallback } from 'react-rnd';
import { DraggableEventHandler } from 'react-draggable';
import { FieldType, TextFieldPosition } from '../types';
import { FaTimes } from 'react-icons/fa';
import Checkbox from './CheckBox';
import TextField from './TextField';

export default function DraggableTextFactory({
onStop,
onResizeStop,
color,
onRemove,
currentPosition,
disableEdit,
type,
disableDelete,
}: {
onStop: DraggableEventHandler;
onResizeStop: RndResizeCallback;
initialText: string | null;
color: string;
onRemove: () => void;
currentPosition: TextFieldPosition;
disableEdit: boolean;
type: FieldType;
disableDelete: boolean;
}) {
return type === FieldType.Checkbox ? (
<Checkbox
onStop={onStop}
onResizeStop={onResizeStop}
color={color}
onRemove={onRemove}
currentPosition={currentPosition}
disableEdit={disableEdit}
disableDelete={disableDelete}
></Checkbox>
) : (
<TextField
onStop={onStop}
onResizeStop={onResizeStop}
color={color}
onRemove={onRemove}
currentPosition={currentPosition}
disableEdit={disableEdit}
disableDelete={disableDelete}
></TextField>
);
}
Original file line number Diff line number Diff line change
@@ -1,37 +1,16 @@
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';
import DraggableText from './DraggableText';
import DraggableTextFactory from './DraggableTextFactory';
import { useCreateFormTemplate } from 'apps/web/src/context/CreateFormTemplateContext';
import { FieldType, TextFieldPosition, FormFields } from '../types';

pdfjs.GlobalWorkerOptions.workerSrc = `https://cdnjs.cloudflare.com/ajax/libs/pdf.js/${pdfjs.version}/pdf.worker.min.js`;

export type TextFieldPosition = {
x: number;
y: number;
width: number;
height: number;
};

type FieldGroupColor = {
border: string;
background: string;
};

type groupId = string;
type fieldId = string;
export type FieldGroups = Map<groupId, FieldGroupColor>;

// index = page num (zero indexing)
export type FormFields = Record<
number,
Map<fieldId, { position: TextFieldPosition; groupId: string }>
>;

export const FormEditor = ({
formTemplateName,
pdfUrl,
Expand All @@ -50,6 +29,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 +40,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 +58,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 +111,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 +140,14 @@ export const FormEditor = ({
}
};

// converts HTML web coordinates to PDF coordinates
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 +244,54 @@ 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>
</Box>
<Box
position="absolute"
right="24px"
top="69px"
background="white"
padding="6px"
boxShadow="0px 1px 4px #E5E5E5"
borderRadius="5px"
border="1px #E5E5E5 solid"
flexDirection="column"
justifyContent="center"
alignItems="center"
gap="8px"
display="flex"
>
<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 @@ -270,7 +329,12 @@ export const FormEditor = ({
{formFields[pageNum] &&
Array.from(formFields[pageNum].entries()).map(
([fieldId, { position, groupId }], index) => (
<DraggableText
<DraggableTextFactory
disableDelete={deleteFields}
type={
formFields[pageNum].get(fieldId)?.type ??
FieldType.Text
}
currentPosition={position}
onRemove={() => {
handleRemoveField(fieldId);
Expand Down Expand Up @@ -299,9 +363,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
Loading