Skip to content

Commit

Permalink
feat: display power ranking
Browse files Browse the repository at this point in the history
  • Loading branch information
DIYgod committed Oct 15, 2024
1 parent 8b6c3f9 commit 1150289
Show file tree
Hide file tree
Showing 6 changed files with 308 additions and 6 deletions.
3 changes: 0 additions & 3 deletions apps/renderer/src/modules/power/my-wallet-section/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { Trans, useTranslation } from "react-i18next"

import { Button } from "~/components/ui/button"
import { CopyButton } from "~/components/ui/code-highlighter"
import { Divider } from "~/components/ui/divider"
import { LoadingWithIcon } from "~/components/ui/loading"
import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger } from "~/components/ui/tooltip"
import { DAILY_CLAIM_AMOUNT } from "~/constants"
Expand Down Expand Up @@ -127,8 +126,6 @@ export const MyWalletSection = () => {
</Tooltip>
</div>
</div>

<Divider className="my-8" />
</>
)
}
126 changes: 126 additions & 0 deletions apps/renderer/src/modules/power/ranking/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { Fragment } from "react"
import { useTranslation } from "react-i18next"

import { useWhoami } from "~/atoms/user"
import { Avatar, AvatarFallback, AvatarImage } from "~/components/ui/avatar"
import { MotionButtonBase } from "~/components/ui/button"
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "~/components/ui/table"
import { EllipsisHorizontalTextWithTooltip } from "~/components/ui/typography"
import { replaceImgUrlIfNeed } from "~/lib/img-proxy"
import { cn } from "~/lib/utils"
import { usePresentUserProfileModal } from "~/modules/profile/hooks"
import { SettingSectionTitle } from "~/modules/settings/section"
import { Balance } from "~/modules/wallet/balance"
import type { useWalletTransactions } from "~/queries/wallet"
import { useWalletRanking } from "~/queries/wallet"

const medals = ["", "🥇", "🥈", "🥉"]
const rankNumber = (index: number) => {
if (index < medals.length) {
return <span className="-ml-[3px]">{medals[index]}</span>
}
return <span>{index}</span>
}

export const PowerRanking: Component = ({ className }) => {
const { t } = useTranslation("settings")
const ranking = useWalletRanking()

return (
<div className="relative flex min-w-0 grow flex-col">
<SettingSectionTitle title={t("wallet.ranking.title")} />
<div className={cn("w-fit min-w-0 grow overflow-x-auto", className)}>
<Table className="w-full table-fixed text-sm">
<TableHeader className="sticky top-0 bg-theme-background">
<TableRow className="[&_*]:!font-semibold">
<TableHead className="w-20">#</TableHead>
<TableHead>{t("wallet.ranking.name")}</TableHead>
<TableHead>{t("wallet.ranking.power")}</TableHead>
<TableHead>{t("wallet.ranking.level")}</TableHead>
</TableRow>
</TableHeader>
<TableBody>
{ranking.data?.map((row, index) => {
const lastRow = ranking.data?.[index - 1]
const hasGap = lastRow?.rank && row.rank && row.rank - lastRow.rank !== 1

return (
<Fragment key={row.userId}>
{!!hasGap && (
<>
<TableRow>
<TableCell className="py-2">...</TableCell>
</TableRow>
<TableRow>
<div className="h-px w-full" />
</TableRow>
</>
)}
<TableRow>
<TableCell className="py-2">{!!row.rank && rankNumber(row.rank)}</TableCell>
<TableCell className="py-2">
<UserRenderer user={row.user} />
</TableCell>
<TableCell className="py-2">
<Balance>{row.powerToken}</Balance>
</TableCell>
<TableCell className="py-2">{row.level}</TableCell>
</TableRow>
</Fragment>
)
})}
<TableRow>
<TableCell className="py-2">...</TableCell>
</TableRow>
</TableBody>
</Table>
</div>
</div>
)
}

const UserRenderer = ({
user,
}: {
user?: NonNullable<ReturnType<typeof useWalletTransactions>["data"]>[number][
| "fromUser"
| "toUser"]
}) => {
const { t } = useTranslation("settings")
const me = useWhoami()
const isMe = user?.id === me?.id

const name = isMe ? t("wallet.transactions.you") : user?.name || APP_NAME

const presentUserModal = usePresentUserProfileModal("drawer")
return (
<MotionButtonBase
onClick={() => {
if (user?.id) presentUserModal(user.id)
}}
className="flex w-full min-w-0 cursor-button items-center gap-2"
>
<Avatar className="aspect-square size-6 duration-200 animate-in fade-in-0">
<AvatarImage src={replaceImgUrlIfNeed(user?.image || undefined)} />
<AvatarFallback>{name?.slice(0, 2)}</AvatarFallback>
</Avatar>

<div className="ml-1 w-0 grow truncate">
<EllipsisHorizontalTextWithTooltip className="text-left">
{isMe ? (
<span className="font-bold">{t("wallet.transactions.you")}</span>
) : (
<span>{name}</span>
)}
</EllipsisHorizontalTextWithTooltip>
</div>
</MotionButtonBase>
)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useTranslation } from "react-i18next"

import { Divider } from "~/components/ui/divider"
import { MyWalletSection } from "~/modules/power/my-wallet-section"
import { PowerRanking } from "~/modules/power/ranking"
import { TransactionsSection } from "~/modules/power/transaction-section"

import { useSubViewTitle } from "../hooks"
Expand All @@ -23,6 +25,10 @@ export function Component() {
</div>
<MyWalletSection />

<Divider className="my-8" />
<PowerRanking />

<Divider className="my-8" />
<TransactionsSection />
</div>
)
Expand Down
16 changes: 16 additions & 0 deletions apps/renderer/src/queries/wallet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,29 @@ export const wallet = {
},
),
},

ranking: {
get: () =>
defineQuery(
["wallet", "ranking"],
async () => {
const res = await apiClient.wallets.ranking.$get()
return res.data
},
{
rootKey: ["wallet", "ranking"],
},
),
},
}

export const useWallet = () => useAuthQuery(wallet.get())

export const useWalletTransactions = (query: Parameters<typeof wallet.transactions.get>[0] = {}) =>
useAuthQuery(wallet.transactions.get(query))

export const useWalletRanking = () => useAuthQuery(wallet.ranking.get())

export const useCreateWalletMutation = () =>
useMutation({
mutationKey: ["createWallet"],
Expand Down
5 changes: 5 additions & 0 deletions locales/settings/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@
"wallet.create.description": "Create a free wallet to receive <PowerIcon /> <strong>Power</strong>, which can be used to reward creators and also get rewarded for your content contributions.",
"wallet.power.dailyClaim": "You can claim {{amount}} free Power daily, which can be used to tip RSS entries on Follow.",
"wallet.power.description": "Power is an <Link>ERC-20 token</Link> on the {{blockchainName}} blockchain.",
"wallet.ranking.level": "Level",
"wallet.ranking.name": "Name",
"wallet.ranking.power": "Power",
"wallet.ranking.rank": "Rank",
"wallet.ranking.title": "Power Ranking",
"wallet.sidebar_title": "Power",
"wallet.transactions.amount": "Amount",
"wallet.transactions.date": "Date",
Expand Down
Loading

0 comments on commit 1150289

Please sign in to comment.