feat: sorting reaction component

This commit is contained in:
DIYgod 2023-03-15 17:50:14 +00:00
parent d7d710005e
commit f9ff893763
No known key found for this signature in database
9 changed files with 146 additions and 124 deletions

View File

@ -30,6 +30,7 @@
"Cancel Reply": "取消回复",
"ago": "{{time}}前",
"joined ago": "{{time}}前加入",
"Like": "点赞",
"Mint to an NFT": "铸造为 NFT",
"Like successfull": "点赞成功",
"Mint successfull": "铸造成功",
@ -59,5 +60,6 @@
"One-time": "一次性",
"Monthly and NFT Rewards": "每月和 NFT 奖励",
"Coming soon": "即将推出",
"What is Mira? Where can I get some?" : "Mira 是什么?我在哪里可以获得?"
"What is Mira? Where can I get some?" : "Mira 是什么?我在哪里可以获得?",
"Tip": "赞赏"
}

View File

@ -14,7 +14,9 @@ export const CharacterList: React.FC<{
setOpen: (open: boolean) => void
hasMore: boolean
loadMore: () => Promise<void>
list: any[]
list: {
list: any[]
}[]
title: string
}> = ({ open, setOpen, hasMore, loadMore, list, title }) => {
const { t } = useTranslation("common")
@ -33,44 +35,49 @@ export const CharacterList: React.FC<{
useWindow={false}
>
{list?.length ? (
list.map((sub: any, index) => (
<div
className="py-3 flex items-center space-x-2 text-sm"
key={index}
>
<UniLink
href={getSiteLink({
subdomain: sub?.character?.handle,
})}
className="flex items-center space-x-2 text-sm"
>
<CharacterFloatCard siteId={sub?.character?.handle}>
<Avatar
className="align-middle border-2 border-white"
images={sub.character?.metadata?.content?.avatars || []}
name={
sub.character?.metadata?.content?.name ||
sub.character?.handle
list.map((page) =>
page.list?.map((sub: any, index) => {
const character = sub?.character || sub?.fromCharacter
return (
<div
className="py-3 flex items-center space-x-2 text-sm"
key={index}
>
<UniLink
href={getSiteLink({
subdomain: character?.handle,
})}
className="flex items-center space-x-2 text-sm"
>
<CharacterFloatCard siteId={character?.handle}>
<Avatar
className="align-middle border-2 border-white"
images={character?.metadata?.content?.avatars || []}
name={
character?.metadata?.content?.name ||
character?.handle
}
size={40}
/>
</CharacterFloatCard>
<span>{character?.metadata?.content?.name}</span>
<span className="text-zinc-400 truncate max-w-xs">
@{character?.handle}
</span>
</UniLink>
<UniLink
href={
CSB_SCAN +
"/tx/" +
(sub.metadata?.proof || sub.transactionHash)
}
size={40}
/>
</CharacterFloatCard>
<span>{sub.character?.metadata?.content?.name}</span>
<span className="text-zinc-400 truncate max-w-xs">
@{sub.character?.handle}
</span>
</UniLink>
<UniLink
href={
CSB_SCAN +
"/tx/" +
(sub.metadata?.proof || sub.transactionHash)
}
>
<BlockchainIcon />
</UniLink>
</div>
))
>
<BlockchainIcon />
</UniLink>
</div>
)
}),
)
) : (
<div className="py-3 text-center text-zinc-300">
{t("No Content Yet.")}

View File

@ -16,7 +16,6 @@ import { CharacterFloatCard } from "./CharacterFloatCard"
import { UniLink } from "../ui/UniLink"
import { getSiteLink } from "~/lib/helpers"
import { CSB_SCAN } from "~/lib/env"
import { BlockchainIcon } from "../icons/BlockchainIcon"
export const PatronModal: React.FC<{
site: Profile | undefined | null

View File

@ -21,23 +21,23 @@ import { cn } from "~/lib/utils"
import { Tooltip } from "~/components/ui/Tooltip"
import confetti from "canvas-confetti"
import { Trans, useTranslation } from "next-i18next"
import { Profile } from "~/lib/types"
export const Reactions: React.FC<{
className?: string
size?: "sm" | "base"
pageId?: string
}> = ({ className, size, pageId }) => {
site?: Profile | null
}> = ({ className, size, pageId, site }) => {
const toggleLikePage = useToggleLikePage()
const mintPage = useMintPage()
const { t } = useTranslation("common")
// like
const userSite = useAccountSites()
const [isLikeOpen, setIsLikeOpen] = useState(false)
const [isMintOpen, setIsMintOpen] = useState(false)
const [isLikeListOpen, setIsLikeListOpen] = useState(false)
const [isMintListOpen, setIsMintListOpen] = useState(false)
const likeRef = useRef<HTMLButtonElement>(null)
const mintRef = useRef<HTMLButtonElement>(null)
const [likes, likesMutation] = useGetLikes({ pageId })
const [likeStatus] = useCheckLike({
@ -51,12 +51,6 @@ export const Reactions: React.FC<{
}
}
const mints = useGetMints({
pageId: pageId,
includeCharacter: size !== "sm",
})
const isMint = useCheckMint(pageId)
const like = () => {
if (pageId) {
if (likeStatus.isLiked) {
@ -87,6 +81,23 @@ export const Reactions: React.FC<{
}
}, [toggleLikePage.isSuccess])
// mint
const [isMintOpen, setIsMintOpen] = useState(false)
const [isMintListOpen, setIsMintListOpen] = useState(false)
const mintRef = useRef<HTMLButtonElement>(null)
const mints = useGetMints({
pageId: pageId,
includeCharacter: size !== "sm",
})
const isMint = useCheckMint(pageId)
const loadMoreMints = async () => {
if (mints.hasNextPage && !mints.isFetchingNextPage) {
await mints.fetchNextPage()
}
}
const mint = () => {
if (pageId) {
if (isMint.data?.count) {
@ -123,41 +134,16 @@ export const Reactions: React.FC<{
}
}, [mintPage.isSuccess])
const [mintList, setMintList] = useState<any[]>([])
const [mintCursor, setMintCursor] = useState<string>()
useEffect(() => {
if (mints.isSuccess && mints.data) {
setMintList(mints.data.list || [])
setMintCursor(mints.data.cursor || "")
}
}, [mints.isSuccess, mints.data])
const loadMoreMints = async () => {
if (mintCursor && pageId) {
const subs = await getMints({
pageId: pageId,
cursor: mintCursor,
})
setMintList((prev) => [...prev, ...(subs?.list || [])])
setMintCursor(subs?.cursor || "")
}
}
return (
<>
<div
className={cn(
"xlog-reactions flex fill-gray-400 text-gray-500 items-center",
size === "sm" ? "text-sm" : "",
"xlog-reactions flex fill-gray-400 text-gray-500 sm:items-center",
size === "sm" ? "text-sm space-x-3" : "space-x-6 sm:space-x-10",
className,
)}
>
<div
className={cn(
"xlog-reactions-like flex items-center",
size === "sm" ? "mr-3" : "mr-10",
)}
>
<div className={cn("xlog-reactions-like flex items-center sm:mb-0")}>
<Button
variant="like"
className={`flex items-center mr-2 ${
@ -168,17 +154,28 @@ export const Reactions: React.FC<{
isLoading={userSite.isLoading || toggleLikePage.isPending}
ref={likeRef}
>
<span
className={cn(
"i-mingcute:thumb-up-2-fill mr-1",
size === "sm" ? "text-base" : "text-[40px]",
)}
></span>
{(() => {
const inner = (
<span
className={cn(
"i-mingcute:thumb-up-2-fill mr-1",
size === "sm" ? "text-base" : "text-[40px]",
)}
></span>
)
return size !== "sm" ? (
<Tooltip label={t("Like")} placement="top">
{inner}
</Tooltip>
) : (
inner
)
})()}
<span>{likeCount}</span>
</Button>
{size !== "sm" && (
<ul
className="-space-x-4 cursor-pointer"
className="-space-x-4 cursor-pointer hidden sm:inline-block"
onClick={() => setIsLikeListOpen(true)}
>
{likes
@ -207,38 +204,38 @@ export const Reactions: React.FC<{
)}
</div>
<div className="xlog-reactions-mint flex items-center">
{(() => {
const inner = (
<Button
variant="collect"
className={`flex items-center mr-2 ${
isMint.isSuccess && isMint.data.count && "active"
}`}
isAutoWidth={true}
onClick={mint}
isLoading={mintPage.isLoading}
ref={mintRef}
>
<Button
variant="collect"
className={`flex items-center mr-2 ${
isMint.isSuccess && isMint.data.count && "active"
}`}
isAutoWidth={true}
onClick={mint}
isLoading={mintPage.isLoading}
ref={mintRef}
>
{(() => {
const inner = (
<MintIcon
className={cn("mr-2", size === "sm" ? "w-3 h-3" : "w-8 h-8")}
className={cn(size === "sm" ? "w-3 h-3" : "w-8 h-8")}
/>
<span>{mints.data?.count || 0}</span>
</Button>
)
return size !== "sm" ? (
<Tooltip label={t("Mint to an NFT")} placement="top">
{inner}
</Tooltip>
) : (
inner
)
})()}
)
return size !== "sm" ? (
<Tooltip label={t("Mint to an NFT")} placement="top">
{inner}
</Tooltip>
) : (
inner
)
})()}
<span className="ml-2">{mints.data?.pages?.[0]?.count || 0}</span>
</Button>
{size !== "sm" && (
<ul
className="-space-x-4 cursor-pointer"
className="-space-x-4 cursor-pointer hidden sm:inline-block"
onClick={() => setIsMintListOpen(true)}
>
{mints.data?.list
{mints.data?.pages?.[0]?.list
?.sort((a, b: any) =>
b.character?.metadata?.content?.avatars?.[0] ? 1 : -1,
)
@ -253,10 +250,10 @@ export const Reactions: React.FC<{
/>
</li>
))}
{(mints.data?.count || 0) > 3 && (
{(mints.data?.pages?.[0]?.count || 0) > 3 && (
<li className="inline-block">
<div className="relative align-middle border-2 border-white w-10 h-10 rounded-full inline-flex bg-gray-100 items-center justify-center text-gray-400 font-medium">
+{mints.data!.count - 3}
+{mints.data!.pages?.[0]?.count - 3}
</div>
</li>
)}
@ -320,15 +317,15 @@ export const Reactions: React.FC<{
title={t("Like List")}
loadMore={loadMoreLikes}
hasMore={!!likesMutation.hasNextPage}
list={likes}
list={likesMutation.data?.pages || []}
></CharacterList>
<CharacterList
open={isMintListOpen}
setOpen={setIsMintListOpen}
title={t("Mint List")}
loadMore={loadMoreMints}
hasMore={!!mintCursor}
list={mintList}
hasMore={!!mints.hasNextPage}
list={mints.data?.pages || []}
></CharacterList>
</div>
</>

View File

@ -1,13 +1,14 @@
import { Note } from "~/lib/types"
import { Note, Profile } from "~/lib/types"
import { Comment } from "~/components/common/Comment"
import { Reactions } from "~/components/common/Reactions"
export const PostFooter: React.FC<{
page?: Note | null
}> = ({ page }) => {
site?: Profile | null
}> = ({ page, site }) => {
return (
<>
<Reactions className="mt-14 mb-12" pageId={page?.id} />
<Reactions className="mt-14 mb-12" pageId={page?.id} site={site} />
<Comment page={page} />
</>
)

View File

@ -85,7 +85,7 @@ export const SitePage: React.FC<{
toc={true}
></PageContent>
</article>
{page?.metadata && <PostFooter page={page} />}
{page?.metadata && <PostFooter page={page} site={site} />}
</>
)
}

View File

@ -15,6 +15,7 @@ export type Variant =
| "collect"
| "crossbell"
| "outline"
| "patron"
export type VariantColor = "green" | "red" | "gray" | "gradient" | "black"

View File

@ -153,6 +153,19 @@ a {
fill: #ffcf55;
}
.button.is-patron {
@apply shadow-none p-0;
@apply text-gray-500 fill-gray-500;
}
.button.is-patron:hover {
color: #f87171;
fill: #f87171;
}
.button.is-patron.active {
color: #f87171;
fill: #f87171;
}
.button.is-crossbell {
background-color: #fff5e1;
fill: #e5b65a;

View File

@ -89,9 +89,9 @@ export const useGetMints = (input: {
pageId?: string
includeCharacter?: boolean
}) => {
return useQuery(
["getMints", input.pageId, input.includeCharacter],
async () => {
return useInfiniteQuery({
queryKey: ["getMints", input.pageId, input],
queryFn: async ({ pageParam }) => {
if (!input.pageId) {
return {
count: 0,
@ -102,9 +102,11 @@ export const useGetMints = (input: {
return pageModel.getMints({
pageId: input.pageId,
includeCharacter: input.includeCharacter,
cursor: pageParam,
})
},
)
getNextPageParam: (lastPage) => lastPage.cursor || undefined,
})
}
export const useCheckMint = (pageId: string | undefined) => {