Skip to content
Draft
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
24 changes: 9 additions & 15 deletions apps/web/src/components/Basenames/RegistrationForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import { formatEtherPrice } from 'apps/web/src/utils/formatEtherPrice';
import { formatUsdPrice } from 'apps/web/src/utils/formatUsdPrice';
import { ConnectButton, useConnectModal } from '@rainbow-me/rainbowkit';
import { Button, ButtonSizes, ButtonVariants } from 'apps/web/src/components/Button/Button';
import {
useSwitchToBasenameChain,
useYearSelectionCallbacks,
} from 'apps/web/src/components/Basenames/basenameFormUtils';

export default function RegistrationForm() {
const { chain: connectedChain, address } = useAccount();
Expand All @@ -41,10 +45,7 @@ export default function RegistrationForm() {
const { basenameChain } = useBasenameChain();
const { switchChain } = useSwitchChain();

const switchToIntendedNetwork = useCallback(
() => switchChain({ chainId: basenameChain.id }),
[basenameChain.id, switchChain],
);
const switchToIntendedNetwork = useSwitchToBasenameChain(switchChain, basenameChain.id);

const {
selectedName,
Expand Down Expand Up @@ -72,17 +73,10 @@ export default function RegistrationForm() {
setLearnMoreAboutDiscountsModalOpen((open) => !open);
}, [logEventWithContext, setLearnMoreAboutDiscountsModalOpen]);

const increment = useCallback(() => {
logEventWithContext('registration_form_increment_year', ActionType.click);

setYears((n) => n + 1);
}, [logEventWithContext, setYears]);

const decrement = useCallback(() => {
logEventWithContext('registration_form_decement_year', ActionType.click);

setYears((n) => (n > 1 ? n - 1 : n));
}, [logEventWithContext, setYears]);
const { increment, decrement } = useYearSelectionCallbacks(setYears, {
onIncrement: () => logEventWithContext('registration_form_increment_year', ActionType.click),
onDecrement: () => logEventWithContext('registration_form_decrement_year', ActionType.click),
});

const ethUsdPrice = useEthPriceFromUniswap();
const { data: initialPrice } = useNameRegistrationPrice(selectedName, years);
Expand Down
17 changes: 6 additions & 11 deletions apps/web/src/components/Basenames/RenewalForm/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ import { RenewalButton } from './RenewalButton';
import { formatUsdPrice } from 'apps/web/src/utils/formatUsdPrice';
import { formatEtherPrice } from 'apps/web/src/utils/formatEtherPrice';
import YearSelector from 'apps/web/src/components/Basenames/YearSelector';
import {
useSwitchToBasenameChain,
useYearSelectionCallbacks,
} from 'apps/web/src/components/Basenames/basenameFormUtils';

export default function RenewalForm() {
const { chain: connectedChain, address } = useAccount();
Expand All @@ -24,23 +28,14 @@ export default function RenewalForm() {

const { years, setYears, renewBasename, price, isPending, expirationDate } = useRenewal();

const switchToIntendedNetwork = useCallback(
() => switchChain({ chainId: basenameChain.id }),
[basenameChain.id, switchChain],
);
const switchToIntendedNetwork = useSwitchToBasenameChain(switchChain, basenameChain.id);

const isOnSupportedNetwork = useMemo(
() => connectedChain && supportedChainIds.includes(connectedChain.id),
[connectedChain],
);

const increment = useCallback(() => {
setYears((n) => n + 1);
}, [setYears]);

const decrement = useCallback(() => {
setYears((n) => (n > 1 ? n - 1 : n));
}, [setYears]);
const { increment, decrement } = useYearSelectionCallbacks(setYears);

const ethUsdPrice = useEthPriceFromUniswap();

Expand Down
36 changes: 36 additions & 0 deletions apps/web/src/components/Basenames/basenameFormUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { useCallback } from 'react';

/**
* Creates a callback to switch to a specific chain
*/
export function useSwitchToBasenameChain(
switchChain: (params: { chainId: number }) => void,
chainId: number,
) {
return useCallback(() => switchChain({ chainId }), [chainId, switchChain]);
}

/**
* Creates callbacks for incrementing and decrementing year selection
*/
export function useYearSelectionCallbacks(
setYears: (fn: (n: number) => number) => void,
options?: {
onIncrement?: () => void;
onDecrement?: () => void;
},
) {
const { onIncrement, onDecrement } = options ?? {};

const increment = useCallback(() => {
onIncrement?.();
setYears((n) => n + 1);
}, [setYears, onIncrement]);

const decrement = useCallback(() => {
onDecrement?.();
setYears((n) => (n > 1 ? n - 1 : n));
}, [setYears, onDecrement]);

return { increment, decrement };
}
14 changes: 5 additions & 9 deletions apps/web/src/components/Builders/AgentKit/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
'use client';

import { ButtonVariants } from 'apps/web/src/components/base-org/Button/types';
import Title from 'apps/web/src/components/base-org/typography/Title';
import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types';
Expand All @@ -9,16 +7,14 @@ import { Demo } from 'apps/web/src/components/Builders/AgentKit/Demo';
import { AGENTKIT_DOCS_LINK } from 'apps/web/src/components/Builders/AgentKit/links';
import { Icon } from 'apps/web/src/components/Icon/Icon';
import Image, { StaticImageData } from 'next/image';
import { useCallback, useState } from 'react';
import { useCopyToClipboard } from 'apps/web/src/hooks/useCopyToClipboard';
import { useCallback } from 'react';

export function Hero() {
const [hasCopied, setHasCopied] = useState(false);

const { hasCopied, copyToClipboard } = useCopyToClipboard();
const handleCopy = useCallback(() => {
void navigator.clipboard.writeText('npx create-agentkit-app');
setHasCopied(true);
setTimeout(() => setHasCopied(false), 2000); // Reset after 2 seconds
}, []);
copyToClipboard('npx create-agentkit-app');
}, [copyToClipboard]);
return (
<div className="flex flex-col gap-2 pt-20 sm:items-center">
<div className="flex items-center gap-2 pb-6 text-[#E66020]">
Expand Down
14 changes: 5 additions & 9 deletions apps/web/src/components/Builders/MiniKit/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,22 @@
'use client';

import Image, { StaticImageData } from 'next/image';
import { useCallback, useState } from 'react';
import { ButtonVariants } from 'apps/web/src/components/base-org/Button/types';
import Title from 'apps/web/src/components/base-org/typography/Title';
import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types';
import { ButtonWithLinkAndEventLogging } from 'apps/web/src/components/Button/ButtonWithLinkAndEventLogging';
import { HeaderAnimation } from 'apps/web/src/components/Builders/MiniKit/HeaderAnimation';
import minikit from 'apps/web/src/components/Builders/MiniKit/minikit.svg';
import { Icon } from 'apps/web/src/components/Icon/Icon';
import { useCopyToClipboard } from 'apps/web/src/hooks/useCopyToClipboard';
import { useCallback } from 'react';

export const GET_STARTED_URL = 'https://docs.base.org/builderkits/minikit/overview';
const MINIKIT_COMMAND = 'npx create-onchain --mini';

export function Hero() {
const [hasCopied, setHasCopied] = useState(false);

const { hasCopied, copyToClipboard } = useCopyToClipboard();
const handleCopy = useCallback(() => {
void navigator.clipboard.writeText(MINIKIT_COMMAND);
setHasCopied(true);
setTimeout(() => setHasCopied(false), 2000); // Reset after 2 seconds
}, []);
copyToClipboard(MINIKIT_COMMAND);
}, [copyToClipboard]);

return (
<div className="flex items-center justify-between gap-10 pt-20 max-sm:flex-col">
Expand Down
14 changes: 5 additions & 9 deletions apps/web/src/components/Builders/Onchainkit/CtaBanner.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
'use client';

import { ButtonVariants } from 'apps/web/src/components/base-org/Button/types';
import { CtaBanner as DefaultCtaBanner } from 'apps/web/src/components/Builders/Shared/CtaBanner';
import { ButtonWithLinkAndEventLogging } from 'apps/web/src/components/Button/ButtonWithLinkAndEventLogging';
import { useCallback, useState } from 'react';
import { Icon } from 'apps/web/src/components/Icon/Icon';
import { useCopyToClipboard } from 'apps/web/src/hooks/useCopyToClipboard';
import { useCallback } from 'react';

const ONCHAINKIT_DOCS_LINK = 'https://docs.base.org/builderkits/onchainkit/getting-started';
const ONCHAINKIT_AI_DOCS_LINK = 'https://docs.base.org/builderkits/onchainkit/llms.txt';

export function CtaBanner() {
const [hasCopied, setHasCopied] = useState(false);

const { hasCopied, copyToClipboard } = useCopyToClipboard();
const handleCopy = useCallback(() => {
void navigator.clipboard.writeText('npm create onchain');
setHasCopied(true);
setTimeout(() => setHasCopied(false), 2000); // Reset after 2 seconds
}, []);
copyToClipboard('npm create onchain');
}, [copyToClipboard]);

return (
<DefaultCtaBanner
Expand Down
14 changes: 5 additions & 9 deletions apps/web/src/components/Builders/Onchainkit/Hero.tsx
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
'use client';

import { ButtonVariants } from 'apps/web/src/components/base-org/Button/types';
import Title from 'apps/web/src/components/base-org/typography/Title';
import { TitleLevel } from 'apps/web/src/components/base-org/typography/Title/types';
import Image, { StaticImageData } from 'next/image';
import onchainkit from 'apps/web/src/components/Builders/Onchainkit/onchainkit.svg';
import { ButtonWithLinkAndEventLogging } from 'apps/web/src/components/Button/ButtonWithLinkAndEventLogging';
import { useCallback, useState } from 'react';
import { Icon } from 'apps/web/src/components/Icon/Icon';
import { useCopyToClipboard } from 'apps/web/src/hooks/useCopyToClipboard';
import { useCallback } from 'react';

const ONCHAINKIT_DOCS_LINK = 'https://docs.base.org/builderkits/onchainkit/getting-started';
const ONCHAINKIT_GITHUB_LINK = 'https://github.com/coinbase/onchainkit';

export function Hero() {
const [hasCopied, setHasCopied] = useState(false);

const { hasCopied, copyToClipboard } = useCopyToClipboard();
const handleCopy = useCallback(() => {
void navigator.clipboard.writeText('npm create onchain');
setHasCopied(true);
setTimeout(() => setHasCopied(false), 2000); // Reset after 2 seconds
}, []);
copyToClipboard('npm create onchain');
}, [copyToClipboard]);

return (
<div className="flex flex-col gap-2 pt-20 sm:items-center">
Expand Down
14 changes: 5 additions & 9 deletions apps/web/src/components/Builders/Shared/BottomCta/index.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
'use client';

import { ButtonVariants } from 'apps/web/src/components/base-org/Button/types';
import { ButtonWithLinkAndEventLogging } from 'apps/web/src/components/Button/ButtonWithLinkAndEventLogging';
import { useCallback, useState } from 'react';
import { Icon } from 'apps/web/src/components/Icon/Icon';
import { CtaBanner } from 'apps/web/src/components/Builders/Shared/BottomCta/CtaBanner';
import { useCopyToClipboard } from 'apps/web/src/hooks/useCopyToClipboard';
import { useCallback } from 'react';

export function BottomCta() {
const [hasCopied, setHasCopied] = useState(false);

const { hasCopied, copyToClipboard } = useCopyToClipboard();
const handleCopy = useCallback(() => {
void navigator.clipboard.writeText('npm create onchain');
setHasCopied(true);
setTimeout(() => setHasCopied(false), 2000); // Reset after 2 seconds
}, []);
copyToClipboard('npm create onchain');
}, [copyToClipboard]);

return (
<CtaBanner
Expand Down
43 changes: 43 additions & 0 deletions apps/web/src/hooks/useCopyToClipboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useCallback, useEffect, useRef, useState } from 'react';

/**
* Hook for handling copy-to-clipboard functionality with temporary feedback state
* @param timeout - Time in milliseconds before the copied state resets (default: 2000ms)
* @returns Object with `hasCopied` state and `copyToClipboard` function
*/
export function useCopyToClipboard(timeout = 2000) {
const [hasCopied, setHasCopied] = useState(false);
const timeoutRef = useRef<NodeJS.Timeout | null>(null);

useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);

const copyToClipboard = useCallback(
async (text: string) => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}

try {
await navigator.clipboard.writeText(text);
setHasCopied(true);

timeoutRef.current = setTimeout(() => {
setHasCopied(false);
timeoutRef.current = null;
}, timeout);
} catch (error) {
// Silently fail - clipboard access may be restricted
console.warn('Failed to copy to clipboard:', error);
}
},
[timeout],
);

return { hasCopied, copyToClipboard };
}
11 changes: 0 additions & 11 deletions apps/web/src/utils/formatWei.ts

This file was deleted.

18 changes: 0 additions & 18 deletions apps/web/src/utils/logEvent.ts

This file was deleted.

13 changes: 0 additions & 13 deletions apps/web/src/utils/weiToEth.ts

This file was deleted.