Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 51 additions & 32 deletions apps/dapp/src/modules/auction/curator-fee-manager.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { Button, InfoLabel, Badge, Tooltip, cn } from "@repo/ui";
import React from "react";
import { Button, InfoLabel, Text, Badge, Tooltip, cn } from "@repo/ui";
import { useCuratorFees } from "./hooks/use-curator-fees";
import { useChainId } from "wagmi";
import React from "react";
import { useFees } from "./hooks/use-fees";
import { parsePercent } from "utils/number";
import { AuctionType } from "@repo/types";
import { getAuctionHouse } from "utils/contracts";
import { activeChains } from "@repo/env/src/chains";
import { auctionMetadata } from "./metadata";
import { z } from "zod";

type CuratorFeeManagerProps = {
chainId?: number;
auctionType: AuctionType;
modules: AuctionType[];
className?: string;
};

export function CuratorFeeManager({
auctionType,
...props
Expand All @@ -30,14 +31,30 @@ export function CuratorFeeManager({
data: { maxCuratorFee },
} = useFees(chainId, ah.address, auctionType);

const [fee, setFee] = React.useState<string>("");
const curatorFees = useCuratorFees(chainId, parseFloat(fee), auctionType);
const parsedAmount = parseFloat(fee);
const [fee, setFee] = React.useState<string | undefined>();
const curatorFees = useCuratorFees(
chainId,
parseFloat(fee ?? "0"),
auctionType,
);

const feeSchema = React.useMemo(() => {
return z.coerce
.number({ invalid_type_error: "Must be a valid number" })
.optional()
.refine((data) => !data || (data ?? 0) <= (maxCuratorFee ?? 0), {
message: `Max fee is ${maxCuratorFee}%`,
})
.refine((data) => !data || data !== curatorFees.fee);
}, [maxCuratorFee]);

const result = feeSchema.safeParse(fee);
const error = !result.success && result.error.errors[0];

//Clears tx state when moving between chains after updating a fee
React.useEffect(() => {
curatorFees.reset();
setFee("");
setFee(undefined);
}, [chainId, auctionType]);

return (
Expand All @@ -48,32 +65,34 @@ export function CuratorFeeManager({
", ",
)}.`}
>
<InfoLabel
editable
label={"Current Fee"}
value={fee || curatorFees.fee + "%"}
className="text-left"
inputClassName="w-28 min-w-0 px-0 border border-surface-secondary"
onChange={(e) => {
parsePercent(e);
setFee(e.target.value);
}}
onBlur={(e) => {
if (!isFinite(parseFloat(e.target.value))) {
setFee(curatorFees.fee + "%");
}
}}
reverse
/>
<div className="flex-col items-start justify-start">
<div className="flex items-end">
<InfoLabel
defaultValue={"" + curatorFees.fee}
value={fee === undefined ? curatorFees.fee : fee}
label={"Current Fee Percentage"}
className="text-left"
inputClassName="w-28 min-w-0 px-0 border border-surface-secondary"
onChange={(e) => setFee(e.target.value)}
maxLength={5}
editable
reverse
/>
<Button
size="sm"
disabled={!!error}
onClick={() => curatorFees.handleSetFee()}
>
Update Fee
</Button>
</div>
{error && (
<Text size="xs" className="text-feedback-alert text-left">
{error.message}
</Text>
)}
</div>
</Tooltip>

<Button
size="sm"
disabled={!isFinite(parsedAmount) || parsedAmount === curatorFees.fee}
onClick={() => curatorFees.handleSetFee()}
>
Update Fee
</Button>
</div>
<Tooltip content="The contract's maximum allowed curator's fee">
<Badge
Expand Down
1 change: 1 addition & 0 deletions apps/dapp/src/utils/number.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export function parsePercent(e: React.ChangeEvent<HTMLInputElement>) {
const int = e.target.value.slice(0, e.target.value.length - 1);
/* If there is no number (just the percent sign), rewrite
it so it persists and move the cursor just before it.*/

if (int.includes("%")) {
e.target.value = "%";
e.target.setSelectionRange(0, 0);
Expand Down
30 changes: 16 additions & 14 deletions packages/ui/src/components/info-label.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,36 +8,38 @@ export type InfoLabelProps = {
editable?: boolean;
className?: string;
inputClassName?: string;
} & React.ComponentProps<"input">;
} & React.InputHTMLAttributes<HTMLInputElement>;

const valueSizeMap = {
sm: "text-base",
md: "text-2xl",
lg: "text-3xl",
} as const;

export function InfoLabel(props: InfoLabelProps) {
export function InfoLabel({
label,
reverse,
editable,
valueSize,
className,
inputClassName,
...props
}: InfoLabelProps) {
return (
<div
className={cn(props.className, props.reverse && "flex flex-col-reverse")}
>
{props.editable ? (
<div className={cn(className, reverse && "flex flex-col-reverse")}>
{editable ? (
<Input
variant="ghost"
textSize="lg"
className={props.inputClassName}
onChange={props.onChange}
onBlur={props.onBlur}
value={props.value as string}
className={inputClassName}
{...props}
/>
) : (
<p
className={cn(valueSizeMap[props.valueSize || "md"], props.className)}
>
<p className={cn(valueSizeMap[valueSize || "md"], className)}>
{props.value}
</p>
)}
<p className="text-sm">{props.label}</p>
<p className="text-sm">{label}</p>
</div>
);
}