feat: add uninserted field validation

This commit is contained in:
David Nguyen
2023-09-22 16:25:09 +10:00
committed by Mythie
parent ebebceea1f
commit d20ad4217c
7 changed files with 239 additions and 161 deletions

View File

@ -3,7 +3,6 @@
import React, { useRef } from 'react';
import { AnimatePresence, motion } from 'framer-motion';
import { createPortal } from 'react-dom';
import { match } from 'ts-pattern';
import { useElementScaleSize } from '@documenso/lib/client-only/hooks/use-element-scale-size';
@ -16,92 +15,46 @@ import {
} from '@documenso/lib/constants/pdf';
import { Field, FieldType } from '@documenso/prisma/client';
import { FieldWithSignature } from '@documenso/prisma/types/field-with-signature';
import { cn } from '@documenso/ui/lib/utils';
import { Card, CardContent } from '@documenso/ui/primitives/card';
export type FieldContainerPortalProps = {
field: FieldWithSignature;
className?: string;
children: React.ReactNode;
};
import { FieldRootContainer } from '@documenso/ui/components/field/field';
export type SinglePlayerModeFieldContainerProps = {
field: FieldWithSignature;
children: React.ReactNode;
validateUninsertedField?: boolean;
};
export type SinglePlayerModeFieldProps<T> = {
field: T;
onClick?: () => void;
validateUninsertedField?: boolean;
};
export function FieldContainerPortal({
field,
children,
className = '',
}: FieldContainerPortalProps) {
const coords = useFieldPageCoords(field);
return createPortal(
<div
className={cn('absolute', className)}
style={{
top: `${coords.y}px`,
left: `${coords.x}px`,
height: `${coords.height}px`,
width: `${coords.width}px`,
}}
>
{children}
</div>,
document.body,
);
}
export function SinglePlayerModeFieldCardContainer({
field,
children,
validateUninsertedField = false,
}: SinglePlayerModeFieldContainerProps) {
return (
<FieldContainerPortal field={field}>
<motion.div className="h-full w-full" animate={{ opacity: 1 }} exit={{ opacity: 0 }}>
<Card
id={`field-${field.id}`}
className={cn('bg-background relative z-20 h-full w-full transition-all', {
'border-orange-300 ring-1 ring-orange-300': !field.inserted && validateUninsertedField,
})}
data-inserted={field.inserted ? 'true' : 'false'}
<FieldRootContainer field={field}>
<AnimatePresence mode="wait" initial={false}>
<motion.div
key={field.inserted ? 'inserted' : 'not-inserted'}
initial={{ opacity: 0 }}
animate={{
opacity: 1,
}}
exit={{ opacity: 0 }}
transition={{
duration: 0.2,
ease: 'easeIn',
}}
>
<CardContent className="text-foreground hover:shadow-primary-foreground group flex h-full w-full flex-col items-center justify-center p-2">
<AnimatePresence mode="wait" initial={false}>
<motion.div
key={field.inserted ? 'inserted' : 'not-inserted'}
initial={{ opacity: 0 }}
animate={{
opacity: 1,
}}
exit={{ opacity: 0 }}
transition={{
duration: 0.2,
ease: 'easeIn',
}}
>
{children}
</motion.div>
</AnimatePresence>
</CardContent>
</Card>
</motion.div>
</FieldContainerPortal>
{children}
</motion.div>
</AnimatePresence>
</FieldRootContainer>
);
}
export function SinglePlayerModeSignatureField({
field,
validateUninsertedField,
onClick,
}: SinglePlayerModeFieldProps<FieldWithSignature>) {
const fontVariable = '--font-signature';
@ -136,10 +89,7 @@ export function SinglePlayerModeSignatureField({
const insertedTypeSignature = field.inserted && field.Signature?.typedSignature;
return (
<SinglePlayerModeFieldCardContainer
validateUninsertedField={validateUninsertedField}
field={field}
>
<SinglePlayerModeFieldCardContainer field={field}>
{insertedBase64Signature ? (
<img
src={insertedBase64Signature}
@ -171,7 +121,6 @@ export function SinglePlayerModeSignatureField({
export function SinglePlayerModeCustomTextField({
field,
validateUninsertedField,
onClick,
}: SinglePlayerModeFieldProps<Field>) {
const fontVariable = '--font-sans';
@ -203,10 +152,7 @@ export function SinglePlayerModeCustomTextField({
const fontSize = maxFontSize * scalingFactor;
return (
<SinglePlayerModeFieldCardContainer
validateUninsertedField={validateUninsertedField}
field={field}
>
<SinglePlayerModeFieldCardContainer field={field}>
{field.inserted ? (
<p
ref={$paragraphEl}