From 1ace096da27ea4d354eef98b9527f23a4d52de40 Mon Sep 17 00:00:00 2001 From: sk1982 Date: Tue, 12 Mar 2024 06:54:31 -0400 Subject: [PATCH] chuni rating --- .../(with-header)/chuni/dashboard/page.tsx | 34 ++++++++++++++++ src/components/chuni/top-rating-sidebar.tsx | 38 ++++++++++++++++++ src/components/chuni/top-rating.tsx | 40 +++++++++++++++++++ src/helpers/floor-dp.ts | 8 ++++ 4 files changed, 120 insertions(+) create mode 100644 src/app/(with-header)/chuni/dashboard/page.tsx create mode 100644 src/components/chuni/top-rating-sidebar.tsx create mode 100644 src/components/chuni/top-rating.tsx create mode 100644 src/helpers/floor-dp.ts diff --git a/src/app/(with-header)/chuni/dashboard/page.tsx b/src/app/(with-header)/chuni/dashboard/page.tsx new file mode 100644 index 0000000..17d6fd8 --- /dev/null +++ b/src/app/(with-header)/chuni/dashboard/page.tsx @@ -0,0 +1,34 @@ +import { getPlaylog } from '@/actions/chuni/playlog'; +import { ChuniNameplate } from '@/components/chuni/nameplate'; +import { ChuniPlaylogCard } from '@/components/chuni/playlog-card'; +import { getUserData, getUserRating } from '@/actions/chuni/profile'; +import { requireUser } from '@/actions/auth'; +import { notFound } from 'next/navigation'; +import { ChuniTopRating } from '@/components/chuni/top-rating'; +import { ChuniTopRatingSidebar } from '@/components/chuni/top-rating-sidebar'; + +export default async function ChuniDashboard() { + const user = await requireUser(); + const [profile, rating, playlog] = await Promise.all([ + getUserData(user), + getUserRating(user), + getPlaylog({ limit: 72 }) + ]) + + if (!profile) return notFound(); + + return (
+ +
+ +
+
+ +
Playlog
+
+ {playlog.data.map((entry, i) => )} +
+
+
); +} + diff --git a/src/components/chuni/top-rating-sidebar.tsx b/src/components/chuni/top-rating-sidebar.tsx new file mode 100644 index 0000000..ed35db0 --- /dev/null +++ b/src/components/chuni/top-rating-sidebar.tsx @@ -0,0 +1,38 @@ +'use client'; + +import { ChuniTopRating, ChuniTopRatingProps } from '@/components/chuni/top-rating'; +import { getUserRating } from '@/actions/chuni/profile'; +import { useState } from 'react'; +import { Button, ButtonGroup } from '@nextui-org/react'; + +export const ChuniTopRatingSidebar = ({ rating }: { rating: Awaited> }) => { + const [shownRating, setShownRating] = useState<'top' | 'recent' | null>('recent'); + + return (
+
+
+
Top
+ +
+
+
Recent
+ +
+
+
+ + + + +
+ Ratings + + + + + +
+ {shownRating && } +
+
); +}; diff --git a/src/components/chuni/top-rating.tsx b/src/components/chuni/top-rating.tsx new file mode 100644 index 0000000..00f7178 --- /dev/null +++ b/src/components/chuni/top-rating.tsx @@ -0,0 +1,40 @@ +import { getUserRating } from '@/actions/chuni/profile'; +import { getJacketUrl } from '@/helpers/assets'; +import { ChuniRating } from '@/components/chuni/rating'; +import { floorToDp } from '@/helpers/floor-dp'; +import { ChuniScoreBadge, getVariantFromRank, getVariantFromScore } from '@/components/chuni/score-badge'; +import { ChuniDifficultyContainer } from '@/components/chuni/difficulty-container'; +import { Tooltip } from '@nextui-org/react'; +import { ChuniLevelBadge } from '@/components/chuni/level-badge'; +import Link from 'next/link'; + +export type ChuniTopRatingProps = { + className?: string, + rating: Awaited>['recent' | 'top'] +}; + +export const ChuniTopRating = ({ rating, className }: ChuniTopRatingProps) => { + return (
+ {rating.map((music, i) =>
+ +
+ {music.title +
+ +
+ +
+ {i + 1}: {music.title} +
+ RATING  + {floorToDp(music.rating, 2)} +
+
+ {music.scoreMax?.toLocaleString()} + {('pastIndex' in music) &&
-{music.pastIndex+1}
} +
+
+
)} +
) +}; diff --git a/src/helpers/floor-dp.ts b/src/helpers/floor-dp.ts new file mode 100644 index 0000000..e0fd2ec --- /dev/null +++ b/src/helpers/floor-dp.ts @@ -0,0 +1,8 @@ +export const floorToDp = (num: number | string, decimals: number) => { + if (typeof num === 'string') { + return num.slice(0, num.indexOf('.') + decimals + 1); + } + + const mult = (10 ** decimals); + return (Math.floor(num * mult) / mult).toFixed(decimals); +};