Skip to content
Merged

Master #15969

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
3 changes: 0 additions & 3 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,3 @@ ANALYZE=false
# Use mock data for development. Set to "false" to use live data but you must have the
# environment variables set to make api requests
USE_MOCK_DATA=true

# Google Sheet ID for torch holders
GOOGLE_SHEET_ID_TORCH_HOLDERS=
136 changes: 76 additions & 60 deletions app/[locale]/10years/_components/CountDown/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@ interface CountDownProps {
className?: string
timeLeftLabels: TimeLeftLabels
expiredLabel: string
dateTime: string
hideZeroUnits?: boolean
onExpired?: () => void
}

const CountDown = ({
className,
timeLeftLabels,
expiredLabel,
dateTime,
hideZeroUnits = false,
onExpired,
}: CountDownProps) => {
const [timeLeft, setTimeLeft] = useState({
days: 0,
Expand All @@ -26,7 +32,7 @@ const CountDown = ({
const [isExpired, setIsExpired] = useState(false)

useEffect(() => {
const targetDate = new Date("2025-07-30T15:44:00Z")
const targetDate = new Date(dateTime)

const calculateTimeLeft = () => {
const now = new Date()
Expand All @@ -41,7 +47,10 @@ const CountDown = ({
seconds: Math.floor((difference / 1000) % 60),
})
} else {
setIsExpired(true)
if (!isExpired) {
setIsExpired(true)
onExpired?.()
}
}
}

Expand All @@ -51,74 +60,81 @@ const CountDown = ({
const timer = setInterval(calculateTimeLeft, 1000)

return () => clearInterval(timer)
}, [])
}, [isExpired, onExpired, dateTime])

if (isExpired) {
return <div className="text-center text-2xl font-bold">{expiredLabel}</div>
}

return (
<div className="flex items-center justify-center gap-10">
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold text-accent-a">
{timeLeft.days}
<div className="flex items-center justify-center gap-10 text-accent-a">
{(!hideZeroUnits || timeLeft.days > 0) && (
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold">{timeLeft.days}</div>
<div className="font-mono text-xs">
{timeLeft.days === 1
? timeLeftLabels.days.singular
: timeLeftLabels.days.plural}
</div>
</div>
<div className="font-mono text-xs text-accent-a">
{timeLeft.days === 1
? timeLeftLabels.days.singular
: timeLeftLabels.days.plural}
)}
{(!hideZeroUnits || timeLeft.days > 0 || timeLeft.hours > 0) && (
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold">{timeLeft.hours}</div>
<div className="font-mono text-xs">
{timeLeft.hours === 1
? timeLeftLabels.hours.singular
: timeLeftLabels.hours.plural}
</div>
</div>
</div>
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold text-accent-a">
{timeLeft.hours}
)}
{(!hideZeroUnits ||
timeLeft.days > 0 ||
timeLeft.hours > 0 ||
timeLeft.minutes > 0) && (
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold">{timeLeft.minutes}</div>
<div className="font-mono text-xs">
{timeLeft.minutes === 1
? timeLeftLabels.minutes.singular
: timeLeftLabels.minutes.plural}
</div>
</div>
<div className="font-mono text-xs text-accent-a">
{timeLeft.hours === 1
? timeLeftLabels.hours.singular
: timeLeftLabels.hours.plural}
)}
{(!hideZeroUnits ||
timeLeft.days > 0 ||
timeLeft.hours > 0 ||
timeLeft.minutes > 0 ||
timeLeft.seconds > 0) && (
<div
className={cn(
"hidden h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] lg:flex dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold">{timeLeft.seconds}</div>
<div className="font-mono text-xs">
{timeLeft.seconds === 1
? timeLeftLabels.seconds.singular
: timeLeftLabels.seconds.plural}
</div>
</div>
</div>
<div
className={cn(
"flex h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold text-accent-a">
{timeLeft.minutes}
</div>
<div className="font-mono text-xs text-accent-a">
{timeLeft.minutes === 1
? timeLeftLabels.minutes.singular
: timeLeftLabels.minutes.plural}
</div>
</div>
<div
className={cn(
"hidden h-20 w-20 flex-col items-center justify-center rounded-2xl border text-center [box-shadow:-2.372px_2.372px_14.234px_1.186px_rgba(52,43,64,0.02),-18.979px_18.979px_14.234px_-3.559px_rgba(52,43,64,0.02),-37.958px_37.958px_28.469px_-7.117px_rgba(52,43,64,0.02),-47.448px_47.448px_47.448px_-14.234px_rgba(88,55,131,0.04)] lg:flex dark:bg-[#171717]",
className
)}
>
<div className="font-mono text-4xl font-bold text-accent-a">
{timeLeft.seconds}
</div>
<div className="font-mono text-xs text-accent-a">
{timeLeft.seconds === 1
? timeLeftLabels.seconds.singular
: timeLeftLabels.seconds.plural}
</div>
</div>
)}
</div>
)
}
Expand Down
77 changes: 77 additions & 0 deletions app/[locale]/10years/_components/NFTMintCard/Connected.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Address } from "viem"
import { useDisconnect, useSwitchChain } from "wagmi"

import { Avatar } from "@/components/ui/avatar"
import { Button } from "@/components/ui/buttons/Button"

import { useNetworkContract } from "@/hooks/useNetworkContract"
import {
formatAddress,
getAddressEtherscanUrl,
getBlockieImage,
} from "@/lib/torch"

export default function Connected({
address,
ensName,
}: {
address: Address
ensName?: string | null
}) {
const { disconnect } = useDisconnect()
const { isSupportedNetwork, networkName, chainId } = useNetworkContract()
const { switchChain, isPending } = useSwitchChain()

const handleSwitchNetwork = () => {
switchChain({ chainId })
}

return (
<div className="flex flex-col items-center justify-between space-y-2">
{/* Wallet Info */}
<div className="flex items-center gap-4">
<Avatar
className="h-6 w-6 !shadow-none"
src={getBlockieImage(address)}
href={getAddressEtherscanUrl(address)}
name={ensName || formatAddress(address)}
/>
<div>{ensName || formatAddress(address)}</div>
</div>

{/* Network Status */}
<div className="text-center">
{isSupportedNetwork ? (
<div className="flex items-center gap-2 text-sm text-success">
<div className="h-2 w-2 rounded-full bg-success"></div>
<span>Connected to {networkName}</span>
</div>
) : (
<div className="flex flex-col items-center gap-2">
<div className="flex items-center gap-2 text-sm text-error">
<div className="h-2 w-2 rounded-full bg-error"></div>
<span>Unsupported Network</span>
</div>
<Button
size="sm"
onClick={handleSwitchNetwork}
disabled={isPending}
>
{isPending ? "Switching..." : `Switch to ${networkName}`}
</Button>
</div>
)}
</div>

{/* Disconnect Button */}
<Button
variant="link"
size="sm"
onClick={() => disconnect()}
className="text-body-medium"
>
disconnect
</Button>
</div>
)
}
14 changes: 14 additions & 0 deletions app/[locale]/10years/_components/NFTMintCard/Connection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { useAccount } from "wagmi"

import MintConnect from "./views/MintConnect"
import Prechecks from "./Prechecks"

export default function Connection() {
const { address, isConnected } = useAccount()

if (!isConnected || !address) {
return <MintConnect />
}

return <Prechecks address={address} />
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Info } from "lucide-react"

import {
Alert,
AlertContent,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert"

const GasFeeInformation = () => {
return (
<Alert variant="warning" className="w-full rounded-none border-none">
<Info className="h-5 w-5 !text-yellow-600" />
<AlertContent>
<AlertTitle className="!text-yellow-800">About Network Fees</AlertTitle>
<AlertDescription className="text-sm text-yellow-700">
While the NFT is free, you&apos;ll need to pay Ethereum network fees
to complete the transaction. Network fees vary throughout the day -
consider waiting for lower network fees periods to save on costs.
</AlertDescription>
</AlertContent>
</Alert>
)
}

export default GasFeeInformation
Loading
Loading