<!-- start pr-codex -->
## PR-Codex overview
This PR removes unnecessary files, updates type definitions, refactors contract-related components, and improves API handling.
### Detailed summary
- Removed several files related to publishing contracts and provider setup
- Updated type definitions and constants
- Refactored contract-related components for consistency
- Improved API handling and URL configurations
> The following files were skipped due to too many changes: `apps/dashboard/src/pages/explore/[category]/index.tsx`, `apps/dashboard/src/contract-ui/tabs/claim-conditions/components/claim-conditions-form/hooks.ts`, `apps/dashboard/src/app/(dashboard)/published-contract/[publisher]/[contract_id]/page.tsx`, `apps/dashboard/src/contract-ui/tabs/manage/components/moduleContractInfo.ts`, `apps/dashboard/src/constants/chains.ts`, `apps/dashboard/src/components/contract-components/contract-table/cells/description.tsx`, `apps/dashboard/src/contract-ui/tabs/claim-conditions/components/claim-conditions-form/index.tsx`, `apps/dashboard/src/components/contract-components/contract-publish-form/landing-fieldset.tsx`, `apps/dashboard/src/components/contract-components/contract-publish-form/factory-fieldset.tsx`, `apps/dashboard/src/app/(dashboard)/contracts/publish/[publish_uri]/page.tsx`, `apps/dashboard/src/components/explore/contract-card/index.tsx`, `apps/dashboard/src/components/contract-components/contract-publish-form/default-factory.tsx`, `apps/dashboard/src/components/contract-components/shared/contract-id-image.tsx`, `apps/dashboard/src/components/smart-wallets/AccountFactories/index.tsx`, `apps/dashboard/src/lib/sdk.ts`, `apps/dashboard/src/contract-ui/tabs/code/components/code-overview.tsx`, `apps/dashboard/src/components/contract-components/publisher/edit-profile.tsx`, `apps/dashboard/src/pages/profile/[profileAddress].tsx`, `apps/dashboard/src/contract-ui/tabs/claim-conditions/legacy-zod-schema.ts`, `apps/dashboard/src/contract-ui/tabs/manage/components/ModuleForm.tsx`, `apps/dashboard/src/components/contract-functions/contract-function.tsx`, `apps/dashboard/src/components/contract-components/hooks.ts`, `apps/dashboard/src/components/contract-components/contract-publish-form/index.tsx`
> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`
<!-- end pr-codex -->
269 lines
7.8 KiB
TypeScript
269 lines
7.8 KiB
TypeScript
import { thirdwebClient } from "@/constants/client";
|
|
import {
|
|
Box,
|
|
Flex,
|
|
FormControl,
|
|
Icon,
|
|
Input,
|
|
Textarea,
|
|
useDisclosure,
|
|
} from "@chakra-ui/react";
|
|
import { SiDiscord } from "@react-icons/all-files/si/SiDiscord";
|
|
import { SiGithub } from "@react-icons/all-files/si/SiGithub";
|
|
import { SiTwitter } from "@react-icons/all-files/si/SiTwitter";
|
|
import { useQueryClient } from "@tanstack/react-query";
|
|
import { FileInput } from "components/shared/FileInput";
|
|
import {
|
|
DASHBOARD_ENGINE_RELAYER_URL,
|
|
DASHBOARD_FORWARDER_ADDRESS,
|
|
} from "constants/misc";
|
|
import type { ProfileMetadata, ProfileMetadataInput } from "constants/schemas";
|
|
import { useTrack } from "hooks/analytics/useTrack";
|
|
import { useImageFileOrUrl } from "hooks/useImageFileOrUrl";
|
|
import { useTxNotifications } from "hooks/useTxNotifications";
|
|
import { useId } from "react";
|
|
import { useForm } from "react-hook-form";
|
|
import { BiImage } from "react-icons/bi";
|
|
import { FiEdit, FiGlobe } from "react-icons/fi";
|
|
import { HiPencilAlt } from "react-icons/hi";
|
|
import {
|
|
getContractPublisher,
|
|
setPublisherProfileUri,
|
|
} from "thirdweb/extensions/thirdweb";
|
|
import { useActiveAccount, useSendAndConfirmTransaction } from "thirdweb/react";
|
|
import { upload } from "thirdweb/storage";
|
|
import {
|
|
Button,
|
|
Drawer,
|
|
FormErrorMessage,
|
|
FormLabel,
|
|
Heading,
|
|
} from "tw-components";
|
|
import { MaskedAvatar } from "tw-components/masked-avatar";
|
|
|
|
interface EditProfileProps {
|
|
publisherProfile: ProfileMetadata;
|
|
}
|
|
|
|
export const EditProfile: React.FC<EditProfileProps> = ({
|
|
publisherProfile,
|
|
}) => {
|
|
const FORM_ID = useId();
|
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
|
|
|
const {
|
|
register,
|
|
handleSubmit,
|
|
setValue,
|
|
watch,
|
|
formState: { errors },
|
|
} = useForm<ProfileMetadataInput>({
|
|
defaultValues: publisherProfile,
|
|
values: publisherProfile,
|
|
});
|
|
|
|
const imageUrl = useImageFileOrUrl(watch("avatar"));
|
|
|
|
const address = useActiveAccount()?.address;
|
|
const queryClient = useQueryClient();
|
|
const sendTx = useSendAndConfirmTransaction({
|
|
gasless: {
|
|
experimentalChainlessSupport: true,
|
|
provider: "engine",
|
|
relayerUrl: DASHBOARD_ENGINE_RELAYER_URL,
|
|
relayerForwarderAddress: DASHBOARD_FORWARDER_ADDRESS,
|
|
},
|
|
});
|
|
|
|
const { onSuccess, onError } = useTxNotifications(
|
|
"Profile update successfully",
|
|
"Error updating profile",
|
|
);
|
|
|
|
const trackEvent = useTrack();
|
|
|
|
return (
|
|
<>
|
|
<Button
|
|
onClick={onOpen}
|
|
size="sm"
|
|
variant="outline"
|
|
leftIcon={<Icon as={FiEdit} />}
|
|
>
|
|
Edit Profile
|
|
</Button>
|
|
|
|
<form
|
|
id={FORM_ID}
|
|
onSubmit={handleSubmit((d) => {
|
|
if (!address) {
|
|
return;
|
|
}
|
|
trackEvent({
|
|
category: "profile",
|
|
action: "edit",
|
|
label: "attempt",
|
|
});
|
|
const tx = setPublisherProfileUri({
|
|
contract: getContractPublisher(thirdwebClient),
|
|
asyncParams: async () => {
|
|
return {
|
|
publisher: address,
|
|
uri: await upload({
|
|
files: [d],
|
|
client: thirdwebClient,
|
|
}),
|
|
};
|
|
},
|
|
});
|
|
sendTx.mutate(tx, {
|
|
onSuccess: async () => {
|
|
await queryClient.invalidateQueries({
|
|
queryKey: ["releaser-profile", address],
|
|
});
|
|
onSuccess();
|
|
trackEvent({
|
|
category: "profile",
|
|
action: "edit",
|
|
label: "success",
|
|
});
|
|
onClose();
|
|
},
|
|
onError: (error) => {
|
|
onError(error);
|
|
trackEvent({
|
|
category: "profile",
|
|
action: "edit",
|
|
label: "error",
|
|
error,
|
|
});
|
|
},
|
|
});
|
|
})}
|
|
>
|
|
<Drawer
|
|
isOpen={isOpen}
|
|
onClose={onClose}
|
|
allowPinchZoom
|
|
preserveScrollBarGap
|
|
size="lg"
|
|
header={{
|
|
children: <Heading size="title.md">Edit your profile</Heading>,
|
|
}}
|
|
footer={{
|
|
children: (
|
|
<Button
|
|
borderRadius="md"
|
|
position="relative"
|
|
role="group"
|
|
colorScheme="primary"
|
|
type="submit"
|
|
isLoading={sendTx.isPending}
|
|
form={FORM_ID}
|
|
>
|
|
Save
|
|
</Button>
|
|
),
|
|
}}
|
|
drawerBodyProps={{
|
|
gap: 6,
|
|
display: "flex",
|
|
flexDirection: "column",
|
|
overflowX: "hidden",
|
|
}}
|
|
>
|
|
<FormControl isInvalid={!!errors.avatar}>
|
|
<FormLabel>
|
|
<Flex gap={2}>
|
|
<Icon as={BiImage} boxSize={4} />
|
|
Avatar
|
|
</Flex>
|
|
</FormLabel>
|
|
<Box width={{ base: "auto", md: "250px" }}>
|
|
<FileInput
|
|
accept={{ "image/*": [] }}
|
|
value={imageUrl}
|
|
showUploadButton
|
|
setValue={(file) => setValue("avatar", file)}
|
|
className="border border-border rounded transition-all"
|
|
renderPreview={(fileUrl) => (
|
|
<MaskedAvatar w="100%" h="100%" src={fileUrl} />
|
|
)}
|
|
/>
|
|
</Box>
|
|
<FormErrorMessage>
|
|
{errors?.avatar?.message as unknown as string}
|
|
</FormErrorMessage>
|
|
</FormControl>
|
|
<FormControl isInvalid={!!errors.bio}>
|
|
<FormLabel>
|
|
<Flex gap={2}>
|
|
<Icon as={HiPencilAlt} boxSize={4} />
|
|
Bio
|
|
</Flex>
|
|
</FormLabel>
|
|
<Textarea
|
|
{...register("bio")}
|
|
autoFocus
|
|
placeholder="Tell us about yourself"
|
|
/>
|
|
<FormErrorMessage>{errors?.bio?.message}</FormErrorMessage>
|
|
</FormControl>
|
|
<FormControl isInvalid={!!errors.github}>
|
|
<FormLabel>
|
|
<Flex gap={2}>
|
|
<Icon as={SiGithub} boxSize={4} />
|
|
GitHub
|
|
</Flex>
|
|
</FormLabel>
|
|
<Input
|
|
{...register("github")}
|
|
placeholder="https://github.com/yourname"
|
|
/>
|
|
<FormErrorMessage>{errors?.github?.message}</FormErrorMessage>
|
|
</FormControl>
|
|
<FormControl isInvalid={!!errors.twitter}>
|
|
<FormLabel>
|
|
<Flex gap={2}>
|
|
<Icon as={SiTwitter} boxSize={4} />
|
|
Twitter
|
|
</Flex>
|
|
</FormLabel>
|
|
<Input
|
|
{...register("twitter")}
|
|
placeholder="https://twitter.com/yourname"
|
|
/>
|
|
<FormErrorMessage>{errors?.twitter?.message}</FormErrorMessage>
|
|
</FormControl>
|
|
<FormControl isInvalid={!!errors.website}>
|
|
<FormLabel>
|
|
<Flex gap={2}>
|
|
<Icon as={FiGlobe} boxSize={4} />
|
|
Website
|
|
</Flex>
|
|
</FormLabel>
|
|
<Input
|
|
{...register("website")}
|
|
placeholder="https://yourwebsite.com"
|
|
/>
|
|
<FormErrorMessage>{errors?.website?.message}</FormErrorMessage>
|
|
</FormControl>
|
|
<FormControl isInvalid={!!errors.discord}>
|
|
<FormLabel>
|
|
<Flex gap={2}>
|
|
<Icon as={SiDiscord} boxSize={4} />
|
|
Discord
|
|
</Flex>
|
|
</FormLabel>
|
|
<Input
|
|
{...register("discord")}
|
|
placeholder="https://discord.gg/yourserver"
|
|
/>
|
|
<FormErrorMessage>{errors?.discord?.message}</FormErrorMessage>
|
|
</FormControl>
|
|
</Drawer>
|
|
</form>
|
|
</>
|
|
);
|
|
};
|