diff --git a/.eslintrc.cjs b/.eslintrc.cjs index ed6ecc0ac..455860ea1 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -5,6 +5,7 @@ module.exports = { rules: { '@next/next/no-img-element': 'off', 'no-unreachable': 'error', + 'react-hooks/exhaustive-deps': 'off', }, settings: { next: { diff --git a/apps/remix/app/components/dialogs/team-email-add-dialog.tsx b/apps/remix/app/components/dialogs/team-email-add-dialog.tsx index 2aee969ca..161c2c0eb 100644 --- a/apps/remix/app/components/dialogs/team-email-add-dialog.tsx +++ b/apps/remix/app/components/dialogs/team-email-add-dialog.tsx @@ -7,6 +7,7 @@ import { Trans } from '@lingui/react/macro'; import type * as DialogPrimitive from '@radix-ui/react-dialog'; import { Plus } from 'lucide-react'; import { useForm } from 'react-hook-form'; +import { useRevalidator } from 'react-router'; import type { z } from 'zod'; import { AppError, AppErrorCode } from '@documenso/lib/errors/app-error'; @@ -50,6 +51,7 @@ export const TeamEmailAddDialog = ({ teamId, trigger, ...props }: TeamEmailAddDi const { _ } = useLingui(); const { toast } = useToast(); + const { revalidate } = useRevalidator(); const form = useForm({ resolver: zodResolver(ZCreateTeamEmailFormSchema), @@ -76,7 +78,7 @@ export const TeamEmailAddDialog = ({ teamId, trigger, ...props }: TeamEmailAddDi duration: 5000, }); - // router.refresh(); // Todo + await revalidate(); setOpen(false); } catch (err) { diff --git a/apps/remix/app/components/dialogs/team-email-delete-dialog.tsx b/apps/remix/app/components/dialogs/team-email-delete-dialog.tsx index b9675f4a5..ec050961c 100644 --- a/apps/remix/app/components/dialogs/team-email-delete-dialog.tsx +++ b/apps/remix/app/components/dialogs/team-email-delete-dialog.tsx @@ -4,6 +4,7 @@ import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import type { Prisma } from '@prisma/client'; +import { useRevalidator } from 'react-router'; import { formatAvatarUrl } from '@documenso/lib/utils/avatars'; import { extractInitials } from '@documenso/lib/utils/recipient-formatter'; @@ -44,6 +45,7 @@ export const TeamEmailDeleteDialog = ({ trigger, teamName, team }: TeamEmailDele const { _ } = useLingui(); const { toast } = useToast(); + const { revalidate } = useRevalidator(); const { mutateAsync: deleteTeamEmail, isPending: isDeletingTeamEmail } = trpc.team.deleteTeamEmail.useMutation({ @@ -92,7 +94,7 @@ export const TeamEmailDeleteDialog = ({ trigger, teamName, team }: TeamEmailDele await deleteTeamEmailVerification({ teamId: team.id }); } - // router.refresh(); // Todo + await revalidate(); }; return ( diff --git a/apps/remix/app/components/dialogs/team-email-update-dialog.tsx b/apps/remix/app/components/dialogs/team-email-update-dialog.tsx index 6958dc64d..bde700949 100644 --- a/apps/remix/app/components/dialogs/team-email-update-dialog.tsx +++ b/apps/remix/app/components/dialogs/team-email-update-dialog.tsx @@ -7,6 +7,7 @@ import { Trans } from '@lingui/react/macro'; import type { TeamEmail } from '@prisma/client'; import type * as DialogPrimitive from '@radix-ui/react-dialog'; import { useForm } from 'react-hook-form'; +import { useRevalidator } from 'react-router'; import { z } from 'zod'; import { trpc } from '@documenso/trpc/react'; @@ -51,6 +52,7 @@ export const TeamEmailUpdateDialog = ({ const { _ } = useLingui(); const { toast } = useToast(); + const { revalidate } = useRevalidator(); const form = useForm({ resolver: zodResolver(ZUpdateTeamEmailFormSchema), @@ -76,7 +78,7 @@ export const TeamEmailUpdateDialog = ({ duration: 5000, }); - // router.refresh(); // Todo + await revalidate(); setOpen(false); } catch (err) { diff --git a/apps/remix/app/components/dialogs/team-member-invite-dialog.tsx b/apps/remix/app/components/dialogs/team-member-invite-dialog.tsx index d7986b199..dac4f8fce 100644 --- a/apps/remix/app/components/dialogs/team-member-invite-dialog.tsx +++ b/apps/remix/app/components/dialogs/team-member-invite-dialog.tsx @@ -46,9 +46,9 @@ import { import { Tabs, TabsContent, TabsList, TabsTrigger } from '@documenso/ui/primitives/tabs'; import { useToast } from '@documenso/ui/primitives/use-toast'; +import { useCurrentTeam } from '~/providers/team'; + export type TeamMemberInviteDialogProps = { - currentUserTeamRole: TeamMemberRole; - teamId: number; trigger?: React.ReactNode; } & Omit; @@ -95,12 +95,7 @@ const ZImportTeamMemberSchema = z.array( }), ); -export const TeamMemberInviteDialog = ({ - currentUserTeamRole, - teamId, - trigger, - ...props -}: TeamMemberInviteDialogProps) => { +export const TeamMemberInviteDialog = ({ trigger, ...props }: TeamMemberInviteDialogProps) => { const [open, setOpen] = useState(false); const fileInputRef = useRef(null); const [invitationType, setInvitationType] = useState('INDIVIDUAL'); @@ -108,6 +103,8 @@ export const TeamMemberInviteDialog = ({ const { _ } = useLingui(); const { toast } = useToast(); + const team = useCurrentTeam(); + const form = useForm({ resolver: zodResolver(ZInviteTeamMembersFormSchema), defaultValues: { @@ -141,7 +138,7 @@ export const TeamMemberInviteDialog = ({ const onFormSubmit = async ({ invitations }: TInviteTeamMembersFormSchema) => { try { await createTeamMemberInvites({ - teamId, + teamId: team.id, invitations, }); @@ -203,7 +200,7 @@ export const TeamMemberInviteDialog = ({ setInvitationType('INDIVIDUAL'); } catch (err) { - console.error(err.message); + console.error(err); toast({ title: _(msg`Something went wrong`), @@ -324,11 +321,13 @@ export const TeamMemberInviteDialog = ({ - {TEAM_MEMBER_ROLE_HIERARCHY[currentUserTeamRole].map((role) => ( - - {_(TEAM_MEMBER_ROLE_MAP[role]) ?? role} - - ))} + {TEAM_MEMBER_ROLE_HIERARCHY[team.currentTeamMember.role].map( + (role) => ( + + {_(TEAM_MEMBER_ROLE_MAP[role]) ?? role} + + ), + )} diff --git a/apps/remix/app/components/dialogs/team-transfer-dialog.tsx b/apps/remix/app/components/dialogs/team-transfer-dialog.tsx index 6205edcb1..8cc5cf1f1 100644 --- a/apps/remix/app/components/dialogs/team-transfer-dialog.tsx +++ b/apps/remix/app/components/dialogs/team-transfer-dialog.tsx @@ -6,6 +6,7 @@ import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { Loader } from 'lucide-react'; import { useForm } from 'react-hook-form'; +import { useRevalidator } from 'react-router'; import { z } from 'zod'; import { IS_BILLING_ENABLED } from '@documenso/lib/constants/app'; @@ -56,6 +57,7 @@ export const TeamTransferDialog = ({ const { _ } = useLingui(); const { toast } = useToast(); + const { revalidate } = useRevalidator(); const { mutateAsync: requestTeamOwnershipTransfer } = trpc.team.requestTeamOwnershipTransfer.useMutation(); @@ -98,7 +100,7 @@ export const TeamTransferDialog = ({ clearPaymentMethods, }); - // router.refresh(); // Todo + await revalidate(); toast({ title: _(msg`Success`), diff --git a/apps/remix/app/components/dialogs/template-direct-link-dialog.tsx b/apps/remix/app/components/dialogs/template-direct-link-dialog.tsx index 2c05cb338..3c1bd9c8a 100644 --- a/apps/remix/app/components/dialogs/template-direct-link-dialog.tsx +++ b/apps/remix/app/components/dialogs/template-direct-link-dialog.tsx @@ -10,7 +10,7 @@ import { type TemplateDirectLink, } from '@prisma/client'; import { CircleDotIcon, CircleIcon, ClipboardCopyIcon, InfoIcon, LoaderIcon } from 'lucide-react'; -import { Link } from 'react-router'; +import { Link, useRevalidator } from 'react-router'; import { P, match } from 'ts-pattern'; import { useLimits } from '@documenso/ee/server-only/limits/provider/client'; @@ -64,6 +64,7 @@ export const TemplateDirectLinkDialog = ({ const { toast } = useToast(); const { quota, remaining } = useLimits(); const { _ } = useLingui(); + const { revalidate } = useRevalidator(); const [, copy] = useCopyToClipboard(); @@ -84,7 +85,9 @@ export const TemplateDirectLinkDialog = ({ isPending: isCreatingTemplateDirectLink, reset: resetCreateTemplateDirectLink, } = trpcReact.template.createTemplateDirectLink.useMutation({ - onSuccess: (data) => { + onSuccess: async (data) => { + await revalidate(); + setToken(data.token); setIsEnabled(data.enabled); setCurrentStep('MANAGE'); @@ -102,7 +105,9 @@ export const TemplateDirectLinkDialog = ({ const { mutateAsync: toggleTemplateDirectLink, isPending: isTogglingTemplateAccess } = trpcReact.template.toggleTemplateDirectLink.useMutation({ - onSuccess: (data) => { + onSuccess: async (data) => { + await revalidate(); + const enabledDescription = msg`Direct link signing has been enabled`; const disabledDescription = msg`Direct link signing has been disabled`; @@ -125,7 +130,9 @@ export const TemplateDirectLinkDialog = ({ const { mutateAsync: deleteTemplateDirectLink, isPending: isDeletingTemplateDirectLink } = trpcReact.template.deleteTemplateDirectLink.useMutation({ - onSuccess: () => { + onSuccess: async () => { + await revalidate(); + onOpenChange(false); setToken(null); diff --git a/apps/remix/app/components/forms/2fa/disable-authenticator-app-dialog.tsx b/apps/remix/app/components/forms/2fa/disable-authenticator-app-dialog.tsx index b4d623c0c..406d4c229 100644 --- a/apps/remix/app/components/forms/2fa/disable-authenticator-app-dialog.tsx +++ b/apps/remix/app/components/forms/2fa/disable-authenticator-app-dialog.tsx @@ -6,6 +6,7 @@ import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { flushSync } from 'react-dom'; import { useForm } from 'react-hook-form'; +import { useRevalidator } from 'react-router'; import { z } from 'zod'; import { trpc } from '@documenso/trpc/react'; @@ -41,6 +42,7 @@ export type TDisable2FAForm = z.infer; export const DisableAuthenticatorAppDialog = () => { const { _ } = useLingui(); const { toast } = useToast(); + const { revalidate } = useRevalidator(); const [isOpen, setIsOpen] = useState(false); const [twoFactorDisableMethod, setTwoFactorDisableMethod] = useState<'totp' | 'backup'>('totp'); @@ -92,8 +94,7 @@ export const DisableAuthenticatorAppDialog = () => { onCloseTwoFactorDisableDialog(); }); - // Todo - // router.refresh(); + await revalidate(); } catch (_err) { toast({ title: _(msg`Unable to disable two-factor authentication`), diff --git a/apps/remix/app/components/forms/2fa/enable-authenticator-app-dialog.tsx b/apps/remix/app/components/forms/2fa/enable-authenticator-app-dialog.tsx index 6d7ffb345..5fdd2c3b7 100644 --- a/apps/remix/app/components/forms/2fa/enable-authenticator-app-dialog.tsx +++ b/apps/remix/app/components/forms/2fa/enable-authenticator-app-dialog.tsx @@ -5,6 +5,7 @@ import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { useForm } from 'react-hook-form'; +import { useRevalidator } from 'react-router'; import { renderSVG } from 'uqr'; import { z } from 'zod'; @@ -47,6 +48,7 @@ export type EnableAuthenticatorAppDialogProps = { export const EnableAuthenticatorAppDialog = ({ onSuccess }: EnableAuthenticatorAppDialogProps) => { const { _ } = useLingui(); const { toast } = useToast(); + const { revalidate } = useRevalidator(); const [isOpen, setIsOpen] = useState(false); const [recoveryCodes, setRecoveryCodes] = useState(null); @@ -128,8 +130,7 @@ export const EnableAuthenticatorAppDialog = ({ onSuccess }: EnableAuthenticatorA if (!isOpen && recoveryCodes && recoveryCodes.length > 0) { setRecoveryCodes(null); - // Todo - // router.refresh(); + void revalidate(); } // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/apps/remix/app/components/forms/profile.tsx b/apps/remix/app/components/forms/profile.tsx index cd1a0af73..c5e179e15 100644 --- a/apps/remix/app/components/forms/profile.tsx +++ b/apps/remix/app/components/forms/profile.tsx @@ -3,6 +3,7 @@ import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; import { Trans } from '@lingui/react/macro'; import { useForm } from 'react-hook-form'; +import { useRevalidator } from 'react-router'; import { z } from 'zod'; import { useSession } from '@documenso/lib/client-only/providers/session'; @@ -42,6 +43,7 @@ export const ProfileForm = ({ className }: ProfileFormProps) => { const { _ } = useLingui(); const { toast } = useToast(); const { user } = useSession(); + const { revalidate } = useRevalidator(); const form = useForm({ values: { @@ -68,7 +70,7 @@ export const ProfileForm = ({ className }: ProfileFormProps) => { duration: 5000, }); - // router.refresh(); // Todo + await revalidate(); } catch (err) { toast({ title: _(msg`An unknown error occurred`), diff --git a/apps/remix/app/components/forms/signup.tsx b/apps/remix/app/components/forms/signup.tsx index 3dc86cf6e..ae00931a3 100644 --- a/apps/remix/app/components/forms/signup.tsx +++ b/apps/remix/app/components/forms/signup.tsx @@ -168,7 +168,6 @@ export const SignUpForm = ({ }; const onNextClick = async () => { - console.log('hello-world'); const valid = await form.trigger(['name', 'email', 'password', 'signature']); if (valid) { diff --git a/apps/remix/app/components/forms/team-update-form.tsx b/apps/remix/app/components/forms/team-update-form.tsx index 2eaf5d30b..a5165e30f 100644 --- a/apps/remix/app/components/forms/team-update-form.tsx +++ b/apps/remix/app/components/forms/team-update-form.tsx @@ -73,7 +73,7 @@ export const TeamUpdateForm = ({ teamId, teamName, teamUrl }: UpdateTeamDialogPr }); if (url !== teamUrl) { - await navigate(`${NEXT_PUBLIC_WEBAPP_URL()}/t/${url}/settings`); + await navigate(`/t/${url}/settings`); } } catch (err) { const error = AppError.parseError(err); diff --git a/apps/remix/app/components/general/document-signing/document-signing-auto-sign.tsx b/apps/remix/app/components/general/document-signing/document-signing-auto-sign.tsx index 495d62ffd..cb90525a7 100644 --- a/apps/remix/app/components/general/document-signing/document-signing-auto-sign.tsx +++ b/apps/remix/app/components/general/document-signing/document-signing-auto-sign.tsx @@ -1,4 +1,4 @@ -import { useState, useTransition } from 'react'; +import { useState } from 'react'; import { msg } from '@lingui/core/macro'; import { useLingui } from '@lingui/react'; @@ -6,6 +6,7 @@ import { Plural, Trans } from '@lingui/react/macro'; import type { Field, Recipient } from '@prisma/client'; import { FieldType } from '@prisma/client'; import { useForm } from 'react-hook-form'; +import { useRevalidator } from 'react-router'; import { P, match } from 'ts-pattern'; import { unsafe_useEffectOnce } from '@documenso/lib/client-only/hooks/use-effect-once'; @@ -60,12 +61,12 @@ export type DocumentSigningAutoSignProps = { export const DocumentSigningAutoSign = ({ recipient, fields }: DocumentSigningAutoSignProps) => { const { _ } = useLingui(); const { toast } = useToast(); + const { revalidate } = useRevalidator(); const { email, fullName } = useRequiredDocumentSigningContext(); const { derivedRecipientActionAuth } = useRequiredDocumentSigningAuthContext(); const [open, setOpen] = useState(false); - const [isPending, startTransition] = useTransition(); const form = useForm(); @@ -153,12 +154,7 @@ export const DocumentSigningAutoSign = ({ recipient, fields }: DocumentSigningAu }); } - startTransition(() => { - // Todo - // router.refresh(); - - setOpen(false); - }); + await revalidate(); }; unsafe_useEffectOnce(() => { @@ -219,7 +215,7 @@ export const DocumentSigningAutoSign = ({ recipient, fields }: DocumentSigningAu