Skip to content

Commit 27fd53c

Browse files
committed
Dashboard: Migrate Claim condition components from chakra to tailwind
1 parent 11d9f3e commit 27fd53c

23 files changed

+648
-910
lines changed

apps/dashboard/public/assets/examples/snapshot-with-maxclaimable.csv

Lines changed: 0 additions & 3 deletions
This file was deleted.

apps/dashboard/public/assets/examples/snapshot-with-overrides.csv

Lines changed: 0 additions & 3 deletions
This file was deleted.

apps/dashboard/public/assets/examples/snapshot.csv

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 31 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
"use client";
2-
import { ArrowDownToLineIcon } from "lucide-react";
2+
import { ArrowDownToLineIcon, FileTextIcon } from "lucide-react";
33
import { Button } from "@/components/ui/button";
44
import { CodeClient } from "@/components/ui/code/code.client";
55
import { handleDownload } from "../download-file-button";
@@ -10,27 +10,36 @@ export function DownloadableCode(props: {
1010
fileNameWithExtension: string;
1111
}) {
1212
return (
13-
<div className="!my-3 relative">
14-
<CodeClient
15-
code={props.code}
16-
lang={props.lang}
17-
scrollableClassName="max-h-[300px] bg-background"
18-
/>
19-
20-
<Button
21-
className="absolute top-3.5 right-14 mt-[1px] h-auto bg-background p-2"
22-
onClick={() => {
23-
handleDownload({
24-
fileContent: props.code,
25-
fileFormat: props.lang === "csv" ? "text/csv" : "application/json",
26-
fileNameWithExtension: props.fileNameWithExtension,
27-
});
28-
}}
29-
size="sm"
30-
variant="outline"
31-
>
32-
<ArrowDownToLineIcon className="size-3" />
33-
</Button>
13+
<div className="!my-5 bg-card">
14+
<p className="text-sm text-muted-foreground border border-b-0 px-4 py-3 pr-3.5 rounded-lg rounded-b-none flex items-center justify-between">
15+
<span className="flex items-center gap-1.5">
16+
<FileTextIcon className="size-3.5" />
17+
{props.fileNameWithExtension}
18+
</span>
19+
<Button
20+
className="h-auto bg-background p-2"
21+
onClick={() => {
22+
handleDownload({
23+
fileContent: props.code,
24+
fileFormat:
25+
props.lang === "csv" ? "text/csv" : "application/json",
26+
fileNameWithExtension: props.fileNameWithExtension,
27+
});
28+
}}
29+
size="sm"
30+
variant="outline"
31+
>
32+
<ArrowDownToLineIcon className="size-3" />
33+
</Button>
34+
</p>
35+
<div className="relative">
36+
<CodeClient
37+
code={props.code}
38+
lang={props.lang}
39+
scrollableClassName="max-h-[300px] bg-background bg-card"
40+
className="rounded-t-none"
41+
/>
42+
</div>
3443
</div>
3544
);
3645
}

apps/dashboard/src/@/components/blocks/drop-zone/drop-zone.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export function DropZone(props: {
2626
return (
2727
<div
2828
className={cn(
29-
"flex cursor-pointer items-center justify-center rounded-md border border-dashed bg-card py-10 hover:border-active-border",
29+
"flex cursor-pointer items-center justify-center rounded-md border border-dashed bg-card py-10 hover:border-active-border px-4",
3030
props.isError &&
3131
"border-red-500 bg-red-200/30 text-red-500 hover:border-red-600 dark:border-red-900 dark:bg-red-900/30 dark:hover:border-red-800",
3232
props.className,

apps/dashboard/src/@/components/tx-button/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ type TransactionButtonProps = Omit<ButtonProps, "variant"> & {
2828
transactionCount: number | undefined; // support for unknown number of tx count
2929
isPending: boolean;
3030
txChainID: number;
31-
variant?: "destructive" | "primary" | "default";
31+
variant?: "destructive" | "primary" | "default" | "outline";
3232
isLoggedIn: boolean;
3333
checkBalance?: boolean;
3434
client: ThirdwebClient;
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,40 @@
1-
import { Box, Flex } from "@chakra-ui/react";
21
import { NATIVE_TOKEN_ADDRESS } from "thirdweb";
32
import { CurrencySelector } from "@/components/blocks/CurrencySelector";
3+
import { FormFieldSetup } from "@/components/blocks/FormFieldSetup";
4+
import { cn } from "@/lib/utils";
45
import { PriceInput } from "../../price-input";
56
import { useClaimConditionsFormContext } from "..";
6-
import { CustomFormControl } from "../common";
77

88
/**
99
* Allows the user to select how much they want to charge to claim each NFT
1010
*/
1111
export const ClaimPriceInput = (props: { contractChainId: number }) => {
12-
const {
13-
formDisabled,
14-
isErc20,
15-
form,
16-
phaseIndex,
17-
field,
18-
isColumn,
19-
claimConditionType,
20-
} = useClaimConditionsFormContext();
12+
const { formDisabled, isErc20, form, phaseIndex, field, claimConditionType } =
13+
useClaimConditionsFormContext();
2114

2215
if (claimConditionType === "creator") {
2316
return null;
2417
}
2518

2619
return (
27-
<CustomFormControl
28-
disabled={formDisabled}
29-
error={
20+
<FormFieldSetup
21+
isRequired={false}
22+
errorMessage={
3023
form.getFieldState(`phases.${phaseIndex}.price`, form.formState).error
24+
?.message
3125
}
3226
label={`How much do you want to charge to claim each ${
3327
isErc20 ? "token" : "NFT"
3428
}?`}
3529
>
36-
<Flex flexDir={{ base: "column", md: "row" }} gap={2}>
37-
<Box minW="70px" w={{ base: "100%", md: "50%" }}>
38-
<PriceInput
39-
onChange={(val) => form.setValue(`phases.${phaseIndex}.price`, val)}
40-
value={field.price?.toString() || ""}
41-
w="full"
42-
/>
43-
</Box>
44-
<Box w={{ base: "100%", md: isColumn ? "50%" : "100%" }}>
30+
<div className={cn("flex flex-col md:flex-row gap-3")}>
31+
<PriceInput
32+
onChange={(val) => form.setValue(`phases.${phaseIndex}.price`, val)}
33+
value={field.price?.toString() || ""}
34+
disabled={formDisabled}
35+
className="max-w-48"
36+
/>
37+
<div className="grow max-w-md">
4538
<CurrencySelector
4639
contractChainId={props.contractChainId}
4740
isDisabled={formDisabled}
@@ -53,8 +46,8 @@ export const ClaimPriceInput = (props: { contractChainId: number }) => {
5346
}
5447
value={field?.currencyAddress || NATIVE_TOKEN_ADDRESS}
5548
/>
56-
</Box>
57-
</Flex>
58-
</CustomFormControl>
49+
</div>
50+
</div>
51+
</FormFieldSetup>
5952
);
6053
};

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/Inputs/ClaimerSelection.tsx

Lines changed: 50 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
1-
import { Box, Flex, Select } from "@chakra-ui/react";
21
import { UploadIcon } from "lucide-react";
2+
import { FormFieldSetup } from "@/components/blocks/FormFieldSetup";
33
import { Button } from "@/components/ui/button";
4-
import { useClaimConditionsFormContext } from "..";
5-
import { CustomFormControl } from "../common";
4+
import {
5+
Select,
6+
SelectContent,
7+
SelectItem,
8+
SelectTrigger,
9+
SelectValue,
10+
} from "@/components/ui/select";
11+
import { cn } from "@/lib/utils";
12+
import { useClaimConditionsFormContext } from "../index";
613

714
/**
815
* Allows the user to
@@ -19,12 +26,11 @@ export const ClaimerSelection = () => {
1926
isErc20,
2027
setOpenSnapshotIndex: setOpenIndex,
2128
isAdmin,
22-
isColumn,
2329
claimConditionType,
2430
} = useClaimConditionsFormContext();
2531

26-
const handleClaimerChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
27-
const val = e.currentTarget.value as "any" | "specific" | "overrides";
32+
const handleClaimerChange = (value: string) => {
33+
const val = value as "any" | "specific" | "overrides";
2834

2935
if (val === "any") {
3036
form.setValue(`phases.${phaseIndex}.snapshot`, undefined);
@@ -80,79 +86,69 @@ export const ClaimerSelection = () => {
8086
: `Who can claim ${isErc20 ? "tokens" : "NFTs"} during this phase?`;
8187

8288
return (
83-
<CustomFormControl
84-
disabled={formDisabled}
85-
error={
89+
<FormFieldSetup
90+
errorMessage={
8691
form.getFieldState(`phases.${phaseIndex}.snapshot`, form.formState)
87-
.error
92+
?.error?.message
8893
}
8994
helperText={helperText}
9095
label={label}
96+
isRequired={false}
9197
>
92-
<Flex direction={{ base: "column", md: "row" }} gap={4}>
98+
<div className="flex flex-col md:flex-row gap-4">
9399
{claimConditionType === "overrides" ||
94100
claimConditionType === "specific" ? null : (
95101
<Select
96-
isDisabled={formDisabled}
97-
onChange={handleClaimerChange}
102+
disabled={formDisabled}
103+
onValueChange={handleClaimerChange}
98104
value={dropType}
99-
w={{ base: "100%", md: "50%" }}
100105
>
101-
<option value="any">Any wallet</option>
102-
<option value="overrides">Any wallet (with overrides)</option>
103-
<option value="specific">Only specific wallets</option>
106+
<SelectTrigger className="w-full md:w-1/2">
107+
<SelectValue />
108+
</SelectTrigger>
109+
<SelectContent>
110+
<SelectItem value="any">Any wallet</SelectItem>
111+
<SelectItem value="overrides">
112+
Any wallet (with overrides)
113+
</SelectItem>
114+
<SelectItem value="specific">Only specific wallets</SelectItem>
115+
</SelectContent>
104116
</Select>
105117
)}
106118

107119
{/* Edit or See Snapshot */}
108120
{field.snapshot ? (
109-
<Flex
110-
direction={{
111-
base: "column",
112-
md: isColumn ? "column" : "row",
113-
}}
114-
gap={1.5}
115-
>
121+
<div className="flex items-center gap-3">
116122
{/* disable the "Edit" button when form is disabled, but not when it's a "See" button */}
117123
<Button
118124
className="gap-2 rounded-md"
119125
disabled={disabledSnapshotButton}
120126
onClick={() => setOpenIndex(phaseIndex)}
121-
variant="primary"
127+
size="sm"
122128
>
123129
{isAdmin ? "Edit" : "See"} Claimer Snapshot
124130
<UploadIcon className="size-4" />
125131
</Button>
126132

127-
<Flex
128-
_light={{
129-
color: field.snapshot?.length === 0 ? "red.500" : "green.500",
130-
}}
131-
align="center"
132-
color={field.snapshot?.length === 0 ? "red.400" : "green.400"}
133-
direction="row"
134-
gap={2}
135-
justify="center"
136-
ml={2}
137-
opacity={disabledSnapshotButton ? 0.5 : 1}
133+
<div
134+
className={cn(
135+
"flex gap-2 items-center",
136+
field.snapshot?.length === 0
137+
? "text-muted-foreground"
138+
: "text-green-600 dark:text-green-500",
139+
disabledSnapshotButton ? "opacity-50" : "",
140+
)}
138141
>
139-
<p>
140-
{" "}
141-
<strong>
142-
{field.snapshot?.length} address
143-
{field.snapshot?.length === 1 ? "" : "es"}
144-
</strong>{" "}
145-
in snapshot
146-
</p>
147-
</Flex>
148-
</Flex>
149-
) : (
150-
<Box
151-
display={{ base: "none", md: "block" }}
152-
w={{ base: "100%", md: "50%" }}
153-
/>
154-
)}
155-
</Flex>
156-
</CustomFormControl>
142+
<div className="size-2 bg-current rounded-full" />
143+
<span className="text-sm">
144+
{field.snapshot?.length}{" "}
145+
{field.snapshot?.length === 1 ? "address" : "addresses"} in
146+
snapshot
147+
</span>
148+
</div>
149+
</div>
150+
) : null}
151+
</div>
152+
</FormFieldSetup>
157153
);
158154
};

apps/dashboard/src/app/(app)/(dashboard)/(chain)/[chain_id]/[contractAddress]/_components/claim-conditions/claim-conditions-form/Inputs/CreatorInput.tsx

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useActiveAccount } from "thirdweb/react";
2+
import { FormFieldSetup } from "@/components/blocks/FormFieldSetup";
23
import { Input } from "@/components/ui/input";
3-
import { CustomFormControl } from "../common";
44
import { useClaimConditionsFormContext } from "../index";
55

66
/**
@@ -14,17 +14,17 @@ interface CreatorInputProps {
1414
export const CreatorInput: React.FC<CreatorInputProps> = ({
1515
creatorAddress,
1616
}) => {
17-
const { formDisabled, claimConditionType, isAdmin } =
18-
useClaimConditionsFormContext();
17+
const { claimConditionType, isAdmin } = useClaimConditionsFormContext();
1918
const walletAddress = useActiveAccount()?.address;
2019

2120
if (claimConditionType !== "creator") {
2221
return null;
2322
}
2423

2524
return (
26-
<CustomFormControl
27-
disabled={formDisabled}
25+
<FormFieldSetup
26+
isRequired={false}
27+
errorMessage={undefined}
2828
helperText={
2929
<>
3030
This wallet address will be able to indefinitely claim.{" "}
@@ -34,7 +34,12 @@ export const CreatorInput: React.FC<CreatorInputProps> = ({
3434
}
3535
label="Creator address"
3636
>
37-
<Input disabled readOnly value={creatorAddress || walletAddress} />
38-
</CustomFormControl>
37+
<Input
38+
disabled
39+
readOnly
40+
value={creatorAddress || walletAddress}
41+
className="disabled:opacity-100 max-w-sm"
42+
/>
43+
</FormFieldSetup>
3944
);
4045
};

0 commit comments

Comments
 (0)