From 3b380c7adb754e93868a038ace2d2e42ba439e03 Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Fri, 25 Oct 2024 03:30:45 +0900 Subject: [PATCH] =?UTF-8?q?=E3=83=A9=E3=83=B3=E3=82=AD=E3=83=B3=E3=82=B0?= =?UTF-8?q?=E3=81=AE=E5=90=84=E3=82=A2=E3=82=A4=E3=83=86=E3=83=A0=E3=81=A8?= =?UTF-8?q?=E8=A1=A8=E7=A4=BA=E3=81=AE=E3=82=B3=E3=83=B3=E3=83=9D=E3=83=BC?= =?UTF-8?q?=E3=83=8D=E3=83=B3=E3=83=88=E4=BD=9C=E6=88=90=E3=83=BBSupabase?= =?UTF-8?q?=E3=81=8B=E3=82=89=E3=83=A9=E3=83=B3=E3=82=AD=E3=83=B3=E3=82=B0?= =?UTF-8?q?=E3=82=92=E5=8F=96=E5=BE=97=E3=81=99=E3=82=8B=E3=83=95=E3=83=83?= =?UTF-8?q?=E3=82=AF=E3=81=AE=E4=BD=9C=E6=88=90=E3=83=BB=E4=B8=80=E5=BA=A6?= =?UTF-8?q?=E3=81=AB=E5=8F=96=E5=BE=97=E3=81=99=E3=82=8B=E4=BB=B6=E6=95=B0?= =?UTF-8?q?=E3=81=AE=E5=88=B6=E9=99=90=E3=83=BB=E3=81=95=E3=82=89=E3=81=AB?= =?UTF-8?q?=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=82=80=E6=A9=9F=E8=83=BD=20?= =?UTF-8?q?=E3=83=A9=E3=83=B3=E3=82=AD=E3=83=B3=E3=82=B0=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=E3=81=AE=E4=BD=9C=E6=88=90=20#26?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Ranking.css | 12 +++++++ app/components/Ranking.tsx | 48 +++++++++++++++++++++++++ app/hooks/useFetchRanking.ts | 68 ++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+) create mode 100644 app/Ranking.css create mode 100644 app/components/Ranking.tsx create mode 100644 app/hooks/useFetchRanking.ts diff --git a/app/Ranking.css b/app/Ranking.css new file mode 100644 index 0000000..787d8ec --- /dev/null +++ b/app/Ranking.css @@ -0,0 +1,12 @@ +.ranking-item{ + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; + margin: 5px 0; + border-radius: 10px; + background-color: #525252; + font-size: 24px; + border: 2px solid #333; + box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.2); +} \ No newline at end of file diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx new file mode 100644 index 0000000..55dc74c --- /dev/null +++ b/app/components/Ranking.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { useFetchRanking } from '~/hooks/useFetchRanking'; +import '../Ranking.css' + +interface RankingData{ + rank: number | null; + name: string; + score: number | null; +} + +export function RankingItem({ rank, name, score }: RankingData){ + return ( +
+ {rank}位 + {name} + {score} +
+ ); +}; + +export function RankingList(){ + const { ranking, loading, error, loadMore } = useFetchRanking(); + + if(loading) return
Loading...
; + if(error) return
Error!!
; + + if(!ranking || ranking.length === 0){ + return
No Ranking Data.
; + } + + return ( +
+ {ranking.map((item, index) => ( + + ))} + {loading ? ( +

Loading...

+ ) : ( + + )} +
+ ); +} \ No newline at end of file diff --git a/app/hooks/useFetchRanking.ts b/app/hooks/useFetchRanking.ts new file mode 100644 index 0000000..4ba69a6 --- /dev/null +++ b/app/hooks/useFetchRanking.ts @@ -0,0 +1,68 @@ +import { useState, useEffect, useCallback, useRef } from "react"; +import { supabase } from "~/libs/supabase"; + +interface Stats{ + id: string; + user_id: string; + display_name: string; + created_at: string; + updated_at: string; + high_score: number | null; + play_count: number; + rank: number | null; +}; + +export function useFetchRanking( limit = 20 ){ + const [ranking, setRanking] = useState(null); + const [loading, setLoading] = useState(true); + const [error, setError] = useState(false); + const [page, setPage] = useState(0); + const hasFetchedInitial = useRef(false); + const scrollPosition = useRef(0); + + const fetchRankings = useCallback(async (fetchPage = page) => { + setLoading(true); + setError(false); + + const start = fetchPage * limit; + const end = start + limit - 1; + + const { data, error } = await supabase + .from('profiles_with_stats') + .select('*') + .order('rank', { ascending: true }) + .range(start, end); + + if(error){ + console.error('Error Fetching Rankings'); + setError(true); + } + else{ + setRanking((prev) => [...(prev ?? []), ...(data ?? [])]) + } + + setLoading(false); + + window.scrollTo(0, scrollPosition.current); + }, [page, limit]); + + useEffect(() => { + if(!hasFetchedInitial.current){ + fetchRankings(0); + hasFetchedInitial.current = true; + } + }) + + useEffect(() => { + if(page > 0){ + fetchRankings(page); + } + }, [fetchRankings]); + + const loadMore = () => { + scrollPosition.current = window.scrollY; + setPage((prev) => prev + 1); + }; + + return { ranking, loading, error, loadMore }; +} \ No newline at end of file