Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
7 changes: 7 additions & 0 deletions .env.production
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
REACT_APP_DEBUG=
REACT_APP_API_BASE_URL=$API_BASE_URL
REACT_APP_LINK_SSV_WEBAPP=$LINK_SSV_WEBAPP
REACT_APP_GOOGLE_TAG_SECRET=$GOOGLE_TAG_SECRET
REACT_APP_GOOGLE_TAG_URL=https://www.googletagmanager.com/gtm.js?id=
REACT_APP_ANNOUNCEMENT=$ANNOUNCEMENT
REACT_APP_MIXPANEL_TOKEN=$MIXPANEL_TOKEN
2 changes: 1 addition & 1 deletion next-env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
/// <reference types="next/image-types/global" />

// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
108 changes: 43 additions & 65 deletions src/app/_components/clusters/filters/owner-address-filter.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
"use client"

import { useState } from "react"
import { searchClusters } from "@/api/clusters"
import { useQuery } from "@tanstack/react-query"
import { CommandLoading } from "cmdk"
import { xor } from "lodash-es"
import { Loader2, X } from "lucide-react"
import { isAddress, type Address } from "viem"
import { X } from "lucide-react"
import { MdKeyboardReturn } from "react-icons/md"
import { isAddress } from "viem"

import { cn } from "@/lib/utils"
import { shortenAddress } from "@/lib/utils/strings"
import { useClustersSearchParams } from "@/hooks/search/use-clusters-search-params"
import { Button } from "@/components/ui/button"
import { Checkbox } from "@/components/ui/checkbox"
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
Expand All @@ -26,26 +24,9 @@ import { FilterButton } from "@/components/filter/filter-button"
export function OwnerAddressFilter() {
const [open, setOpen] = useState(false)
const [search, setSearch] = useState<string>("")
const { network, filters, setFilters } = useClustersSearchParams()
const query = useQuery({
queryKey: ["clusters", "owner-address", search, network],
queryFn: async () => {
return searchClusters({
search: search,
network,
page: 1,
perPage: 10,
})
},
select: (data) => [
...new Set(
data.clusters
.map((cluster) => cluster.ownerAddress)
.filter((address): address is Address => Boolean(address))
),
],
enabled: open && isAddress(search),
})
const { filters, setFilters } = useClustersSearchParams()

const isSearchValidAddress = isAddress(search)

return (
<FilterButton
Expand All @@ -63,9 +44,13 @@ export function OwnerAddressFilter() {
}}
>
<Command>
<div className="p-2">
<div
className={cn("p-2", {
"pb-0": isSearchValidAddress,
})}
>
<CommandInput
placeholder="Search Owner Address"
placeholder="Search addresses"
value={search}
onValueChange={(value) => setSearch(value)}
/>
Expand Down Expand Up @@ -95,45 +80,38 @@ export function OwnerAddressFilter() {
))}
</div>
)}
<CommandList
className={cn("max-h-none overflow-y-auto", {
"pt-0": !filters.ownerAddress?.length,
})}
>
{query.isLoading ? (
<CommandLoading className="flex items-center justify-center p-4">
<Loader2 className="animate-spin" />
</CommandLoading>
) : (
{isSearchValidAddress && (
<CommandList
className={cn("max-h-none overflow-y-auto", {
"pt-0": !filters.ownerAddress?.length,
})}
>
<CommandEmpty>This list is empty.</CommandEmpty>
)}
{query.data?.map((owner_address) => (
<CommandItem
key={owner_address}
value={owner_address}
className="flex h-10 items-center space-x-2 px-2"
onSelect={() => {
setFilters((prev) => ({
...prev,
ownerAddress: xor(prev.ownerAddress, [owner_address]),
}))
}}
>
<Checkbox
id={owner_address}
checked={filters.ownerAddress?.includes(owner_address)}
className="mr-2"
/>
<span
className={cn(
"flex-1 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)}
<CommandGroup>
<CommandItem
value={search}
className="flex h-10 items-center space-x-2 px-2"
onSelect={() => {
setFilters((prev) => ({
...prev,
ownerAddress: xor(prev.ownerAddress, [search]),
}))
}}
>
{owner_address}
</span>
</CommandItem>
))}
</CommandList>
<span
className={cn(
"flex-1 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)}
>
{search}
</span>
<div className="flex h-5 w-6 items-center justify-center rounded-md border border-gray-400">
<MdKeyboardReturn className="size-3 text-gray-500" />
</div>
</CommandItem>
</CommandGroup>
</CommandList>
)}
</Command>
</FilterButton>
)
Expand Down
71 changes: 22 additions & 49 deletions src/app/_components/operators/filters/owner-address-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,10 @@ import { FilterButton } from "@/components/filter/filter-button"
export function OwnerAddressFilter() {
const [open, setOpen] = useState(false)
const [search, setSearch] = useState<string>("")
const { network, filters, setFilters } = useOperatorsSearchParams()
const { filters, setFilters } = useOperatorsSearchParams()

const isSearchValidAddress = isAddress(search)

const query = useQuery({
queryKey: ["operators", "owner-address", search, network],
queryFn: async () => {
return searchOperators({
network,
search,
page: 1,
perPage: 10,
})
},
select: (data) => [
...new Set(data.operators.map((operator) => operator.owner_address)),
],
enabled: open && isSearchValidAddress,
})

return (
<FilterButton
name="Owner Address"
Expand Down Expand Up @@ -105,40 +89,29 @@ export function OwnerAddressFilter() {
"pt-0": !filters.ownerAddress?.length,
})}
>
{query.isLoading ? (
<CommandLoading className="flex items-center justify-center p-4">
<Loader2 className="animate-spin" />
</CommandLoading>
) : (
<CommandEmpty>This list is empty.</CommandEmpty>
)}
<CommandEmpty>This list is empty.</CommandEmpty>
<CommandGroup>
{query.data?.map((owner_address) => (
<CommandItem
key={owner_address}
value={owner_address}
className="flex h-10 items-center space-x-2 px-2"
onSelect={() => {
setFilters((prev) => ({
...prev,
ownerAddress: xor(prev.ownerAddress, [
owner_address as Address,
]),
}))
}}
<CommandItem
value={search}
className="flex h-10 items-center space-x-2 px-2"
onSelect={() => {
setFilters((prev) => ({
...prev,
ownerAddress: xor(prev.ownerAddress, [search]),
}))
}}
>
<span
className={cn(
"flex-1 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)}
>
<span
className={cn(
"flex-1 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)}
>
{owner_address}
</span>
<div className="flex h-5 w-6 items-center justify-center rounded-md border border-gray-400">
<MdKeyboardReturn className="size-3 text-gray-500" />
</div>
</CommandItem>
))}
{search}
</span>
<div className="flex h-5 w-6 items-center justify-center rounded-md border border-gray-400">
<MdKeyboardReturn className="size-3 text-gray-500" />
</div>
</CommandItem>
</CommandGroup>
</CommandList>
)}
Expand Down
78 changes: 24 additions & 54 deletions src/app/_components/validators/filters/owner-address-filter.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
"use client"

import { useState } from "react"
import { searchValidators } from "@/api/validators"
import { useQuery } from "@tanstack/react-query"
import { CommandLoading } from "cmdk"
import { xor } from "lodash-es"
import { Loader2, X } from "lucide-react"
import { X } from "lucide-react"
import { MdKeyboardReturn } from "react-icons/md"
import { isAddress, type Address } from "viem"
import { isAddress } from "viem"

import { cn } from "@/lib/utils"
import { shortenAddress } from "@/lib/utils/strings"
Expand All @@ -27,28 +24,10 @@ import { FilterButton } from "@/components/filter/filter-button"
export function OwnerAddressFilter() {
const [open, setOpen] = useState(false)
const [search, setSearch] = useState<string>("")
const { network, filters, setFilters } = useValidatorsSearchParams()
const { filters, setFilters } = useValidatorsSearchParams()

const isSearchValidAddress = isAddress(search)

const query = useQuery({
queryKey: ["validators", "owner-address", search, network],
queryFn: async () => {
return searchValidators({
network,
search,
page: 1,
perPage: 10,
})
},
select: (data) => [
...new Set(
data.validators.map((validator) => validator.owner_address as Address)
),
],
enabled: open && isSearchValidAddress,
})

return (
<FilterButton
name="Owner Address"
Expand Down Expand Up @@ -107,38 +86,29 @@ export function OwnerAddressFilter() {
"pt-0": !filters.ownerAddress?.length,
})}
>
{query.isLoading ? (
<CommandLoading className="flex items-center justify-center p-4">
<Loader2 className="animate-spin" />
</CommandLoading>
) : (
<CommandEmpty>This list is empty.</CommandEmpty>
)}
<CommandEmpty>This list is empty.</CommandEmpty>
<CommandGroup>
{query.data?.map((owner_address) => (
<CommandItem
key={owner_address}
value={owner_address}
className="flex h-10 items-center space-x-2 px-2"
onSelect={() => {
setFilters((prev) => ({
...prev,
ownerAddress: xor(prev.ownerAddress, [owner_address]),
}))
}}
<CommandItem
value={search}
className="flex h-10 items-center space-x-2 px-2"
onSelect={() => {
setFilters((prev) => ({
...prev,
ownerAddress: xor(prev.ownerAddress, [search]),
}))
}}
>
<span
className={cn(
"flex-1 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)}
>
<span
className={cn(
"flex-1 text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
)}
>
{owner_address}
</span>
<div className="flex h-5 w-6 items-center justify-center rounded-md border border-gray-400">
<MdKeyboardReturn className="size-3 text-gray-500" />
</div>
</CommandItem>
))}
{search}
</span>
<div className="flex h-5 w-6 items-center justify-center rounded-md border border-gray-400">
<MdKeyboardReturn className="size-3 text-gray-500" />
</div>
</CommandItem>
</CommandGroup>
</CommandList>
)}
Expand Down
21 changes: 15 additions & 6 deletions src/app/_components/validators/validators-table-columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { type Operator, type SearchValidator } from "@/types/api"
import { add0x, remove0x, shortenAddress } from "@/lib/utils/strings"
import { CopyBtn } from "@/components/ui/copy-btn"
import { Text } from "@/components/ui/text"
import { Tooltip } from "@/components/ui/tooltip"
import { DataTableColumnHeader } from "@/components/data-table/data-table-column-header"
import { OperatorAvatar } from "@/components/operators/operator-avatar"
import { OperatorInfo } from "@/components/tooltip/operator-info"
import { ValidatorStatusBadge } from "@/components/validators/validator-status-badge"

export const validatorsTableColumns: ColumnDef<SearchValidator<Operator>>[] = [
Expand Down Expand Up @@ -77,12 +79,19 @@ export const validatorsTableColumns: ColumnDef<SearchValidator<Operator>>[] = [
cell: ({ row }) => (
<div className="flex gap-1">
{row.original.operators.map((operator) => (
<Link href={`/operator/${operator.id}`} key={operator.id}>
<OperatorAvatar
src={operator.logo}
isPrivate={operator.is_private}
/>
</Link>
<Tooltip
asChild
key={operator.id}
className="w-[240px] p-4"
content={<OperatorInfo operator={operator} />}
>
<Link href={`/operator/${operator.id}`} key={operator.id}>
<OperatorAvatar
src={operator.logo}
isPrivate={operator.is_private}
/>
</Link>
</Tooltip>
))}
</div>
),
Expand Down
Loading