Skip to content

Commit 04c7243

Browse files
committed
Dashboard: Migrate various components from chakra to tailwind #2 (#7749)
<!-- ## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes" If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000): ## Notes for the reviewer Anything important to call out? Be sure to also clarify these in your comments. ## How to test Unit tests, playground, etc. --> <!-- start pr-codex --> --- ## PR-Codex overview This PR focuses on refactoring components for better structure and performance, particularly in the forms and tables related to NFTs. It also removes unused components and improves the user experience with updated UI elements and error handling. ### Detailed summary - Removed `FormHelperText` and `FormErrorMessage` from `chakra/form`. - Refactored `NFTSharedMetadataButton` to use a function component instead of a React.FC. - Updated `ContractPermissionsPage` to use a function component and improved prop handling. - Replaced `FormControl` and `FormErrorMessage` with a new form structure in `NFTRevealButton`. - Refactored `SharedMetadataForm` to enhance form handling and error messaging. - Updated `NFTGetAllTable` to streamline pagination and data fetching logic. - Removed unused imports and components to clean up the codebase. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` <!-- end pr-codex --> <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Refactor** * Updated multiple NFT dashboard components to use a new custom UI library, replacing Chakra UI and simplifying form and table logic. * Improved form validation and error handling with integrated schema validation and toast notifications. * Streamlined table rendering and pagination for NFT listings with a more explicit and user-friendly approach. * Simplified permission and metadata management pages for improved clarity and consistency. * **Chores** * Removed deprecated Chakra UI-based components and helper utilities, including custom link and button components no longer in use. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
1 parent 66cba85 commit 04c7243

File tree

8 files changed

+536
-739
lines changed

8 files changed

+536
-739
lines changed
Lines changed: 126 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,33 @@
11
"use client";
22

3-
import { FormControl, Input, Select } from "@chakra-ui/react";
4-
import { FormErrorMessage, FormLabel } from "chakra/form";
3+
import { zodResolver } from "@hookform/resolvers/zod";
54
import { EyeIcon } from "lucide-react";
65
import { useState } from "react";
76
import { useForm } from "react-hook-form";
87
import { toast } from "sonner";
98
import type { ThirdwebContract } from "thirdweb";
109
import { getBatchesToReveal, reveal } from "thirdweb/extensions/erc721";
1110
import { useReadContract, useSendAndConfirmTransaction } from "thirdweb/react";
11+
import * as z from "zod";
1212
import { MinterOnly } from "@/components/contracts/roles/minter-only";
1313
import { TransactionButton } from "@/components/tx-button";
1414
import { Button } from "@/components/ui/button";
15+
import {
16+
Form,
17+
FormControl,
18+
FormField,
19+
FormItem,
20+
FormLabel,
21+
FormMessage,
22+
} from "@/components/ui/form";
23+
import { Input } from "@/components/ui/input";
24+
import {
25+
Select,
26+
SelectContent,
27+
SelectItem,
28+
SelectTrigger,
29+
SelectValue,
30+
} from "@/components/ui/select";
1531
import {
1632
Sheet,
1733
SheetContent,
@@ -20,29 +36,35 @@ import {
2036
SheetTrigger,
2137
} from "@/components/ui/sheet";
2238
import { ToolTipLabel } from "@/components/ui/tooltip";
39+
import { parseError } from "@/utils/errorParser";
2340

24-
interface NFTRevealButtonProps {
25-
contract: ThirdwebContract;
26-
isLoggedIn: boolean;
27-
}
41+
const revealFormSchema = z.object({
42+
batchId: z.string().min(1, "Please select a batch"),
43+
password: z.string().min(1, "Password is required"),
44+
});
2845

29-
const REVEAL_FORM_ID = "reveal-form";
46+
type RevealFormData = z.infer<typeof revealFormSchema>;
3047

31-
export const NFTRevealButton: React.FC<NFTRevealButtonProps> = ({
48+
export function NFTRevealButton({
3249
contract,
3350
isLoggedIn,
34-
}) => {
51+
}: {
52+
contract: ThirdwebContract;
53+
isLoggedIn: boolean;
54+
}) {
3555
const batchesQuery = useReadContract(getBatchesToReveal, {
3656
contract,
3757
});
3858

3959
const sendTxMutation = useSendAndConfirmTransaction();
4060

41-
const {
42-
register,
43-
handleSubmit,
44-
formState: { errors, isDirty },
45-
} = useForm<{ batchId: string; password: string }>();
61+
const form = useForm<RevealFormData>({
62+
resolver: zodResolver(revealFormSchema),
63+
defaultValues: {
64+
batchId: "",
65+
password: "",
66+
},
67+
});
4668

4769
const [open, setOpen] = useState(false);
4870

@@ -67,6 +89,27 @@ export const NFTRevealButton: React.FC<NFTRevealButtonProps> = ({
6789
);
6890
}
6991

92+
const onSubmit = async (data: RevealFormData) => {
93+
const tx = reveal({
94+
batchId: BigInt(data.batchId),
95+
contract,
96+
password: data.password,
97+
});
98+
99+
await sendTxMutation.mutateAsync(tx, {
100+
onError: (error) => {
101+
toast.error("Failed to reveal batch", {
102+
description: parseError(error),
103+
});
104+
console.error(error);
105+
},
106+
onSuccess: () => {
107+
toast.success("Batch revealed successfully");
108+
setOpen(false);
109+
},
110+
});
111+
};
112+
70113
return (
71114
<MinterOnly contract={contract}>
72115
<Sheet onOpenChange={setOpen} open={open}>
@@ -75,80 +118,80 @@ export const NFTRevealButton: React.FC<NFTRevealButtonProps> = ({
75118
<EyeIcon className="size-4" /> Reveal NFTs
76119
</Button>
77120
</SheetTrigger>
78-
<SheetContent className="w-full overflow-y-auto sm:min-w-[540px] lg:min-w-[700px]">
121+
<SheetContent className="!w-full lg:!max-w-lg">
79122
<SheetHeader>
80123
<SheetTitle className="text-left">Reveal batch</SheetTitle>
81124
</SheetHeader>
82-
<form
83-
className="mt-10 flex flex-col gap-6"
84-
id={REVEAL_FORM_ID}
85-
onSubmit={handleSubmit((data) => {
86-
const tx = reveal({
87-
batchId: BigInt(data.batchId),
88-
contract,
89-
password: data.password,
90-
});
91-
92-
const promise = sendTxMutation.mutateAsync(tx, {
93-
onError: (error) => {
94-
console.error(error);
95-
},
96-
onSuccess: () => {
97-
setOpen(false);
98-
},
99-
});
100-
101-
toast.promise(promise, {
102-
error: "Failed to reveal batch",
103-
loading: "Revealing batch",
104-
success: "Batch revealed successfully",
105-
});
106-
})}
107-
>
108-
<FormControl isInvalid={!!errors.password} isRequired mr={4}>
109-
<FormLabel>Select a batch</FormLabel>
110-
<Select {...register("batchId")} autoFocus>
111-
{batchesQuery.data.map((batch) => (
112-
<option
113-
disabled={batch.batchUri === "0x"}
114-
key={batch.batchId.toString()}
115-
value={batch.batchId.toString()}
116-
>
117-
{batch.placeholderMetadata?.name ||
118-
batch.batchId.toString()}{" "}
119-
{batch.batchUri === "0x" && "(REVEALED)"}
120-
</option>
121-
))}
122-
</Select>
123-
<FormErrorMessage>{errors?.password?.message}</FormErrorMessage>
124-
</FormControl>
125-
<FormControl isInvalid={!!errors.password} isRequired mr={4}>
126-
<FormLabel>Password</FormLabel>
127-
<Input
128-
{...register("password")}
129-
autoFocus
130-
placeholder="The one you used to upload this batch"
131-
type="password"
132-
/>
133-
<FormErrorMessage>{errors?.password?.message}</FormErrorMessage>
134-
</FormControl>
135-
</form>
136-
<div className="mt-4 flex justify-end">
137-
<TransactionButton
138-
client={contract.client}
139-
disabled={!isDirty}
140-
form={REVEAL_FORM_ID}
141-
isLoggedIn={isLoggedIn}
142-
isPending={sendTxMutation.isPending}
143-
transactionCount={1}
144-
txChainID={contract.chain.id}
145-
type="submit"
125+
<Form {...form}>
126+
<form
127+
className="mt-4 space-y-6"
128+
onSubmit={form.handleSubmit(onSubmit)}
146129
>
147-
Reveal NFTs
148-
</TransactionButton>
149-
</div>
130+
<FormField
131+
control={form.control}
132+
name="batchId"
133+
render={({ field }) => (
134+
<FormItem>
135+
<FormLabel>Select a batch</FormLabel>
136+
<Select onValueChange={field.onChange} value={field.value}>
137+
<FormControl>
138+
<SelectTrigger className="bg-card">
139+
<SelectValue placeholder="Select a batch" />
140+
</SelectTrigger>
141+
</FormControl>
142+
<SelectContent>
143+
{batchesQuery.data.map((batch) => (
144+
<SelectItem
145+
disabled={batch.batchUri === "0x"}
146+
key={batch.batchId.toString()}
147+
value={batch.batchId.toString()}
148+
>
149+
{batch.placeholderMetadata?.name ||
150+
batch.batchId.toString()}{" "}
151+
{batch.batchUri === "0x" && "(REVEALED)"}
152+
</SelectItem>
153+
))}
154+
</SelectContent>
155+
</Select>
156+
<FormMessage />
157+
</FormItem>
158+
)}
159+
/>
160+
<FormField
161+
control={form.control}
162+
name="password"
163+
render={({ field }) => (
164+
<FormItem>
165+
<FormLabel>Password</FormLabel>
166+
<FormControl>
167+
<Input
168+
{...field}
169+
placeholder="The one you used to upload this batch"
170+
type="password"
171+
className="bg-card"
172+
/>
173+
</FormControl>
174+
<FormMessage />
175+
</FormItem>
176+
)}
177+
/>
178+
179+
<div className="flex justify-end">
180+
<TransactionButton
181+
client={contract.client}
182+
isLoggedIn={isLoggedIn}
183+
isPending={sendTxMutation.isPending}
184+
transactionCount={1}
185+
txChainID={contract.chain.id}
186+
type="submit"
187+
>
188+
Reveal NFTs
189+
</TransactionButton>
190+
</div>
191+
</form>
192+
</Form>
150193
</SheetContent>
151194
</Sheet>
152195
</MinterOnly>
153196
);
154-
};
197+
}

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/nfts/components/shared-metadata-button.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,24 +13,23 @@ import {
1313
} from "@/components/ui/sheet";
1414
import { SharedMetadataForm } from "./shared-metadata-form";
1515

16-
interface NFTSharedMetadataButtonProps {
16+
export function NFTSharedMetadataButton({
17+
contract,
18+
isLoggedIn,
19+
}: {
1720
contract: ThirdwebContract;
1821
isLoggedIn: boolean;
19-
}
20-
21-
export const NFTSharedMetadataButton: React.FC<
22-
NFTSharedMetadataButtonProps
23-
> = ({ contract, isLoggedIn, ...restButtonProps }) => {
22+
}) {
2423
const [open, setOpen] = useState(false);
2524
return (
2625
<MinterOnly contract={contract}>
2726
<Sheet onOpenChange={setOpen} open={open}>
2827
<SheetTrigger asChild>
29-
<Button className="gap-2" variant="primary" {...restButtonProps}>
28+
<Button className="gap-2" variant="primary">
3029
<PlusIcon className="size-5" /> Set NFT Metadata
3130
</Button>
3231
</SheetTrigger>
33-
<SheetContent className="w-full overflow-y-auto sm:min-w-[540px] lg:min-w-[700px]">
32+
<SheetContent className="!w-full lg:!max-w-2xl overflow-auto">
3433
<SheetHeader>
3534
<SheetTitle className="text-left">Set NFT Metadata</SheetTitle>
3635
</SheetHeader>
@@ -43,4 +42,4 @@ export const NFTSharedMetadataButton: React.FC<
4342
</Sheet>
4443
</MinterOnly>
4544
);
46-
};
45+
}

0 commit comments

Comments
 (0)