add acc slider to the pp graph
Some checks failed
Deploy Website / docker (ubuntu-latest) (push) Has been cancelled

This commit is contained in:
Lee 2024-10-21 13:27:47 +01:00
parent b7349f0226
commit 077bb6d73b
2 changed files with 75 additions and 5 deletions

@ -1,10 +1,12 @@
"use client";
import React from "react";
import React, { useState } from "react";
import GenericChart, { DatasetConfig } from "@/components/chart/generic-chart";
import ScoreSaberLeaderboard from "@ssr/common/leaderboard/impl/scoresaber-leaderboard";
import { scoresaberService } from "@ssr/common/service/impl/scoresaber";
import Card from "@/components/card";
import { DualRangeSlider } from "@/components/ui/dual-range-slider";
import { useDebounce } from "@uidotdev/usehooks";
type Props = {
/**
@ -14,10 +16,15 @@ type Props = {
};
export default function LeaderboardPpChart({ leaderboard }: Props) {
const [values, setValues] = useState([60, 100]);
const debouncedMin = useDebounce(values[0], 100);
const histories: Record<string, (number | null)[]> = {};
const labels: string[] = [];
const min = debouncedMin;
const precision = min >= 60 ? 0.1 : 0.2;
for (let accuracy = 60; accuracy <= 100; accuracy += 0.2) {
for (let accuracy = min; accuracy <= 100; accuracy += precision) {
const label = accuracy.toFixed(2) + "%";
labels.push(label);
@ -45,9 +52,24 @@ export default function LeaderboardPpChart({ leaderboard }: Props) {
];
return (
<Card className="h-64 w-full">
<Card className="w-full gap-7">
<div className="flex flex-col h-64">
<p className="font-semibold">PP Curve</p>
<GenericChart labels={labels} datasetConfig={datasetConfig} histories={histories} />
</div>
<div className="flex items-center justify-center">
<div className="w-[95%]">
<DualRangeSlider
label={value => <span>{value}%</span>}
value={values}
onValueChange={setValues}
min={5}
max={100}
step={1}
/>
</div>
</div>
</Card>
);
}

@ -0,0 +1,48 @@
"use client";
import * as React from "react";
import * as SliderPrimitive from "@radix-ui/react-slider";
import { cn } from "@/common/utils";
interface DualRangeSliderProps extends React.ComponentProps<typeof SliderPrimitive.Root> {
labelPosition?: "top" | "bottom";
label?: (value: number | undefined) => React.ReactNode;
}
const DualRangeSlider = React.forwardRef<React.ElementRef<typeof SliderPrimitive.Root>, DualRangeSliderProps>(
({ className, label, labelPosition = "top", ...props }, ref) => {
const initialValue = Array.isArray(props.value) ? props.value : [props.min, props.max];
return (
<SliderPrimitive.Root
ref={ref}
className={cn("relative flex w-full touch-none select-none items-center text-[15px]", className)}
{...props}
>
<SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
<SliderPrimitive.Range className="absolute h-full bg-primary" />
</SliderPrimitive.Track>
{initialValue.map((value, index) => (
<React.Fragment key={index}>
<SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50">
{label && (
<span
className={cn(
"absolute flex w-full justify-center",
labelPosition === "top" && "-top-7",
labelPosition === "bottom" && "top-4"
)}
>
{label(value)}
</span>
)}
</SliderPrimitive.Thumb>
</React.Fragment>
))}
</SliderPrimitive.Root>
);
}
);
DualRangeSlider.displayName = "DualRangeSlider";
export { DualRangeSlider };