mirror of
https://github.com/penxio/penx.git
synced 2026-05-12 03:03:12 -04:00
feat: improve create-fi page
This commit is contained in:
@@ -5,7 +5,7 @@ export const revalidate = 3600 * 24
|
||||
|
||||
export default async function Page() {
|
||||
return (
|
||||
<div className="pt-10">
|
||||
<div className="pt-10 mx-auto md:max-w-3xl">
|
||||
<Wallet />
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
import { PropsWithChildren, Suspense } from 'react'
|
||||
import { useQueryEthBalance } from '@/app/(creator-fi)/hooks/useEthBalance'
|
||||
import { useQueryEthPrice } from '@/app/(creator-fi)/hooks/useEthPrice'
|
||||
import { useQuerySpace, useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { ClientOnly } from '@/components/ClientOnly'
|
||||
import LoadingCircle from '@/components/icons/loading-circle'
|
||||
import { Profile } from '@/components/Profile/Profile'
|
||||
import { SpaceType } from '@/lib/types'
|
||||
import Link from 'next/link'
|
||||
import { SpaceBasicInfo } from './Space/SpaceBasicInfo'
|
||||
import { SpaceNav } from './Space/SpaceNav'
|
||||
|
||||
interface HeaderProps {
|
||||
isLoading: boolean
|
||||
space: SpaceType
|
||||
}
|
||||
function Header({ isLoading }: HeaderProps) {
|
||||
function Header({ space }: HeaderProps) {
|
||||
return (
|
||||
<header className="flex h-16 items-center justify-between px-4">
|
||||
<div className="flex flex-1 items-center gap-2 ">
|
||||
@@ -36,10 +36,9 @@ function Header({ isLoading }: HeaderProps) {
|
||||
></path>
|
||||
</svg>
|
||||
</Link>
|
||||
{isLoading && <div>Loading..</div>}
|
||||
{!isLoading && <SpaceBasicInfo />}
|
||||
<SpaceBasicInfo space={space} />
|
||||
</div>
|
||||
<SpaceNav></SpaceNav>
|
||||
<SpaceNav />
|
||||
<div className="flex flex-1 justify-end">
|
||||
<Profile />
|
||||
</div>
|
||||
@@ -47,26 +46,17 @@ function Header({ isLoading }: HeaderProps) {
|
||||
)
|
||||
}
|
||||
|
||||
export function CreatorFiLayout({ children }: PropsWithChildren) {
|
||||
interface Props {
|
||||
space: SpaceType
|
||||
}
|
||||
|
||||
export function CreatorFiLayout({ children, space }: PropsWithChildren<Props>) {
|
||||
useQueryEthPrice()
|
||||
useQueryEthBalance()
|
||||
useQuerySpace()
|
||||
const { space } = useSpace()
|
||||
|
||||
if (!space?.address) {
|
||||
return (
|
||||
<>
|
||||
<Header isLoading />
|
||||
<div className="flex h-[80vh] items-center justify-center">
|
||||
<LoadingCircle />
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Header isLoading={false} />
|
||||
<Header space={space} />
|
||||
{children}
|
||||
</>
|
||||
)
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
'use client'
|
||||
|
||||
import { useHolders } from '@/app/(creator-fi)/hooks/useHolders'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { UserAvatar } from '@/components/UserAvatar'
|
||||
import { useHolders } from '@/app/(creator-fi)/hooks/useHolders'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { precision } from '@/lib/math'
|
||||
import { cn, shortenAddress } from '@/lib/utils'
|
||||
|
||||
interface Props {}
|
||||
|
||||
export function HolderList({}: Props) {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { holders, isLoading } = useHolders()
|
||||
|
||||
if (isLoading) {
|
||||
@@ -38,7 +38,9 @@ export function HolderList({}: Props) {
|
||||
<div className="text-sm">{shortenAddress(item.account)}</div>
|
||||
</div>
|
||||
<div className="flex gap-1">
|
||||
<span className="font-bold">{precision.toDecimal(item.balance).toFixed(2)}</span>
|
||||
<span className="font-bold">
|
||||
{precision.toDecimal(item.balance).toFixed(2)}
|
||||
</span>
|
||||
{space.symbolName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { useCopyToClipboard } from '@/app/(creator-fi)/hooks/useCopyToClipboard'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { Copy } from 'lucide-react'
|
||||
import { toast } from 'sonner'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
|
||||
export function SpaceAddress() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { address = '' } = space
|
||||
const { copy } = useCopyToClipboard()
|
||||
return (
|
||||
|
||||
@@ -1,33 +1,27 @@
|
||||
'use client'
|
||||
|
||||
import { useAddress } from '@/app/(creator-fi)/hooks/useAddress'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { getSpaceId } from '@/lib/getSpaceId'
|
||||
import { SpaceType } from '@/lib/types'
|
||||
import { getUrl } from '@/lib/utils'
|
||||
|
||||
interface Props {}
|
||||
|
||||
export function SpaceBasicInfo({}: Props) {
|
||||
const address = useAddress()
|
||||
const { space } = useSpace()
|
||||
const spaceId = getSpaceId()
|
||||
interface Props {
|
||||
space: SpaceType
|
||||
}
|
||||
|
||||
export function SpaceBasicInfo({ space }: Props) {
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<img
|
||||
alt={space.name || ''}
|
||||
className="h-9 w-9 rounded-lg bg-foreground shadow-sm"
|
||||
src={
|
||||
space.logo ||
|
||||
'https://public.blob.vercel-storage.com/eEZHAoPTOBSYGBE3/JRajRyC-PhBHEinQkupt02jqfKacBVHLWJq7Iy.png'
|
||||
}
|
||||
src={getUrl(space.logo)}
|
||||
/>
|
||||
|
||||
<div className="text-lg font-bold">{space.name}</div>
|
||||
{/* <SpaceAddress /> */}
|
||||
<Button size="sm" variant="secondary" className="rounded-full">
|
||||
<a
|
||||
href={`https://www.respace.one/space/${spaceId}`}
|
||||
href={`https://www.respace.one/space/${space.address}`}
|
||||
className="flex items-center gap-1"
|
||||
target="_blank"
|
||||
>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
'use client'
|
||||
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { cn } from '@/lib/utils'
|
||||
import Link from 'next/link'
|
||||
import { usePathname } from 'next/navigation'
|
||||
@@ -9,9 +8,6 @@ interface Props {}
|
||||
|
||||
export function SpaceNav({}: Props) {
|
||||
const pathname = usePathname()
|
||||
const { space } = useSpace()
|
||||
|
||||
if (!space) return null
|
||||
|
||||
const Paths = {
|
||||
about: `/creator-fi`,
|
||||
@@ -27,7 +23,7 @@ export function SpaceNav({}: Props) {
|
||||
const linkClassName = (path: string) =>
|
||||
cn(
|
||||
'inline-flex item-center justify-center py-1.5 border-b-2 px-3 -mb-[1px] border-transparent',
|
||||
path === pathname && 'border-black border-zinc-400'
|
||||
path === pathname && 'border-black border-zinc-400',
|
||||
)
|
||||
|
||||
return (
|
||||
|
||||
@@ -3,14 +3,14 @@
|
||||
import { ReactNode } from 'react'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { useEthPrice } from '@/app/(creator-fi)/hooks/useEthPrice'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { precision } from '@/lib/math'
|
||||
import { useBalance } from 'wagmi'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
|
||||
interface Props {}
|
||||
|
||||
export function SpaceStats({}: Props) {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { ethPrice } = useEthPrice()
|
||||
|
||||
return (
|
||||
@@ -49,7 +49,7 @@ function StatsItem({ title, value }: StatsItemProps) {
|
||||
}
|
||||
|
||||
function MarketCap() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { data, isLoading } = useBalance({ address: space.address })
|
||||
const { ethPrice } = useEthPrice()
|
||||
if (isLoading || !data) return <Skeleton className="h-8"></Skeleton>
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { UserAvatar } from '@/components/UserAvatar'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useTrades } from '@/app/(creator-fi)/hooks/useTrades'
|
||||
import { precision } from '@/lib/math'
|
||||
import { cn, shortenAddress } from '@/lib/utils'
|
||||
import { TradeType } from '../constants'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
|
||||
interface Props {}
|
||||
|
||||
export function TradeList({}: Props) {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { trades, isLoading } = useTrades()
|
||||
|
||||
if (isLoading) {
|
||||
|
||||
@@ -18,7 +18,7 @@ export function Transaction() {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rounded-2xl bg-white p-4 shadow-sm dark:bg-zinc-950/50">
|
||||
<div className="rounded-2xl bg-background p-4 shadow-sm">
|
||||
<div className="rounded-lg">
|
||||
<div className="mb-3 flex text-foreground/80">
|
||||
<button
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useState } from 'react'
|
||||
import { useQueryEthBalance } from '@/app/(creator-fi)/hooks/useEthBalance'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useTrades } from '@/app/(creator-fi)/hooks/useTrades'
|
||||
import LoadingDots from '@/components/icons/loading-dots'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { WalletConnectButton } from '@/components/WalletConnectButton'
|
||||
import { useAddress } from '@/hooks/useAddress'
|
||||
@@ -37,7 +37,7 @@ export const BuyBtn = ({
|
||||
const balance = useSpaceTokenBalance()
|
||||
const { refetch: refetchEth } = useQueryEthBalance()
|
||||
const address = useAddress()
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const trade = useTrades()
|
||||
const wagmiConfig = useWagmiConfig()
|
||||
const checkChain = useCheckChain()
|
||||
@@ -80,12 +80,13 @@ export const BuyBtn = ({
|
||||
)
|
||||
return (
|
||||
<Button
|
||||
variant="brand"
|
||||
className="h-[50px] w-full rounded-xl"
|
||||
disabled={!isAmountValid || isInsufficientBalance || loading}
|
||||
onClick={() => onBuy()}
|
||||
>
|
||||
{loading ? (
|
||||
<LoadingDots />
|
||||
<LoadingDots />
|
||||
) : isInsufficientBalance ? (
|
||||
'Insufficient ETH balance'
|
||||
) : isAmountValid ? (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from 'react'
|
||||
import { useEthBalance } from '@/app/(creator-fi)/hooks/useEthBalance'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { precision } from '@/lib/math'
|
||||
import { toFloorFixed } from '@/lib/utils'
|
||||
@@ -13,7 +13,7 @@ export const BuyPanel = () => {
|
||||
const [ethAmount, setEthAmount] = useState<string>('')
|
||||
const [tokenAmount, setTokenAmount] = useState<string>('')
|
||||
const { ethBalance } = useEthBalance()
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
|
||||
const isAmountValid = parseFloat(ethAmount) > 0 && parseFloat(tokenAmount) > 0
|
||||
|
||||
@@ -66,7 +66,7 @@ export const BuyPanel = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-4 rounded-xl bg-gray-100 p-4 dark:bg-zinc-900">
|
||||
<div className="mb-4 rounded-xl bg-foreground/5 p-4">
|
||||
<div className="text-sm">Buy</div>
|
||||
<AmountInput
|
||||
symbolName={space.symbolName}
|
||||
|
||||
@@ -81,12 +81,13 @@ export const SellBtn = ({
|
||||
<>
|
||||
{address ? (
|
||||
<Button
|
||||
variant="brand"
|
||||
className="h-[50px] w-full rounded-xl"
|
||||
disabled={!isAmountValid || isInsufficientBalance || loading}
|
||||
onClick={() => onSell()}
|
||||
>
|
||||
{loading ? (
|
||||
<LoadingDots />
|
||||
<LoadingDots />
|
||||
) : isInsufficientBalance ? (
|
||||
`Insufficient ${space.symbolName} balance`
|
||||
) : isAmountValid ? (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useState } from 'react'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { precision } from '@/lib/math'
|
||||
import { toFloorFixed } from '@/lib/utils'
|
||||
@@ -12,7 +12,7 @@ import { SpaceTokenBalance } from './SpaceTokenBalance'
|
||||
export const SellPanel = () => {
|
||||
const [ethAmount, setEthAmount] = useState<string>('')
|
||||
const [tokenAmount, setTokenAmount] = useState<string>('')
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { data: tokenBalance } = useSpaceTokenBalance()
|
||||
|
||||
const isAmountValid = parseFloat(tokenAmount) > 0
|
||||
@@ -50,7 +50,7 @@ export const SellPanel = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="mb-2 rounded-xl bg-gray-100 p-4 dark:bg-zinc-900">
|
||||
<div className="mb-2 rounded-xl bg-foreground/5 p-4">
|
||||
<div className="text-sm">Sell</div>
|
||||
|
||||
<AmountInput
|
||||
@@ -83,7 +83,7 @@ export const SellPanel = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mb-4 rounded-xl bg-gray-100 p-4 dark:bg-zinc-900">
|
||||
<div className="mb-4 rounded-xl bg-foreground/5 p-4">
|
||||
<div className="text-sm">Buy</div>
|
||||
|
||||
<AmountInput
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useAddress } from '@/app/(creator-fi)/hooks/useAddress'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { spaceAbi } from '@/lib/abi'
|
||||
import { Address } from 'viem'
|
||||
import { useReadContract } from 'wagmi'
|
||||
@@ -11,7 +11,7 @@ export const formatAmount = (value: string): string => {
|
||||
|
||||
export function useSpaceTokenBalance() {
|
||||
const address = useAddress()
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
return useReadContract({
|
||||
address: space.address as Address,
|
||||
abi: spaceAbi,
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
'use client'
|
||||
|
||||
import { useQueryEthBalance } from '@/app/(creator-fi)/hooks/useEthBalance'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -7,8 +9,6 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { useQueryEthBalance } from '@/app/(creator-fi)/hooks/useEthBalance'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { MemberForm } from './MemberForm'
|
||||
import { useMemberDialog } from './useMemberDialog'
|
||||
|
||||
@@ -16,7 +16,7 @@ interface Props {}
|
||||
|
||||
export function MemberDialog({}: Props) {
|
||||
const { isOpen, setIsOpen } = useMemberDialog()
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
useQueryEthBalance()
|
||||
|
||||
return (
|
||||
@@ -26,8 +26,8 @@ export function MemberDialog({}: Props) {
|
||||
<DialogHeader>
|
||||
<DialogTitle>Subscription</DialogTitle>
|
||||
<div className="text-sm text-neutral-600">
|
||||
Subscribe to become a member of the <span className="font-bold">{space.name}</span>{' '}
|
||||
space.
|
||||
Subscribe to become a member of the{' '}
|
||||
<span className="font-bold">{space.name}</span> space.
|
||||
</div>
|
||||
</DialogHeader>
|
||||
<MemberForm space={space} />
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use client'
|
||||
|
||||
import { forwardRef } from 'react'
|
||||
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
|
||||
import { useEthBalance } from '@/app/(creator-fi)/hooks/useEthBalance'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useTokenBalance } from '@/app/(creator-fi)/hooks/useTokenBalance'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
|
||||
import { precision } from '@/lib/math'
|
||||
|
||||
interface Props {
|
||||
@@ -14,7 +14,7 @@ interface Props {
|
||||
|
||||
export const TokenSelect = forwardRef<HTMLDivElement, Props>(
|
||||
function TokenSelect({ value, onChange }, ref) {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { ethBalance } = useEthBalance()
|
||||
const { data } = useTokenBalance()
|
||||
const isEth = value === 'ETH'
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, { forwardRef } from 'react'
|
||||
import { matchNumber } from '@/lib/utils'
|
||||
import { Input } from '../../../components/ui/input'
|
||||
import { Input } from '@/components/ui/input'
|
||||
|
||||
export interface NumberInputProps
|
||||
extends Omit<
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use client'
|
||||
|
||||
import { ReactNode, useState } from 'react'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { useSpaceContext } from '../../../components/SpaceContext'
|
||||
|
||||
enum TabTypes {
|
||||
Holders = 'Holders',
|
||||
@@ -12,11 +12,8 @@ enum TabTypes {
|
||||
export const dynamic = 'force-static'
|
||||
|
||||
export default function Layout({ children }: { children: ReactNode }) {
|
||||
const { space } = useSpace()
|
||||
const [type, setType] = useState(TabTypes.Trades)
|
||||
|
||||
if (!space) return null
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="mx-auto mt-4 flex w-full flex-col gap-12 p-3 sm:w-full">
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
'use client'
|
||||
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useSpaceContext } from '../../../../components/SpaceContext'
|
||||
import { MemberList } from '../../Space/MemberList'
|
||||
|
||||
export const dynamic = 'force-static'
|
||||
// export const revalidate = 3600 * 24
|
||||
|
||||
export default function Page() {
|
||||
const { space } = useSpace()
|
||||
|
||||
if (!space) return null
|
||||
const space = useSpaceContext()
|
||||
return <MemberList space={space}></MemberList>
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
'use client'
|
||||
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { PlateEditor } from '@/components/editor/plate-editor'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
|
||||
export const dynamic = 'force-static'
|
||||
|
||||
export default function Page() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
|
||||
return <PlateEditor value={space.aboutJson} readonly />
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ import { useForm } from 'react-hook-form'
|
||||
import { NumberInput } from '@/app/(creator-fi)/components/NumberInput'
|
||||
import { editorDefaultValue } from '@/app/(creator-fi)/constants'
|
||||
import { useEthPrice } from '@/app/(creator-fi)/hooks/useEthPrice'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import LoadingDots from '@/components/icons/loading-dots'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Form,
|
||||
@@ -38,7 +38,7 @@ const FormSchema = z.object({
|
||||
export function AddPlanForm() {
|
||||
const [isLoading, setLoading] = useState(false)
|
||||
const { setIsOpen } = useAddPlanDialog()
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { ethPrice } = useEthPrice()
|
||||
const wagmiConfig = useWagmiConfig()
|
||||
const checkChain = useCheckChain()
|
||||
|
||||
@@ -5,9 +5,9 @@ import { Plan } from '@/app/(creator-fi)/domains/Plan'
|
||||
import { useAddress } from '@/app/(creator-fi)/hooks/useAddress'
|
||||
import { useEthPrice } from '@/app/(creator-fi)/hooks/useEthPrice'
|
||||
import { useMembers } from '@/app/(creator-fi)/hooks/useMembers'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useSubscriptions } from '@/app/(creator-fi)/hooks/useSubscriptions'
|
||||
import { PlateEditor } from '@/components/editor/plate-editor'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card } from '@/components/ui/card'
|
||||
import { useConnectModal } from '@rainbow-me/rainbowkit'
|
||||
@@ -23,7 +23,7 @@ export function PlanItem({ plan }: Props) {
|
||||
const address = useAddress()
|
||||
const { ethPrice } = useEthPrice()
|
||||
const { setState } = useUpdatePlanDialog()
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { isConnected } = useAccount()
|
||||
const { openConnectModal } = useConnectModal()
|
||||
const { subscriptions } = useSubscriptions()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { MemberDialog } from '@/app/(creator-fi)/components/MemberDialog/MemberDialog'
|
||||
import { useAddress } from '@/app/(creator-fi)/hooks/useAddress'
|
||||
import { usePlans } from '@/app/(creator-fi)/hooks/usePlans'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { AddPlanDialog } from './AddPlanDialog/AddPlanDialog'
|
||||
import { PlanItem } from './PlanItem'
|
||||
import { UpdatePlanDialog } from './UpdatePlanDialog/UpdatePlanDialog'
|
||||
@@ -12,7 +12,7 @@ interface Props {}
|
||||
|
||||
export function PlanList({}: Props) {
|
||||
const { plans, isLoading } = usePlans()
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const address = useAddress()
|
||||
|
||||
if (isLoading) return <div className="text-foreground/60">Loading...</div>
|
||||
|
||||
@@ -6,9 +6,9 @@ import { NumberInput } from '@/app/(creator-fi)/components/NumberInput'
|
||||
import { PlanStatus } from '@/app/(creator-fi)/domains/Plan'
|
||||
import { useEthPrice } from '@/app/(creator-fi)/hooks/useEthPrice'
|
||||
import { usePlans } from '@/app/(creator-fi)/hooks/usePlans'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { PlateEditor } from '@/components/editor/plate-editor'
|
||||
import LoadingDots from '@/components/icons/loading-dots'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import {
|
||||
Form,
|
||||
@@ -44,7 +44,7 @@ export function UpdatePlanForm() {
|
||||
const [isLoading, setLoading] = useState(false)
|
||||
const wagmiConfig = useWagmiConfig()
|
||||
const { setIsOpen } = useUpdatePlanDialog()
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { ethPrice } = useEthPrice()
|
||||
const { plan } = useUpdatePlanDialog()
|
||||
const { refetch } = usePlans()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useMemo, useState } from 'react'
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import LoadingDots from '@/components/icons/loading-dots'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { WalletConnectButton } from '@/components/WalletConnectButton'
|
||||
import { useCheckChain } from '@/hooks/useCheckChain'
|
||||
@@ -25,7 +25,7 @@ export const StakingPanel = () => {
|
||||
const { writeContractAsync } = useWriteContract()
|
||||
const [tokenAmount, setTokenAmount] = useState<string>('')
|
||||
const { data: tokenBalance } = useSpaceTokenBalance()
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { isConnected } = useAccount()
|
||||
const wagmiConfig = useWagmiConfig()
|
||||
const checkChain = useCheckChain()
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
'use client'
|
||||
|
||||
import { useSpace } from '@/app/(creator-fi)/hooks/useSpace'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { SubscriptionRecordList } from '../../Space/SubscriptionRecordList'
|
||||
|
||||
export const dynamic = 'force-static'
|
||||
|
||||
export default function Page() {
|
||||
const { space } = useSpace()
|
||||
if (!space) return
|
||||
const space = useSpaceContext()
|
||||
return <SubscriptionRecordList space={space} />
|
||||
}
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
import { getSite, getSpace } from '@/lib/fetchers'
|
||||
import { Transaction } from '../../Space/Transaction'
|
||||
|
||||
export const dynamic = 'force-static'
|
||||
export const revalidate = 3600 * 24
|
||||
|
||||
export default function Page() {
|
||||
export default async function Page() {
|
||||
const site = await getSite()
|
||||
if (!site?.spaceId) return null
|
||||
const space = await getSpace(site.spaceId)
|
||||
|
||||
return (
|
||||
<div className="flex h-[80vh] items-center justify-center">
|
||||
<div className="w-full space-y-8 md:w-[480px]">
|
||||
<div className="text-center text-4xl font-bold">Trade token</div>
|
||||
<div className="text-center text-4xl font-bold">
|
||||
Trade ${space.symbol} token
|
||||
</div>
|
||||
<Transaction />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { spaceAbi } from '@/lib/abi'
|
||||
import { Address } from 'viem'
|
||||
import { useReadContract } from 'wagmi'
|
||||
import { useSpace } from './useSpace'
|
||||
|
||||
export function useContributors() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { data: contributors = [], ...rest } = useReadContract({
|
||||
address: space.address as Address,
|
||||
abi: spaceAbi,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { RESPACE_SUBGRAPH_URL } from '@/lib/constants'
|
||||
import { Holder } from '@/lib/types'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { gql, request } from 'graphql-request'
|
||||
import { useSpace } from './useSpace'
|
||||
|
||||
export function useHolders() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
|
||||
const query = gql`
|
||||
query getHolders($spaceAddress: String!) {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { spaceAbi } from '@/lib/abi'
|
||||
import { Address } from 'viem'
|
||||
import { useReadContract } from 'wagmi'
|
||||
import { useSpace } from './useSpace'
|
||||
|
||||
export function useMembers() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { data: members = [], ...rest } = useReadContract({
|
||||
address: space.address as Address,
|
||||
abi: spaceAbi,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { Plan, PlanInfo } from '@/app/(creator-fi)/domains/Plan'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { useWagmiConfig } from '@/hooks/useWagmiConfig'
|
||||
import { spaceAbi } from '@/lib/abi'
|
||||
import { isIPFSCID } from '@/lib/utils'
|
||||
@@ -9,7 +10,7 @@ import { IPFS_GATEWAY } from '../constants'
|
||||
import { useSpace } from './useSpace'
|
||||
|
||||
export function usePlans() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const wagmiConfig = useWagmiConfig()
|
||||
const { data: plans = [], ...rest } = useQuery({
|
||||
queryKey: ['plans', space.address],
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { spaceAbi } from '@/lib/abi'
|
||||
import { Address } from 'viem'
|
||||
import { useReadContract } from 'wagmi'
|
||||
import { useSpace } from './useSpace'
|
||||
|
||||
export function useShareOrders() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { data: orders = [], ...rest } = useReadContract({
|
||||
address: space.address as Address,
|
||||
abi: spaceAbi,
|
||||
|
||||
@@ -20,7 +20,6 @@ export function useSpace() {
|
||||
|
||||
export function useQuerySpace() {
|
||||
const spaceId = getSpaceId()
|
||||
console.log('=========spaceId:', spaceId)
|
||||
|
||||
const { data, ...rest } = useQuery({
|
||||
queryKey: ['space'],
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { RESPACE_SUBGRAPH_URL } from '@/lib/constants'
|
||||
import { SubscriptionRecord, Trade } from '@/lib/types'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { gql, request } from 'graphql-request'
|
||||
import { useSpace } from './useSpace'
|
||||
|
||||
export function useSubscriptionRecords() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
|
||||
const query = gql`
|
||||
query getSubscriptionRecords($spaceAddress: String!) {
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Subscription } from '@/app/(creator-fi)/domains/Subscription'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { spaceAbi } from '@/lib/abi'
|
||||
import { Address } from 'viem'
|
||||
import { useReadContract } from 'wagmi'
|
||||
import { useSpace } from './useSpace'
|
||||
|
||||
export function useSubscriptions() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { data = [], ...rest } = useReadContract({
|
||||
address: space.address as Address,
|
||||
abi: spaceAbi,
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import { EthBalance } from '@/app/(creator-fi)/domains/EthBalance'
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { spaceAbi } from '@/lib/abi'
|
||||
import { atom } from 'jotai'
|
||||
import { Address } from 'viem'
|
||||
import { useReadContract } from 'wagmi'
|
||||
import { useAddress } from './useAddress'
|
||||
import { useSpace } from './useSpace'
|
||||
|
||||
export const ethBalanceAtom = atom<EthBalance>({} as EthBalance)
|
||||
|
||||
export function useTokenBalance() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const address = useAddress()
|
||||
const res = useReadContract({
|
||||
address: space.address as Address,
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { RESPACE_SUBGRAPH_URL } from '@/lib/constants'
|
||||
import { Trade } from '@/lib/types'
|
||||
import { useQuery } from '@tanstack/react-query'
|
||||
import { gql, request } from 'graphql-request'
|
||||
import { useSpace } from './useSpace'
|
||||
|
||||
export function useTrades() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
|
||||
const query = gql`
|
||||
query getTrades($spaceAddress: String!) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { useSpaceContext } from '@/components/SpaceContext'
|
||||
import { spaceAbi } from '@/lib/abi'
|
||||
import { Address } from 'viem'
|
||||
import { useReadContract } from 'wagmi'
|
||||
@@ -13,7 +14,7 @@ export type Vesting = {
|
||||
}
|
||||
|
||||
export function useVestings() {
|
||||
const { space } = useSpace()
|
||||
const space = useSpaceContext()
|
||||
const { data: vestings = [], ...rest } = useReadContract({
|
||||
address: space.address as Address,
|
||||
abi: spaceAbi,
|
||||
|
||||
@@ -1,17 +1,27 @@
|
||||
'use client'
|
||||
|
||||
import { getSite, getSpace } from '@/lib/fetchers'
|
||||
import { StoreProvider } from '@/store'
|
||||
import { Toaster } from 'sonner'
|
||||
import { SpaceProvider } from '../../components/SpaceContext'
|
||||
import { CreatorFiLayout } from './CreatorFiLayout'
|
||||
|
||||
export default function Layout({ children }: { children: React.ReactNode }) {
|
||||
export default async function Layout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
const site = await getSite()
|
||||
if (!site?.spaceId) return null
|
||||
const space = await getSpace(site.spaceId)
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-foreground/5">
|
||||
<StoreProvider>
|
||||
<Toaster className="dark:hidden" />
|
||||
<Toaster theme="dark" className="hidden dark:block" />
|
||||
<CreatorFiLayout>{children}</CreatorFiLayout>
|
||||
</StoreProvider>
|
||||
<SpaceProvider space={space}>
|
||||
<StoreProvider>
|
||||
<Toaster className="dark:hidden" />
|
||||
<Toaster theme="dark" className="hidden dark:block" />
|
||||
<CreatorFiLayout space={space}>{children}</CreatorFiLayout>
|
||||
</StoreProvider>
|
||||
</SpaceProvider>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -25,8 +25,8 @@ export function PostActions({ post, receivers }: Props) {
|
||||
<TippersDialog post={post} receivers={receivers} />
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
{typeof post.creationId === 'number' && <CollectButton post={post} />}
|
||||
<TipTokenButton post={post} receivers={receivers} />
|
||||
{typeof post.creationId === 'number' && <CollectButton post={post} />}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -11,6 +11,7 @@ import {
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog'
|
||||
import { useAllocationCap } from '@/hooks/useAllocationCap'
|
||||
import { useTipInfo } from '@/hooks/useTipInfo'
|
||||
import { useTipStats } from '@/hooks/useTipStats'
|
||||
import { useWagmiConfig } from '@/hooks/useWagmiConfig'
|
||||
import { tipAbi } from '@/lib/abi'
|
||||
@@ -22,6 +23,7 @@ import { toFloorFixed } from '@/lib/utils'
|
||||
import { Post } from '@penxio/types'
|
||||
import { readContract, waitForTransactionReceipt } from '@wagmi/core'
|
||||
import { SetStateAction } from 'jotai'
|
||||
import { useParams } from 'next/navigation'
|
||||
import pRetry, { AbortError } from 'p-retry'
|
||||
import { toast } from 'sonner'
|
||||
import { Address } from 'viem'
|
||||
@@ -49,6 +51,7 @@ export function TipTokenDialog({
|
||||
receivers,
|
||||
}: Props) {
|
||||
const [amount, setAmount] = useState('1')
|
||||
const params = useParams()
|
||||
const { address = '' } = useAccount()
|
||||
let { data: executionFee } = useReadContract({
|
||||
address: addressMap.Tip,
|
||||
@@ -56,7 +59,8 @@ export function TipTokenDialog({
|
||||
functionName: 'executionFee',
|
||||
})
|
||||
|
||||
const { refetch: refetchTipInfo } = useTipStats(receivers)
|
||||
const { refetch: refetchTipStats } = useTipStats(receivers)
|
||||
const { refetch: refetchTipInfo } = useTipInfo(post.id)
|
||||
const { data: data, isLoading: isLoadingCap, refetch } = useAllocationCap()
|
||||
|
||||
const { writeContractAsync } = useWriteContract()
|
||||
@@ -122,7 +126,11 @@ export function TipTokenDialog({
|
||||
toast.success('Tip $PEN successfully')
|
||||
await refetch()
|
||||
setTimeout(() => {
|
||||
refetchTipInfo()
|
||||
if (params?.slug) {
|
||||
refetchTipInfo()
|
||||
} else {
|
||||
refetchTipStats()
|
||||
}
|
||||
}, 4000)
|
||||
} catch (error) {
|
||||
console.log('====error>>>:', error)
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
|
||||
import { Dispatch, SetStateAction } from 'react'
|
||||
import { Skeleton } from '@/components/ui/skeleton'
|
||||
import { useTipInfo } from '@/hooks/useTipInfo'
|
||||
import { useTipStats } from '@/hooks/useTipStats'
|
||||
import { precision } from '@/lib/math'
|
||||
import { Post } from '@penxio/types'
|
||||
import { DollarSign } from 'lucide-react'
|
||||
import { useParams } from 'next/navigation'
|
||||
|
||||
interface Props {
|
||||
post: Post
|
||||
@@ -12,7 +15,31 @@ interface Props {
|
||||
setIsOpen: Dispatch<SetStateAction<boolean>>
|
||||
}
|
||||
|
||||
export function TippedAmount({ post, receivers, setIsOpen }: Props) {
|
||||
export function TippedAmount(props: Props) {
|
||||
const params = useParams()
|
||||
const slug = params.slug
|
||||
|
||||
if (slug) {
|
||||
return <TippedAmountInPostDetail {...props} />
|
||||
}
|
||||
return <TippedAmountInHome {...props} />
|
||||
}
|
||||
|
||||
export function TippedAmountInPostDetail({ post, setIsOpen }: Props) {
|
||||
const { data, isLoading } = useTipInfo(post.id)
|
||||
if (isLoading) return <Skeleton className="h-6 w-12" />
|
||||
return (
|
||||
<div
|
||||
className="flex items-center justify-between text-foreground gap-1 cursor-pointer opacity-70 hover:opacity-100"
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
<DollarSign size={18} />
|
||||
<div> {!data ? '0' : precision.toDecimal(data?.totalAmount)}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function TippedAmountInHome({ post, receivers, setIsOpen }: Props) {
|
||||
const { data = [], isLoading } = useTipStats(receivers)
|
||||
if (isLoading) return <Skeleton className="h-6 w-12" />
|
||||
const item = data.find((i) => i.uri === post.id)
|
||||
@@ -22,7 +49,8 @@ export function TippedAmount({ post, receivers, setIsOpen }: Props) {
|
||||
className="flex items-center justify-between text-foreground gap-1 cursor-pointer opacity-70 hover:opacity-100"
|
||||
onClick={() => setIsOpen(true)}
|
||||
>
|
||||
<span className="i-[ri--quill-pen-ai-fill]"></span>
|
||||
{/* <span className="i-[ri--quill-pen-ai-fill]"></span> */}
|
||||
<DollarSign size={18} />
|
||||
<div> {!data ? '0' : precision.toDecimal(item?.totalAmount)}</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
26
components/SpaceContext.tsx
Normal file
26
components/SpaceContext.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
'use client'
|
||||
|
||||
import { createContext, PropsWithChildren, useContext } from 'react'
|
||||
import { SpaceType } from '@/lib/types'
|
||||
import { Space } from '../app/(creator-fi)/domains/Space'
|
||||
|
||||
export const SpaceContext = createContext({} as Space)
|
||||
|
||||
interface Props {
|
||||
space: SpaceType
|
||||
}
|
||||
|
||||
export const SpaceProvider = ({
|
||||
space,
|
||||
children,
|
||||
}: PropsWithChildren<Props>) => {
|
||||
return (
|
||||
<SpaceContext.Provider value={new Space(space)}>
|
||||
{children}
|
||||
</SpaceContext.Provider>
|
||||
)
|
||||
}
|
||||
|
||||
export function useSpaceContext() {
|
||||
return useContext(SpaceContext)
|
||||
}
|
||||
@@ -39,7 +39,7 @@ const DialogContent = React.forwardRef<
|
||||
<DialogPrimitive.Content
|
||||
ref={ref}
|
||||
className={cn(
|
||||
'fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg',
|
||||
'fixed left-[50%] top-[50%] z-50 grid max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] rounded-lg w-11/12',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
@@ -8,7 +8,7 @@ type TipInfo = {
|
||||
uri: string
|
||||
}
|
||||
|
||||
export function useTipStats(receivers: string[]) {
|
||||
export function useTipStats(receivers: string[] = []) {
|
||||
const query = gql`
|
||||
query geTips($receivers: [Bytes]) {
|
||||
tips(where: { receiver_in: $receivers }) {
|
||||
@@ -30,7 +30,7 @@ export function useTipStats(receivers: string[]) {
|
||||
},
|
||||
})
|
||||
},
|
||||
enabled: !!receivers,
|
||||
enabled: receivers.length > 0,
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import prisma from '@/lib/prisma'
|
||||
import { getSite as getSiteInfo } from '@/server/lib/getSite'
|
||||
import ky from 'ky'
|
||||
import { unstable_cache } from 'next/cache'
|
||||
import { PostStatus } from './constants'
|
||||
import { PostStatus, RESPACE_BASE_URI } from './constants'
|
||||
import { SpaceType } from './types'
|
||||
import { getUrl } from './utils'
|
||||
|
||||
export async function getSite() {
|
||||
@@ -113,3 +115,19 @@ export async function getTagWithPost(name: string) {
|
||||
// },
|
||||
// )()
|
||||
// }
|
||||
|
||||
export async function getSpace(spaceId: string) {
|
||||
return await unstable_cache(
|
||||
async () => {
|
||||
const response = await ky
|
||||
.get(RESPACE_BASE_URI + `/api/get-space?address=${spaceId}`)
|
||||
.json<SpaceType>()
|
||||
return response
|
||||
},
|
||||
[`space-${spaceId}`],
|
||||
{
|
||||
revalidate: 10,
|
||||
tags: [`space-${spaceId}`],
|
||||
},
|
||||
)()
|
||||
}
|
||||
|
||||
@@ -23,8 +23,8 @@ module.exports = {
|
||||
'penx-theme-micro',
|
||||
'penx-theme-card',
|
||||
'penx-theme-minimal',
|
||||
'penx-theme-photo',
|
||||
'penx-theme-garden',
|
||||
'penx-theme-photo',
|
||||
],
|
||||
|
||||
images: {
|
||||
|
||||
Reference in New Issue
Block a user