More leaderboard types
BIN
src/app/assets/berries/Berry.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/app/assets/berries/CoinBerry.png
Normal file
|
After Width: | Height: | Size: 8.3 KiB |
BIN
src/app/assets/berries/GoldenBerry.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
src/app/assets/berries/PoisonBerry.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
src/app/assets/berries/SlowBerry.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
src/app/assets/berries/SpeedyBerry.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
src/app/assets/berries/UltraBerry.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
@@ -1,11 +1,11 @@
|
||||
@import "tailwindcss";
|
||||
|
||||
.leaderboard-container {
|
||||
@apply flex justify-center;
|
||||
@apply flex items-end justify-center gap-3;
|
||||
}
|
||||
|
||||
.leaderboard-scroll {
|
||||
@apply h-[510px] bg-[#161616] border border-[#242424] rounded-lg overflow-y-auto w-[475px];
|
||||
@apply h-[510px] bg-[#161616] border border-[#242424] rounded-lg overflow-y-auto w-[475px] relative;
|
||||
}
|
||||
|
||||
.leaderboard-entry {
|
||||
@@ -15,3 +15,39 @@
|
||||
.leaderboard-entry p.score {
|
||||
@apply font-mono text-blue-500 text-lg;
|
||||
}
|
||||
|
||||
.side-dropdown {
|
||||
@apply flex items-end min-w-[52px];
|
||||
}
|
||||
|
||||
.dropdown-root {
|
||||
@apply relative w-max;
|
||||
}
|
||||
|
||||
.dropdown-btn {
|
||||
@apply px-3 py-2 rounded-md bg-[#242424] disabled:bg-[#161616] border border-[#484848] disabled:border-[#383838] text-gray-200 hover:bg-[#323232] hover:border-[#565656] transition-colors cursor-pointer;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
@apply absolute bottom-full mb-2 w-45 bg-[#242424] border border-[#484848] rounded-md shadow-lg hidden z-50;
|
||||
}
|
||||
|
||||
.dropdown-left .dropdown-menu {
|
||||
@apply left-0;
|
||||
}
|
||||
|
||||
.dropdown-right .dropdown-menu {
|
||||
@apply right-0 w-40;
|
||||
}
|
||||
|
||||
.dropdown-menu.open {
|
||||
@apply block;
|
||||
}
|
||||
|
||||
.dropdown-item {
|
||||
@apply block w-full text-left px-4 py-2 hover:bg-[#323232] text-gray-200 cursor-pointer;
|
||||
}
|
||||
|
||||
.dropdown-item.selected {
|
||||
@apply bg-[#323232] hover:bg-[#484848];
|
||||
}
|
||||
|
||||
@@ -1,28 +1,57 @@
|
||||
'use client'
|
||||
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useCallback, useEffect, useRef, useState } from 'react'
|
||||
import './Leaderboards.css'
|
||||
import axios from 'axios'
|
||||
import { app } from '@tauri-apps/api'
|
||||
import { platform } from '@tauri-apps/plugin-os'
|
||||
import { decrypt } from '../util/Encryption'
|
||||
import { decrypt, encrypt } from '../util/Encryption'
|
||||
import { invoke } from '@tauri-apps/api/core'
|
||||
import Image from 'next/image'
|
||||
import { LeaderboardResponse } from '../types/LeaderboardResponse'
|
||||
import { faChevronDown } from '@fortawesome/free-solid-svg-icons'
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
|
||||
import { getKey } from '../util/KeysHelper'
|
||||
|
||||
import Berry from '../assets/berries/Berry.png'
|
||||
import PoisonBerry from '../assets/berries/PoisonBerry.png'
|
||||
import SlowBerry from '../assets/berries/SlowBerry.png'
|
||||
import UltraBerry from '../assets/berries/UltraBerry.png'
|
||||
import SpeedyBerry from '../assets/berries/SpeedyBerry.png'
|
||||
import CoinBerry from '../assets/berries/CoinBerry.png'
|
||||
|
||||
export default function Leaderboards () {
|
||||
const [leaderboardData, setLeaderboardData] =
|
||||
useState<LeaderboardResponse | null>(null)
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [leftOpen, setLeftOpen] = useState(false)
|
||||
const [rightOpen, setRightOpen] = useState(false)
|
||||
const leftRef = useRef<HTMLDivElement | null>(null)
|
||||
const rightRef = useRef<HTMLDivElement | null>(null)
|
||||
const formatter = new Intl.NumberFormat('en-US')
|
||||
const [leaderboardType, setLeaderboardType] = useState<number>(0)
|
||||
const [berryType, setBerryType] = useState<number>(0)
|
||||
|
||||
async function refresh () {
|
||||
const refresh = useCallback(async () => {
|
||||
setLoading(true)
|
||||
setLeaderboardData(null)
|
||||
try {
|
||||
const launcherVersion = await app.getVersion()
|
||||
const response = await axios.get(
|
||||
const sendKey = await getKey(1)
|
||||
const formData = new URLSearchParams()
|
||||
formData.append(
|
||||
await encrypt('type', sendKey),
|
||||
await encrypt(leaderboardType.toString(), sendKey)
|
||||
)
|
||||
if (leaderboardType == 1) {
|
||||
formData.append(
|
||||
await encrypt('showType', sendKey),
|
||||
await encrypt(berryType.toString(), sendKey)
|
||||
)
|
||||
}
|
||||
const response = await axios.post(
|
||||
'https://berrydash.lncvrt.xyz/database/getTopPlayers.php',
|
||||
formData,
|
||||
{
|
||||
headers: {
|
||||
Requester: 'BerryDashLauncher',
|
||||
@@ -38,7 +67,7 @@ export default function Leaderboards () {
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
}, [leaderboardType, berryType])
|
||||
|
||||
function downloadLeaderboard () {
|
||||
let content = '"Username","Score","ScoreFormatted"\n'
|
||||
@@ -55,6 +84,16 @@ export default function Leaderboards () {
|
||||
|
||||
useEffect(() => {
|
||||
refresh()
|
||||
}, [refresh])
|
||||
|
||||
useEffect(() => {
|
||||
function onDocClick (e: MouseEvent) {
|
||||
const t = e.target as Node
|
||||
if (leftRef.current && !leftRef.current.contains(t)) setLeftOpen(false)
|
||||
if (rightRef.current && !rightRef.current.contains(t)) setRightOpen(false)
|
||||
}
|
||||
document.addEventListener('mousedown', onDocClick)
|
||||
return () => document.removeEventListener('mousedown', onDocClick)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
@@ -65,7 +104,7 @@ export default function Leaderboards () {
|
||||
<button
|
||||
className='button text-3xl'
|
||||
onClick={downloadLeaderboard}
|
||||
disabled={loading || leaderboardData?.entries.length === 0}
|
||||
disabled={loading || leaderboardData?.entries?.length === 0}
|
||||
>
|
||||
Download Leaderboards
|
||||
</button>
|
||||
@@ -78,9 +117,73 @@ export default function Leaderboards () {
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='leaderboard-container'>
|
||||
<div className='side-dropdown'>
|
||||
<div ref={leftRef} className='dropdown-root dropdown-left'>
|
||||
<button
|
||||
className='dropdown-btn'
|
||||
onClick={() => setLeftOpen(v => !v)}
|
||||
aria-expanded={leftOpen}
|
||||
disabled={loading}
|
||||
>
|
||||
Type{' '}
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronDown}
|
||||
className={leftOpen ? 'rotate-180' : ''}
|
||||
/>
|
||||
</button>
|
||||
<div className={`dropdown-menu ${leftOpen ? 'open' : ''}`}>
|
||||
<button
|
||||
className={`dropdown-item ${
|
||||
leaderboardType == 0 ? 'selected' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
setLeftOpen(false)
|
||||
setLeaderboardType(0)
|
||||
}}
|
||||
>
|
||||
Score Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${
|
||||
leaderboardType == 1 ? 'selected' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
setLeftOpen(false)
|
||||
setLeaderboardType(1)
|
||||
}}
|
||||
>
|
||||
Berry Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${
|
||||
leaderboardType == 2 ? 'selected' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
setLeftOpen(false)
|
||||
setLeaderboardType(2)
|
||||
}}
|
||||
>
|
||||
Coins Leaderboard
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${
|
||||
leaderboardType == 3 ? 'selected' : ''
|
||||
}`}
|
||||
onClick={() => {
|
||||
setLeftOpen(false)
|
||||
setLeaderboardType(3)
|
||||
}}
|
||||
>
|
||||
Legacy Leaderboard
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='leaderboard-scroll'>
|
||||
{leaderboardData?.entries.length ? (
|
||||
{leaderboardData?.entries?.length ? (
|
||||
leaderboardData.entries.map((entry, i) => (
|
||||
<div key={i} className='leaderboard-entry justify-between'>
|
||||
<div className='flex items-center gap-2'>
|
||||
@@ -124,6 +227,97 @@ export default function Leaderboards () {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className='side-dropdown'>
|
||||
<div ref={rightRef} className='dropdown-root dropdown-right'>
|
||||
<button
|
||||
className='dropdown-btn'
|
||||
onClick={() => setRightOpen(v => !v)}
|
||||
aria-expanded={rightOpen}
|
||||
disabled={loading || leaderboardType != 1}
|
||||
>
|
||||
Berry Type{' '}
|
||||
<FontAwesomeIcon
|
||||
icon={faChevronDown}
|
||||
className={rightOpen ? 'rotate-180' : ''}
|
||||
/>
|
||||
</button>
|
||||
<div className={`dropdown-menu ${rightOpen ? 'open' : ''}`}>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 0 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(0)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={Berry} width={24} height={24} alt='' />
|
||||
Normal Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 1 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(1)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={PoisonBerry} width={24} height={24} alt='' />
|
||||
Poison Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 2 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(2)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={SlowBerry} width={24} height={24} alt='' />
|
||||
Slow Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 3 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(3)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={UltraBerry} width={24} height={24} alt='' />
|
||||
Ultra Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 4 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(4)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={SpeedyBerry} width={24} height={24} alt='' />
|
||||
Speedy Berry
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
className={`dropdown-item ${berryType == 5 ? 'selected' : ''}`}
|
||||
onClick={() => {
|
||||
setRightOpen(false)
|
||||
setBerryType(5)
|
||||
}}
|
||||
>
|
||||
<span className='flex items-center gap-2'>
|
||||
<Image src={CoinBerry} width={24} height={24} alt='' />
|
||||
Coin Berry
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||