chore: add more field types (#1141)
Adds a number of new field types and capabilities to existing fields. A massive change with far too many moving pieces to document in a single commit.
This commit is contained in:
@@ -4,13 +4,27 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
|
||||
import { Caveat } from 'next/font/google';
|
||||
|
||||
import { ChevronsUpDown } from 'lucide-react';
|
||||
import {
|
||||
CalendarDays,
|
||||
CheckSquare,
|
||||
ChevronDown,
|
||||
ChevronsUpDown,
|
||||
Disc,
|
||||
Hash,
|
||||
Mail,
|
||||
Type,
|
||||
User,
|
||||
} from 'lucide-react';
|
||||
import { useFieldArray, useForm } from 'react-hook-form';
|
||||
|
||||
import { getBoundingClientRect } from '@documenso/lib/client-only/get-bounding-client-rect';
|
||||
import { useDocumentElement } from '@documenso/lib/client-only/hooks/use-document-element';
|
||||
import { PDF_VIEWER_PAGE_SELECTOR } from '@documenso/lib/constants/pdf-viewer';
|
||||
import { RECIPIENT_ROLES_DESCRIPTION } from '@documenso/lib/constants/recipient-roles';
|
||||
import {
|
||||
type TFieldMetaSchema as FieldMeta,
|
||||
ZFieldMetaSchema,
|
||||
} from '@documenso/lib/types/field-meta';
|
||||
import { nanoid } from '@documenso/lib/universal/id';
|
||||
import type { Field, Recipient } from '@documenso/prisma/client';
|
||||
import { FieldType, RecipientRole } from '@documenso/prisma/client';
|
||||
@@ -28,6 +42,7 @@ import {
|
||||
DocumentFlowFormContainerActions,
|
||||
DocumentFlowFormContainerContent,
|
||||
DocumentFlowFormContainerFooter,
|
||||
DocumentFlowFormContainerHeader,
|
||||
DocumentFlowFormContainerStep,
|
||||
} from '@documenso/ui/primitives/document-flow/document-flow-root';
|
||||
import { FieldItem } from '@documenso/ui/primitives/document-flow/field-item';
|
||||
@@ -35,8 +50,10 @@ import type { DocumentFlowStep } from '@documenso/ui/primitives/document-flow/ty
|
||||
import { FRIENDLY_FIELD_TYPE } from '@documenso/ui/primitives/document-flow/types';
|
||||
import { Popover, PopoverContent, PopoverTrigger } from '@documenso/ui/primitives/popover';
|
||||
|
||||
import { getSignerColorStyles, useSignerColors } from '../../lib/signer-colors';
|
||||
import type { FieldFormType } from '../document-flow/add-fields';
|
||||
import { FieldAdvancedSettings } from '../document-flow/field-item-advanced-settings';
|
||||
import { useStep } from '../stepper';
|
||||
// import { Tooltip, TooltipContent, TooltipTrigger } from '@documenso/ui/primitives/tooltip';
|
||||
import type { TAddTemplateFieldsFormSchema } from './add-template-fields.types';
|
||||
|
||||
const fontCaveat = Caveat({
|
||||
@@ -46,11 +63,8 @@ const fontCaveat = Caveat({
|
||||
variable: '--font-caveat',
|
||||
});
|
||||
|
||||
const DEFAULT_HEIGHT_PERCENT = 5;
|
||||
const DEFAULT_WIDTH_PERCENT = 15;
|
||||
|
||||
const MIN_HEIGHT_PX = 60;
|
||||
const MIN_WIDTH_PX = 200;
|
||||
const MIN_HEIGHT_PX = 40;
|
||||
const MIN_WIDTH_PX = 140;
|
||||
|
||||
export type AddTemplateFieldsFormProps = {
|
||||
documentFlow: DocumentFlowStep;
|
||||
@@ -58,6 +72,7 @@ export type AddTemplateFieldsFormProps = {
|
||||
recipients: Recipient[];
|
||||
fields: Field[];
|
||||
onSubmit: (_data: TAddTemplateFieldsFormSchema) => void;
|
||||
teamId?: number;
|
||||
};
|
||||
|
||||
export const AddTemplateFieldsFormPartial = ({
|
||||
@@ -66,15 +81,19 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
recipients,
|
||||
fields,
|
||||
onSubmit,
|
||||
teamId,
|
||||
}: AddTemplateFieldsFormProps) => {
|
||||
const { isWithinPageBounds, getFieldPosition, getPage } = useDocumentElement();
|
||||
|
||||
const { currentStep, totalSteps, previousStep } = useStep();
|
||||
const [showAdvancedSettings, setShowAdvancedSettings] = useState(false);
|
||||
const [currentField, setCurrentField] = useState<FieldFormType>();
|
||||
|
||||
const {
|
||||
control,
|
||||
handleSubmit,
|
||||
formState: { isSubmitting },
|
||||
setValue,
|
||||
getValues,
|
||||
} = useForm<TAddTemplateFieldsFormSchema>({
|
||||
defaultValues: {
|
||||
fields: fields.map((field) => ({
|
||||
@@ -97,6 +116,25 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
|
||||
const onFormSubmit = handleSubmit(onSubmit);
|
||||
|
||||
const handleSavedFieldSettings = (fieldState: FieldMeta) => {
|
||||
const initialValues = getValues();
|
||||
|
||||
const updatedFields = initialValues.fields.map((field) => {
|
||||
if (field.formId === currentField?.formId) {
|
||||
const parsedFieldMeta = ZFieldMetaSchema.parse(fieldState);
|
||||
|
||||
return {
|
||||
...field,
|
||||
fieldMeta: parsedFieldMeta,
|
||||
};
|
||||
}
|
||||
|
||||
return field;
|
||||
});
|
||||
|
||||
setValue('fields', updatedFields);
|
||||
};
|
||||
|
||||
const {
|
||||
append,
|
||||
remove,
|
||||
@@ -111,6 +149,11 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
const [selectedSigner, setSelectedSigner] = useState<Recipient | null>(null);
|
||||
const [showRecipientsSelector, setShowRecipientsSelector] = useState(false);
|
||||
|
||||
const selectedSignerIndex = recipients.findIndex((r) => r.id === selectedSigner?.id);
|
||||
const selectedSignerStyles = useSignerColors(
|
||||
selectedSignerIndex === -1 ? 0 : selectedSignerIndex,
|
||||
);
|
||||
|
||||
const [isFieldWithinBounds, setIsFieldWithinBounds] = useState(false);
|
||||
const [coords, setCoords] = useState({
|
||||
x: 0,
|
||||
@@ -189,6 +232,7 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
signerEmail: selectedSigner.email,
|
||||
signerId: selectedSigner.id,
|
||||
signerToken: selectedSigner.token ?? '',
|
||||
fieldMeta: undefined,
|
||||
});
|
||||
|
||||
setIsFieldWithinBounds(false);
|
||||
@@ -270,11 +314,9 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
return;
|
||||
}
|
||||
|
||||
const { height, width } = $page.getBoundingClientRect();
|
||||
|
||||
fieldBounds.current = {
|
||||
height: Math.max(height * (DEFAULT_HEIGHT_PERCENT / 100), MIN_HEIGHT_PX),
|
||||
width: Math.max(width * (DEFAULT_WIDTH_PERCENT / 100), MIN_WIDTH_PX),
|
||||
height: Math.max(MIN_HEIGHT_PX),
|
||||
width: Math.max(MIN_WIDTH_PX),
|
||||
};
|
||||
});
|
||||
|
||||
@@ -314,265 +356,428 @@ export const AddTemplateFieldsFormPartial = ({
|
||||
);
|
||||
}, [recipientsByRole]);
|
||||
|
||||
const handleAdvancedSettings = () => {
|
||||
setShowAdvancedSettings((prev) => !prev);
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<DocumentFlowFormContainerContent>
|
||||
<div className="flex flex-col">
|
||||
{selectedField && (
|
||||
<Card
|
||||
className={cn(
|
||||
'bg-background pointer-events-none fixed z-50 cursor-pointer transition-opacity',
|
||||
{
|
||||
'border-primary': isFieldWithinBounds,
|
||||
'opacity-50': !isFieldWithinBounds,
|
||||
},
|
||||
)}
|
||||
style={{
|
||||
top: coords.y,
|
||||
left: coords.x,
|
||||
height: fieldBounds.current.height,
|
||||
width: fieldBounds.current.width,
|
||||
}}
|
||||
>
|
||||
<CardContent className="text-foreground flex h-full w-full items-center justify-center p-2">
|
||||
{FRIENDLY_FIELD_TYPE[selectedField]}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)}
|
||||
|
||||
{localFields.map((field, index) => (
|
||||
<FieldItem
|
||||
key={index}
|
||||
field={field}
|
||||
disabled={selectedSigner?.email !== field.signerEmail}
|
||||
minHeight={fieldBounds.current.height}
|
||||
minWidth={fieldBounds.current.width}
|
||||
passive={isFieldWithinBounds && !!selectedField}
|
||||
onResize={(options) => onFieldResize(options, index)}
|
||||
onMove={(options) => onFieldMove(options, index)}
|
||||
onRemove={() => remove(index)}
|
||||
/>
|
||||
))}
|
||||
|
||||
{!hideRecipients && (
|
||||
<Popover open={showRecipientsSelector} onOpenChange={setShowRecipientsSelector}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
className="bg-background text-muted-foreground mb-12 justify-between font-normal"
|
||||
{showAdvancedSettings && currentField ? (
|
||||
<FieldAdvancedSettings
|
||||
title="Advanced settings"
|
||||
description={`Configure the ${FRIENDLY_FIELD_TYPE[currentField.type]} field`}
|
||||
field={currentField}
|
||||
fields={localFields}
|
||||
onAdvancedSettings={handleAdvancedSettings}
|
||||
onSave={handleSavedFieldSettings}
|
||||
teamId={teamId}
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<DocumentFlowFormContainerHeader
|
||||
title={documentFlow.title}
|
||||
description={documentFlow.description}
|
||||
/>
|
||||
<DocumentFlowFormContainerContent>
|
||||
<div className="flex flex-col">
|
||||
{selectedField && (
|
||||
<div
|
||||
className={cn(
|
||||
'pointer-events-none fixed z-50 flex cursor-pointer flex-col items-center justify-center bg-white transition duration-200',
|
||||
selectedSignerStyles.default.base,
|
||||
{
|
||||
'-rotate-6 scale-90 opacity-50': !isFieldWithinBounds,
|
||||
},
|
||||
)}
|
||||
style={{
|
||||
top: coords.y,
|
||||
left: coords.x,
|
||||
height: fieldBounds.current.height,
|
||||
width: fieldBounds.current.width,
|
||||
}}
|
||||
>
|
||||
{selectedSigner?.email && (
|
||||
<span className="flex-1 truncate text-left">
|
||||
{selectedSigner?.name} ({selectedSigner?.email})
|
||||
</span>
|
||||
)}
|
||||
{FRIENDLY_FIELD_TYPE[selectedField]}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!selectedSigner?.email && (
|
||||
<span className="flex-1 truncate text-left">{selectedSigner?.email}</span>
|
||||
)}
|
||||
{localFields.map((field, index) => {
|
||||
const recipientIndex = recipients.findIndex((r) => r.email === field.signerEmail);
|
||||
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
return (
|
||||
<FieldItem
|
||||
key={index}
|
||||
recipientIndex={recipientIndex === -1 ? 0 : recipientIndex}
|
||||
field={field}
|
||||
disabled={selectedSigner?.email !== field.signerEmail}
|
||||
minHeight={fieldBounds.current.height}
|
||||
minWidth={fieldBounds.current.width}
|
||||
passive={isFieldWithinBounds && !!selectedField}
|
||||
onResize={(options) => onFieldResize(options, index)}
|
||||
onMove={(options) => onFieldMove(options, index)}
|
||||
onRemove={() => remove(index)}
|
||||
onAdvancedSettings={() => {
|
||||
setCurrentField(field);
|
||||
handleAdvancedSettings();
|
||||
}}
|
||||
hideRecipients={hideRecipients}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
<PopoverContent className="p-0" align="start">
|
||||
<Command>
|
||||
<CommandInput />
|
||||
<CommandEmpty>
|
||||
<span className="text-muted-foreground inline-block px-4">
|
||||
No recipient matching this description was found.
|
||||
</span>
|
||||
</CommandEmpty>
|
||||
|
||||
{recipientsByRoleToDisplay.map(([role, recipients], roleIndex) => (
|
||||
<CommandGroup key={roleIndex}>
|
||||
<div className="text-muted-foreground mb-1 ml-2 mt-2 text-xs font-medium">
|
||||
{`${RECIPIENT_ROLES_DESCRIPTION[role].roleName}s`}
|
||||
</div>
|
||||
|
||||
{recipients.length === 0 && (
|
||||
<div
|
||||
key={`${role}-empty`}
|
||||
className="text-muted-foreground/80 px-4 pb-4 pt-2.5 text-center text-xs"
|
||||
>
|
||||
No recipients with this role
|
||||
</div>
|
||||
{!hideRecipients && (
|
||||
<Popover open={showRecipientsSelector} onOpenChange={setShowRecipientsSelector}>
|
||||
<PopoverTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
variant="outline"
|
||||
role="combobox"
|
||||
className={cn(
|
||||
'bg-background text-muted-foreground hover:text-foreground mb-12 mt-2 justify-between font-normal',
|
||||
selectedSignerStyles.default.base,
|
||||
)}
|
||||
>
|
||||
{selectedSigner?.email && (
|
||||
<span className="flex-1 truncate text-left">
|
||||
{selectedSigner?.name} ({selectedSigner?.email})
|
||||
</span>
|
||||
)}
|
||||
|
||||
{recipients.map((recipient) => (
|
||||
<CommandItem
|
||||
key={recipient.id}
|
||||
className={cn('px-2 last:mb-1 [&:not(:first-child)]:mt-1')}
|
||||
onSelect={() => {
|
||||
setSelectedSigner(recipient);
|
||||
setShowRecipientsSelector(false);
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className={cn('text-foreground/70 truncate', {
|
||||
'text-foreground/80': recipient === selectedSigner,
|
||||
})}
|
||||
>
|
||||
{recipient.name && (
|
||||
<span title={`${recipient.name} (${recipient.email})`}>
|
||||
{recipient.name} ({recipient.email})
|
||||
{!selectedSigner?.email && (
|
||||
<span className="gradie flex-1 truncate text-left">
|
||||
{selectedSigner?.email}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<ChevronsUpDown className="ml-2 h-4 w-4" />
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
|
||||
<PopoverContent className="p-0" align="start">
|
||||
<Command value={selectedSigner?.email}>
|
||||
<CommandInput />
|
||||
|
||||
<CommandEmpty>
|
||||
<span className="text-muted-foreground inline-block px-4">
|
||||
No recipient matching this description was found.
|
||||
</span>
|
||||
</CommandEmpty>
|
||||
|
||||
{recipientsByRoleToDisplay.map(([role, roleRecipients], roleIndex) => (
|
||||
<CommandGroup key={roleIndex}>
|
||||
<div className="text-muted-foreground mb-1 ml-2 mt-2 text-xs font-medium">
|
||||
{`${RECIPIENT_ROLES_DESCRIPTION[role].roleName}s`}
|
||||
</div>
|
||||
|
||||
{roleRecipients.length === 0 && (
|
||||
<div
|
||||
key={`${role}-empty`}
|
||||
className="text-muted-foreground/80 px-4 pb-4 pt-2.5 text-center text-xs"
|
||||
>
|
||||
No recipients with this role
|
||||
</div>
|
||||
)}
|
||||
|
||||
{roleRecipients.map((recipient) => (
|
||||
<CommandItem
|
||||
key={recipient.id}
|
||||
className={cn(
|
||||
'px-2 last:mb-1 [&:not(:first-child)]:mt-1',
|
||||
getSignerColorStyles(
|
||||
Math.max(
|
||||
recipients.findIndex((r) => r.id === recipient.id),
|
||||
0,
|
||||
),
|
||||
).default.comboxBoxItem,
|
||||
)}
|
||||
onSelect={() => {
|
||||
setSelectedSigner(recipient);
|
||||
setShowRecipientsSelector(false);
|
||||
}}
|
||||
>
|
||||
<span
|
||||
className={cn('text-foreground/70 truncate', {
|
||||
'text-foreground/80': recipient === selectedSigner,
|
||||
})}
|
||||
>
|
||||
{recipient.name && (
|
||||
<span title={`${recipient.name} (${recipient.email})`}>
|
||||
{recipient.name} ({recipient.email})
|
||||
</span>
|
||||
)}
|
||||
|
||||
{!recipient.name && (
|
||||
<span title={recipient.email}>{recipient.email}</span>
|
||||
)}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{!recipient.name && (
|
||||
<span title={recipient.email}>{recipient.email}</span>
|
||||
)}
|
||||
</span>
|
||||
</CommandItem>
|
||||
</CommandItem>
|
||||
))}
|
||||
</CommandGroup>
|
||||
))}
|
||||
</CommandGroup>
|
||||
))}
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
</Command>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)}
|
||||
|
||||
<div className="-mx-2 flex-1 overflow-y-auto px-2">
|
||||
<div className="grid grid-cols-2 gap-x-4 gap-y-8">
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
disabled={!selectedSigner}
|
||||
onClick={() => setSelectedField(FieldType.SIGNATURE)}
|
||||
onMouseDown={() => setSelectedField(FieldType.SIGNATURE)}
|
||||
data-selected={selectedField === FieldType.SIGNATURE ? true : undefined}
|
||||
>
|
||||
<Card className="group-data-[selected]:border-documenso h-full w-full cursor-pointer group-disabled:opacity-50">
|
||||
<CardContent className="flex flex-col items-center justify-center px-6 py-4">
|
||||
<p
|
||||
<div className="-mx-2 flex-1 overflow-y-auto px-2">
|
||||
<fieldset className="my-2 grid grid-cols-3 gap-4">
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.SIGNATURE)}
|
||||
onMouseDown={() => setSelectedField(FieldType.SIGNATURE)}
|
||||
data-selected={selectedField === FieldType.SIGNATURE ? true : undefined}
|
||||
>
|
||||
<Card
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground w-full truncate text-3xl font-medium',
|
||||
fontCaveat.className,
|
||||
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
|
||||
// selectedSignerStyles.borderClass,
|
||||
)}
|
||||
>
|
||||
{selectedSigner?.name || 'Signature'}
|
||||
</p>
|
||||
<CardContent className="flex flex-col items-center justify-center px-6 py-4">
|
||||
<p
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-lg font-normal',
|
||||
fontCaveat.className,
|
||||
)}
|
||||
>
|
||||
Signature
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<p className="text-muted-foreground mt-2 text-center text-xs">Signature</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
disabled={!selectedSigner}
|
||||
onClick={() => setSelectedField(FieldType.EMAIL)}
|
||||
onMouseDown={() => setSelectedField(FieldType.EMAIL)}
|
||||
data-selected={selectedField === FieldType.EMAIL ? true : undefined}
|
||||
>
|
||||
<Card className="group-data-[selected]:border-documenso h-full w-full cursor-pointer group-disabled:opacity-50">
|
||||
<CardContent className="flex flex-col items-center justify-center px-6 py-4">
|
||||
<p
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.EMAIL)}
|
||||
onMouseDown={() => setSelectedField(FieldType.EMAIL)}
|
||||
data-selected={selectedField === FieldType.EMAIL ? true : undefined}
|
||||
>
|
||||
<Card
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground text-xl font-medium',
|
||||
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
|
||||
// selectedSignerStyles.borderClass,
|
||||
)}
|
||||
>
|
||||
{'Email'}
|
||||
</p>
|
||||
<CardContent className="p-4">
|
||||
<p
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
||||
)}
|
||||
>
|
||||
<Mail className="h-4 w-4" />
|
||||
Email
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<p className="text-muted-foreground mt-2 text-xs">Email</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
disabled={!selectedSigner}
|
||||
onClick={() => setSelectedField(FieldType.NAME)}
|
||||
onMouseDown={() => setSelectedField(FieldType.NAME)}
|
||||
data-selected={selectedField === FieldType.NAME ? true : undefined}
|
||||
>
|
||||
<Card className="group-data-[selected]:border-documenso h-full w-full cursor-pointer group-disabled:opacity-50">
|
||||
<CardContent className="flex flex-col items-center justify-center px-6 py-4">
|
||||
<p
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.NAME)}
|
||||
onMouseDown={() => setSelectedField(FieldType.NAME)}
|
||||
data-selected={selectedField === FieldType.NAME ? true : undefined}
|
||||
>
|
||||
<Card
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground text-xl font-medium',
|
||||
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
|
||||
// selectedSignerStyles.borderClass,
|
||||
)}
|
||||
>
|
||||
{'Name'}
|
||||
</p>
|
||||
<CardContent className="p-4">
|
||||
<p
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
||||
)}
|
||||
>
|
||||
<User className="h-4 w-4" />
|
||||
Name
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<p className="text-muted-foreground mt-2 text-xs">Name</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
disabled={!selectedSigner}
|
||||
onClick={() => setSelectedField(FieldType.DATE)}
|
||||
onMouseDown={() => setSelectedField(FieldType.DATE)}
|
||||
data-selected={selectedField === FieldType.DATE ? true : undefined}
|
||||
>
|
||||
<Card className="group-data-[selected]:border-documenso h-full w-full cursor-pointer group-disabled:opacity-50">
|
||||
<CardContent className="flex flex-col items-center justify-center px-6 py-4">
|
||||
<p
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.DATE)}
|
||||
onMouseDown={() => setSelectedField(FieldType.DATE)}
|
||||
data-selected={selectedField === FieldType.DATE ? true : undefined}
|
||||
>
|
||||
<Card
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground text-xl font-medium',
|
||||
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
|
||||
// selectedSignerStyles.borderClass,
|
||||
)}
|
||||
>
|
||||
{'Date'}
|
||||
</p>
|
||||
<CardContent className="p-4">
|
||||
<p
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
||||
)}
|
||||
>
|
||||
<CalendarDays className="h-4 w-4" />
|
||||
Date
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<p className="text-muted-foreground mt-2 text-xs">Date</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.TEXT)}
|
||||
onMouseDown={() => setSelectedField(FieldType.TEXT)}
|
||||
data-selected={selectedField === FieldType.TEXT ? true : undefined}
|
||||
>
|
||||
<Card className="group-data-[selected]:border-documenso h-full w-full cursor-pointer group-disabled:opacity-50">
|
||||
<CardContent className="flex flex-col items-center justify-center px-6 py-4">
|
||||
<p
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.TEXT)}
|
||||
onMouseDown={() => setSelectedField(FieldType.TEXT)}
|
||||
data-selected={selectedField === FieldType.TEXT ? true : undefined}
|
||||
>
|
||||
<Card
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground text-xl font-medium',
|
||||
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
|
||||
// selectedSignerStyles.borderClass,
|
||||
)}
|
||||
>
|
||||
{'Text'}
|
||||
</p>
|
||||
<CardContent className="p-4">
|
||||
<p
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
||||
)}
|
||||
>
|
||||
<Type className="h-4 w-4" />
|
||||
Text
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<p className="text-muted-foreground mt-2 text-xs">Custom Text</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.NUMBER)}
|
||||
onMouseDown={() => setSelectedField(FieldType.NUMBER)}
|
||||
data-selected={selectedField === FieldType.NUMBER ? true : undefined}
|
||||
>
|
||||
<Card
|
||||
className={cn(
|
||||
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
|
||||
// selectedSignerStyles.borderClass,
|
||||
)}
|
||||
>
|
||||
<CardContent className="p-4">
|
||||
<p
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
||||
)}
|
||||
>
|
||||
<Hash className="h-4 w-4" />
|
||||
Number
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.RADIO)}
|
||||
onMouseDown={() => setSelectedField(FieldType.RADIO)}
|
||||
data-selected={selectedField === FieldType.RADIO ? true : undefined}
|
||||
>
|
||||
<Card
|
||||
className={cn(
|
||||
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
|
||||
// selectedSignerStyles.borderClass,
|
||||
)}
|
||||
>
|
||||
<CardContent className="p-4">
|
||||
<p
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
||||
)}
|
||||
>
|
||||
<Disc className="h-4 w-4" />
|
||||
Radio
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.CHECKBOX)}
|
||||
onMouseDown={() => setSelectedField(FieldType.CHECKBOX)}
|
||||
data-selected={selectedField === FieldType.CHECKBOX ? true : undefined}
|
||||
>
|
||||
<Card
|
||||
className={cn(
|
||||
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
|
||||
// selectedSignerStyles.borderClass,
|
||||
)}
|
||||
>
|
||||
<CardContent className="p-4">
|
||||
<p
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
||||
)}
|
||||
>
|
||||
<CheckSquare className="h-4 w-4" />
|
||||
Checkbox
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
|
||||
<button
|
||||
type="button"
|
||||
className="group h-full w-full"
|
||||
onClick={() => setSelectedField(FieldType.DROPDOWN)}
|
||||
onMouseDown={() => setSelectedField(FieldType.DROPDOWN)}
|
||||
data-selected={selectedField === FieldType.DROPDOWN ? true : undefined}
|
||||
>
|
||||
<Card
|
||||
className={cn(
|
||||
'flex h-full w-full cursor-pointer items-center justify-center group-disabled:opacity-50',
|
||||
// selectedSignerStyles.borderClass,
|
||||
)}
|
||||
>
|
||||
<CardContent className="p-4">
|
||||
<p
|
||||
className={cn(
|
||||
'text-muted-foreground group-data-[selected]:text-foreground flex items-center justify-center gap-x-1.5 text-sm font-normal',
|
||||
)}
|
||||
>
|
||||
<ChevronDown className="h-4 w-4" />
|
||||
Dropdown
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</button>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</DocumentFlowFormContainerContent>
|
||||
</DocumentFlowFormContainerContent>
|
||||
|
||||
<DocumentFlowFormContainerFooter>
|
||||
<DocumentFlowFormContainerStep
|
||||
title={documentFlow.title}
|
||||
step={currentStep}
|
||||
maxStep={totalSteps}
|
||||
/>
|
||||
<DocumentFlowFormContainerFooter>
|
||||
<DocumentFlowFormContainerStep
|
||||
title={documentFlow.title}
|
||||
step={currentStep}
|
||||
maxStep={totalSteps}
|
||||
/>
|
||||
|
||||
<DocumentFlowFormContainerActions
|
||||
loading={isSubmitting}
|
||||
disabled={isSubmitting}
|
||||
goNextLabel="Save Template"
|
||||
onGoBackClick={() => {
|
||||
previousStep();
|
||||
remove();
|
||||
}}
|
||||
onGoNextClick={() => void onFormSubmit()}
|
||||
/>
|
||||
</DocumentFlowFormContainerFooter>
|
||||
<DocumentFlowFormContainerActions
|
||||
loading={isSubmitting}
|
||||
disabled={isSubmitting}
|
||||
goNextLabel="Save Template"
|
||||
onGoBackClick={() => {
|
||||
previousStep();
|
||||
remove();
|
||||
}}
|
||||
onGoNextClick={() => void onFormSubmit()}
|
||||
/>
|
||||
</DocumentFlowFormContainerFooter>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user