Files
js/apps/dashboard/src/components/settings/Account/AccountForm.tsx
T
jnsdls 575c3e3141 react-query v4 -> v5 (#4600)
<!-- start pr-codex -->

## PR-Codex overview
This PR updates loading states in various components to use `isPending` instead of `isLoading`.

### Detailed summary
- Replaced `isLoading` with `isPending` in multiple components for loading state handling.

> The following files were skipped due to too many changes: `apps/dashboard/src/contract-ui/tabs/manage/components/InstalledModulesTable.tsx`, `apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayCustomers.ts`, `apps/dashboard/src/components/pay/PayConfig.tsx`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/server/chain-header.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/add-partner-form.client.tsx`, `apps/dashboard/src/components/pay/PayAnalytics/components/PaymentHistory.tsx`, `apps/dashboard/src/contract-ui/tabs/split/components/distribute-button.tsx`, `apps/dashboard/src/components/onboarding/LinkWallet.tsx`, `apps/dashboard/src/components/pay/PayAnalytics/components/TotalVolumePieChart.tsx`, `apps/dashboard/package.json`, `apps/dashboard/src/components/pay/PayAnalytics/hooks/usePayPurchases.ts`, `apps/dashboard/src/components/engine/configuration/local-config.tsx.tsx`, `apps/dashboard/src/components/settings/ApiKeys/Create/index.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/server/partners-table.tsx`, `apps/dashboard/src/contract-ui/components/solidity-inputs/string-input.tsx`, `apps/dashboard/src/components/settings/Account/Billing/index.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/update-partner-form.client.tsx`, `apps/dashboard/src/contract-ui/tabs/nfts/page.tsx`, `apps/dashboard/src/components/configure-networks/Form/IconUpload.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/hooks/use-create-ecosystem.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/create/components/client/create-ecosystem-form.client.tsx`, `apps/dashboard/src/components/engine/engine-instances-table.tsx`, `apps/dashboard/src/components/engine/contract-subscription/contract-subscriptions-table.tsx`, `apps/dashboard/src/components/pay/PayAnalytics/components/PayCustomersTable.tsx`, `apps/dashboard/src/pages/api/revalidate/publish.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-ecosystem.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-add-partner.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-delete-partner.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/hooks/use-update-partner.ts`, `apps/dashboard/src/app/(dashboard)/(chain)/[chain_id]/(chainPage)/components/client/live-stats.tsx`, `apps/dashboard/src/contract-ui/tabs/shared-components/marketplace-table.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/query/useQueryWithNetwork.ts`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/pay/components/webhooks.client.tsx`, `apps/dashboard/src/components/contract-components/tables/deployed-contracts.tsx`, `apps/dashboard/src/contract-ui/tabs/proposals/components/proposal.tsx`, `apps/dashboard/src/components/app-layouts/app.tsx`, `apps/dashboard/src/app/(dashboard)/dashboard/connect/ecosystem/[slug]/(active)/components/client/integration-permissions-toggle.client.tsx`, `apps/dashboard/src/app/account/settings/AccountSettingsPageUI.tsx`, `apps/dashboard/src/components/cmd-k-search/index.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useLoggedInUser.ts`, `apps/dashboard/src/components/contract-components/hooks.ts`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useRegistry.ts`, `apps/dashboard/src/contract-ui/tabs/manage/components/ModuleForm.tsx`, `apps/dashboard/src/app/team/[team_slug]/(team)/~/settings/general/GeneralSettingsPage.tsx`, `apps/dashboard/src/components/storage/your-files.tsx`, `apps/dashboard/src/components/contract-functions/interactive-abi-function.tsx`, `apps/dashboard/src/components/ipfs-upload/dropzone.tsx`, `apps/dashboard/src/core-ui/nft-drawer/useNftDrawerTabs.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useApi.ts`, `pnpm-lock.yaml`, `apps/dashboard/src/contract-ui/hooks/useRouteConfig.tsx`, `apps/dashboard/src/@3rdweb-sdk/react/hooks/useEngine.ts`

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->
2024-09-15 21:32:49 +00:00

259 lines
6.8 KiB
TypeScript

import { type Account, useUpdateAccount } from "@3rdweb-sdk/react/hooks/useApi";
import {
Flex,
FormControl,
HStack,
Input,
VStack,
useColorModeValue,
} from "@chakra-ui/react";
import { zodResolver } from "@hookform/resolvers/zod";
import { ManageBillingButton } from "components/settings/Account/Billing/ManageButton";
import { useTrack } from "hooks/analytics/useTrack";
import { useTxNotifications } from "hooks/useTxNotifications";
import { type ChangeEvent, useState } from "react";
import { useForm } from "react-hook-form";
import {
Button,
type ButtonProps,
Checkbox,
FormErrorMessage,
FormLabel,
Heading,
Text,
} from "tw-components";
import {
type AccountValidationSchema,
accountValidationSchema,
} from "./validations";
interface AccountFormProps {
account: Account;
horizontal?: boolean;
previewEnabled?: boolean;
showBillingButton?: boolean;
showSubscription?: boolean;
hideName?: boolean;
buttonProps?: ButtonProps;
buttonText?: string;
padded?: boolean;
trackingCategory?: string;
disableUnchanged?: boolean;
onSave?: (email: string) => void;
onDuplicateError?: (email: string) => void;
}
export const AccountForm: React.FC<AccountFormProps> = ({
account,
onSave,
onDuplicateError,
buttonProps,
buttonText = "Save",
horizontal = false,
previewEnabled = false,
hideName = false,
showBillingButton = false,
showSubscription = false,
disableUnchanged = false,
padded = true,
}) => {
const [isSubscribing, setIsSubscribing] = useState(
showSubscription && !!account.email?.length,
);
const trackEvent = useTrack();
const bg = useColorModeValue("backgroundCardHighlight", "transparent");
const form = useForm<AccountValidationSchema>({
resolver: zodResolver(accountValidationSchema),
defaultValues: {
name: account.name || "",
email: account.unconfirmedEmail || account.email || "",
},
values: {
name: account.name || "",
email: account.unconfirmedEmail || account.email || "",
},
});
const updateMutation = useUpdateAccount();
const { onSuccess, onError } = useTxNotifications(
"Billing account saved.",
"Failed to save your billing account.",
);
const handleSubmit = form.handleSubmit((values) => {
const formData = {
...values,
...(showSubscription
? {
subscribeToUpdates: isSubscribing,
}
: {}),
};
trackEvent({
category: "account",
action: "update",
label: "attempt",
data: formData,
});
updateMutation.mutate(formData, {
onSuccess: (data) => {
if (onSave) {
onSave(values.email);
}
onSuccess();
trackEvent({
category: "account",
action: "update",
label: "success",
data,
});
},
onError: (err) => {
const error = err as Error;
if (
onDuplicateError &&
error?.message.match(/email address already exists/)
) {
onDuplicateError(values.email);
} else {
onError(error);
}
trackEvent({
category: "account",
action: "update",
label: "error",
error,
fromOnboarding: !!onDuplicateError,
});
},
});
});
return (
<form onSubmit={handleSubmit}>
<VStack
alignItems="flex-start"
w="full"
gap={horizontal ? 6 : 8}
borderRadius="xl"
borderColor="borderColor"
borderWidth={padded ? 1 : 0}
bg={bg}
p={padded ? 6 : 0}
>
<Flex
gap={horizontal ? 4 : 8}
flexDir={horizontal ? "row" : "column"}
w="full"
>
<FormControl
isRequired
isInvalid={!!form.getFieldState("email", form.formState).error}
>
<FormLabel>Email</FormLabel>
{previewEnabled ? (
<Flex
borderRadius="md"
borderColor="borderColor"
borderWidth={1}
h={10}
px={3}
alignItems="center"
>
<Heading size="subtitle.sm">{form.getValues("email")}</Heading>
</Flex>
) : (
<Input
placeholder="[email protected]"
type="email"
{...form.register("email")}
/>
)}
{form.getFieldState("email", form.formState).error && (
<FormErrorMessage size="body.sm">
{form.getFieldState("email", form.formState).error?.message}
</FormErrorMessage>
)}
</FormControl>
{!hideName && (
<FormControl
isInvalid={!!form.getFieldState("name", form.formState).error}
>
<FormLabel>Name</FormLabel>
{previewEnabled ? (
<Flex
borderRadius="md"
borderColor="borderColor"
borderWidth={1}
h={10}
px={3}
alignItems="center"
>
<Heading size="subtitle.sm">{form.getValues("name")}</Heading>
</Flex>
) : (
<Input
placeholder="Company Inc."
type="text"
{...form.register("name")}
/>
)}
{form.getFieldState("name", form.formState).error && (
<FormErrorMessage size="body.sm">
{form.getFieldState("name", form.formState).error?.message}
</FormErrorMessage>
)}
</FormControl>
)}
{showSubscription && (
<Checkbox
defaultChecked
onChange={(e: ChangeEvent<HTMLInputElement>) =>
setIsSubscribing(e.target.checked)
}
>
<Text>Subscribe to new features and key product updates</Text>
</Checkbox>
)}
</Flex>
<HStack
justifyContent={showBillingButton ? "space-between" : "flex-end"}
w="full"
>
{showBillingButton && <ManageBillingButton account={account} />}
{!previewEnabled && (
<Button
{...buttonProps}
type="button"
onClick={handleSubmit}
colorScheme={buttonProps?.variant ? undefined : "blue"}
isDisabled={
updateMutation.isPending ||
(disableUnchanged && !form.formState.isDirty)
}
isLoading={updateMutation.isPending}
>
{buttonText}
</Button>
)}
</HStack>
</VStack>
</form>
);
};