mirror of
https://github.com/documenso/documenso.git
synced 2025-11-16 17:51:49 +10:00
chore: [incomplete] trying to use checkbox without the dialog
skill issue probably
This commit is contained in:
@ -1,10 +1,13 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { useEffect, useState, useTransition } from 'react';
|
import { useState, useTransition } from 'react';
|
||||||
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
|
|
||||||
|
import { zodResolver } from '@hookform/resolvers/zod';
|
||||||
import { Loader } from 'lucide-react';
|
import { Loader } from 'lucide-react';
|
||||||
|
import { useForm } from 'react-hook-form';
|
||||||
|
import { z } from 'zod';
|
||||||
|
|
||||||
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
import { DO_NOT_INVALIDATE_QUERY_ON_MUTATION } from '@documenso/lib/constants/trpc';
|
||||||
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error';
|
||||||
@ -12,12 +15,10 @@ import type { TRecipientActionAuth } from '@documenso/lib/types/document-auth';
|
|||||||
import type { Recipient } from '@documenso/prisma/client';
|
import type { Recipient } from '@documenso/prisma/client';
|
||||||
import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature';
|
import type { FieldWithSignature } from '@documenso/prisma/types/field-with-signature';
|
||||||
import { trpc } from '@documenso/trpc/react';
|
import { trpc } from '@documenso/trpc/react';
|
||||||
import { Button } from '@documenso/ui/primitives/button';
|
|
||||||
import { Checkbox } from '@documenso/ui/primitives/checkbox';
|
import { Checkbox } from '@documenso/ui/primitives/checkbox';
|
||||||
import { Dialog, DialogContent, DialogFooter, DialogTitle } from '@documenso/ui/primitives/dialog';
|
import { Form, FormControl, FormField } from '@documenso/ui/primitives/form/form';
|
||||||
import { useToast } from '@documenso/ui/primitives/use-toast';
|
import { useToast } from '@documenso/ui/primitives/use-toast';
|
||||||
|
|
||||||
import { useRequiredDocumentAuthContext } from './document-auth-provider';
|
|
||||||
import { SigningFieldContainer } from './signing-field-container';
|
import { SigningFieldContainer } from './signing-field-container';
|
||||||
|
|
||||||
export type CheckboxFieldProps = {
|
export type CheckboxFieldProps = {
|
||||||
@ -25,12 +26,16 @@ export type CheckboxFieldProps = {
|
|||||||
recipient: Recipient;
|
recipient: Recipient;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const CheckBoxSchema = z.object({
|
||||||
|
check: z.boolean().default(false).optional(),
|
||||||
|
});
|
||||||
|
|
||||||
export const CheckboxField = ({ field, recipient }: CheckboxFieldProps) => {
|
export const CheckboxField = ({ field, recipient }: CheckboxFieldProps) => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const { toast } = useToast();
|
const { toast } = useToast();
|
||||||
|
|
||||||
const { executeActionAuthProcedure } = useRequiredDocumentAuthContext();
|
// const { executeActionAuthProcedure } = useRequiredDocumentAuthContext();
|
||||||
|
|
||||||
const [isPending, startTransition] = useTransition();
|
const [isPending, startTransition] = useTransition();
|
||||||
|
|
||||||
@ -44,30 +49,17 @@ export const CheckboxField = ({ field, recipient }: CheckboxFieldProps) => {
|
|||||||
|
|
||||||
const isLoading = isSignFieldWithTokenLoading || isRemoveSignedFieldWithTokenLoading || isPending;
|
const isLoading = isSignFieldWithTokenLoading || isRemoveSignedFieldWithTokenLoading || isPending;
|
||||||
|
|
||||||
const [showCustomTextModal, setShowCustomTextModal] = useState(false);
|
|
||||||
const [localText, setLocalCustomText] = useState('');
|
const [localText, setLocalCustomText] = useState('');
|
||||||
|
|
||||||
useEffect(() => {
|
const form = useForm<z.infer<typeof CheckBoxSchema>>({
|
||||||
if (!showCustomTextModal) {
|
resolver: zodResolver(CheckBoxSchema),
|
||||||
setLocalCustomText('');
|
defaultValues: {
|
||||||
}
|
check: true,
|
||||||
}, [showCustomTextModal]);
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* When the user clicks the sign button in the dialog where they enter the text field.
|
|
||||||
*/
|
|
||||||
const onDialogSignClick = () => {
|
|
||||||
setShowCustomTextModal(false);
|
|
||||||
|
|
||||||
void executeActionAuthProcedure({
|
|
||||||
onReauthFormSubmit: async (authOptions) => await onSign(authOptions),
|
|
||||||
actionTarget: field.type,
|
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
const onPreSign = () => {
|
const onPreSign = () => {
|
||||||
if (!localText) {
|
if (!localText) {
|
||||||
setShowCustomTextModal(true);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,13 +119,18 @@ export const CheckboxField = ({ field, recipient }: CheckboxFieldProps) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onSubmit = (data: z.infer<typeof CheckBoxSchema>) => {
|
||||||
|
console.log(data);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SigningFieldContainer
|
<SigningFieldContainer
|
||||||
field={field}
|
field={field}
|
||||||
onPreSign={onPreSign}
|
onPreSign={onPreSign}
|
||||||
onSign={onSign}
|
onSign={onSign}
|
||||||
onRemove={onRemove}
|
onRemove={onRemove}
|
||||||
type="Signature"
|
type="Checkbox"
|
||||||
|
raw={true}
|
||||||
>
|
>
|
||||||
{isLoading && (
|
{isLoading && (
|
||||||
<div className="bg-background absolute inset-0 flex items-center justify-center rounded-md">
|
<div className="bg-background absolute inset-0 flex items-center justify-center rounded-md">
|
||||||
@ -142,54 +139,37 @@ export const CheckboxField = ({ field, recipient }: CheckboxFieldProps) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{!field.inserted && (
|
{!field.inserted && (
|
||||||
<p className="group-hover:text-primary text-muted-foreground text-lg duration-200">
|
// TODO: span with a box
|
||||||
Checkbox
|
// <p className="group-hover:text-primary text-muted-foreground text-lg duration-200">
|
||||||
</p>
|
// Checkbox
|
||||||
)}
|
// </p>
|
||||||
|
|
||||||
{field.inserted && <p className="text-muted-foreground duration-200">{field.customText}</p>}
|
|
||||||
|
|
||||||
{/* TODO : Avoid the whole dialog thing */}
|
|
||||||
<Dialog open={showCustomTextModal} onOpenChange={setShowCustomTextModal}>
|
|
||||||
<DialogContent>
|
|
||||||
<DialogTitle>Check Field</DialogTitle>
|
|
||||||
|
|
||||||
<div className="mt-4 flex items-center space-x-2">
|
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id="checkbox-field"
|
id={`field-${field.id}`}
|
||||||
|
onClick={() => {
|
||||||
|
console.log('clicked checkbox');
|
||||||
|
}}
|
||||||
onCheckedChange={(checked) => {
|
onCheckedChange={(checked) => {
|
||||||
setLocalCustomText(checked ? '✓' : '𐄂');
|
setLocalCustomText(checked ? '✓' : '𐄂');
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<label
|
)}
|
||||||
htmlFor="checkbox-field"
|
|
||||||
className="font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
|
|
||||||
>
|
|
||||||
Check Field
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<DialogFooter>
|
{field.inserted && <p className="text-muted-foreground duration-200">{field.customText}</p>}
|
||||||
<div className="mt-4 flex w-full flex-1 flex-nowrap gap-4">
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
className="dark:bg-muted dark:hover:bg-muted/80 flex-1 bg-black/5 hover:bg-black/10"
|
|
||||||
variant="secondary"
|
|
||||||
onClick={() => {
|
|
||||||
setShowCustomTextModal(false);
|
|
||||||
setLocalCustomText('');
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button type="button" className="flex-1" onClick={() => onDialogSignClick()}>
|
<Form {...form}>
|
||||||
Save Checkbox
|
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||||
</Button>
|
<FormField
|
||||||
</div>
|
control={form.control}
|
||||||
</DialogFooter>
|
name="check"
|
||||||
</DialogContent>
|
render={({ field }) => (
|
||||||
</Dialog>
|
<FormControl>
|
||||||
|
<Checkbox checked={field.value} onCheckedChange={field.onChange} />
|
||||||
|
</FormControl>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
</SigningFieldContainer>
|
</SigningFieldContainer>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -35,8 +35,10 @@ export type SignatureFieldProps = {
|
|||||||
*/
|
*/
|
||||||
onSign?: (documentAuthValue?: TRecipientActionAuth) => Promise<void> | void;
|
onSign?: (documentAuthValue?: TRecipientActionAuth) => Promise<void> | void;
|
||||||
onRemove?: () => Promise<void> | void;
|
onRemove?: () => Promise<void> | void;
|
||||||
type?: 'Date' | 'Email' | 'Name' | 'Signature';
|
type?: 'Date' | 'Email' | 'Name' | 'Signature' | 'Checkbox';
|
||||||
tooltipText?: string | null;
|
tooltipText?: string | null;
|
||||||
|
|
||||||
|
raw?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SigningFieldContainer = ({
|
export const SigningFieldContainer = ({
|
||||||
@ -48,6 +50,7 @@ export const SigningFieldContainer = ({
|
|||||||
children,
|
children,
|
||||||
type,
|
type,
|
||||||
tooltipText,
|
tooltipText,
|
||||||
|
raw = false,
|
||||||
}: SignatureFieldProps) => {
|
}: SignatureFieldProps) => {
|
||||||
const { executeActionAuthProcedure, isAuthRedirectRequired } = useRequiredDocumentAuthContext();
|
const { executeActionAuthProcedure, isAuthRedirectRequired } = useRequiredDocumentAuthContext();
|
||||||
|
|
||||||
@ -103,7 +106,7 @@ export const SigningFieldContainer = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<FieldRootContainer field={field}>
|
<FieldRootContainer raw={raw} field={field}>
|
||||||
{!field.inserted && !loading && (
|
{!field.inserted && !loading && (
|
||||||
<button
|
<button
|
||||||
type="submit"
|
type="submit"
|
||||||
|
|||||||
@ -18,6 +18,7 @@ export type FieldRootContainerProps = {
|
|||||||
export type FieldContainerPortalProps = {
|
export type FieldContainerPortalProps = {
|
||||||
field: Field;
|
field: Field;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
raw?: boolean;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -44,7 +45,7 @@ export function FieldContainerPortal({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function FieldRootContainer({ field, children }: FieldContainerPortalProps) {
|
export function FieldRootContainer({ field, children, raw = false }: FieldContainerPortalProps) {
|
||||||
const [isValidating, setIsValidating] = useState(false);
|
const [isValidating, setIsValidating] = useState(false);
|
||||||
|
|
||||||
const ref = React.useRef<HTMLDivElement>(null);
|
const ref = React.useRef<HTMLDivElement>(null);
|
||||||
@ -71,6 +72,7 @@ export function FieldRootContainer({ field, children }: FieldContainerPortalProp
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FieldContainerPortal field={field}>
|
<FieldContainerPortal field={field}>
|
||||||
|
{!raw && (
|
||||||
<Card
|
<Card
|
||||||
id={`field-${field.id}`}
|
id={`field-${field.id}`}
|
||||||
className={cn(
|
className={cn(
|
||||||
@ -86,6 +88,26 @@ export function FieldRootContainer({ field, children }: FieldContainerPortalProp
|
|||||||
{children}
|
{children}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{raw && (
|
||||||
|
<div
|
||||||
|
onClick={() => {
|
||||||
|
console.log('clickeddd');
|
||||||
|
}}
|
||||||
|
id={`field-${field.id}`}
|
||||||
|
className={cn(
|
||||||
|
'field-card-container bg-background relative z-20 h-full w-full transition-all',
|
||||||
|
{
|
||||||
|
'border-orange-300 ring-1 ring-orange-300': !field.inserted && isValidating,
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
ref={ref}
|
||||||
|
data-inserted={field.inserted ? 'true' : 'false'}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</FieldContainerPortal>
|
</FieldContainerPortal>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user