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 01/14] =?UTF-8?q?=E3=83=A9=E3=83=B3=E3=82=AD=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=81=AE=E5=90=84=E3=82=A2=E3=82=A4=E3=83=86=E3=83=A0?= =?UTF-8?q?=E3=81=A8=E8=A1=A8=E7=A4=BA=E3=81=AE=E3=82=B3=E3=83=B3=E3=83=9D?= =?UTF-8?q?=E3=83=BC=E3=83=8D=E3=83=B3=E3=83=88=E4=BD=9C=E6=88=90=E3=83=BB?= =?UTF-8?q?Supabase=E3=81=8B=E3=82=89=E3=83=A9=E3=83=B3=E3=82=AD=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=82=92=E5=8F=96=E5=BE=97=E3=81=99=E3=82=8B=E3=83=95?= =?UTF-8?q?=E3=83=83=E3=82=AF=E3=81=AE=E4=BD=9C=E6=88=90=E3=83=BB=E4=B8=80?= =?UTF-8?q?=E5=BA=A6=E3=81=AB=E5=8F=96=E5=BE=97=E3=81=99=E3=82=8B=E4=BB=B6?= =?UTF-8?q?=E6=95=B0=E3=81=AE=E5=88=B6=E9=99=90=E3=83=BB=E3=81=95=E3=82=89?= =?UTF-8?q?=E3=81=AB=E8=AA=AD=E3=81=BF=E8=BE=BC=E3=82=80=E6=A9=9F=E8=83=BD?= =?UTF-8?q?=20=E3=83=A9=E3=83=B3=E3=82=AD=E3=83=B3=E3=82=B0=E6=A9=9F?= =?UTF-8?q?=E8=83=BD=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 From 93403dc8a9d73d74fc0e88f26ba5616b0aeea649 Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Fri, 25 Oct 2024 03:40:30 +0900 Subject: [PATCH 02/14] =?UTF-8?q?=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E4=BD=8D=E7=BD=AE=E3=81=8C=E4=BF=9D=E5=AD=98=E3=81=95?= =?UTF-8?q?=E3=82=8C=E3=81=BE=E3=81=97=E3=81=9F=20=E3=83=A9=E3=83=B3?= =?UTF-8?q?=E3=82=AD=E3=83=B3=E3=82=B0=E6=A9=9F=E8=83=BD=E3=81=AE=E4=BD=9C?= =?UTF-8?q?=E6=88=90=20#26?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/hooks/useFetchRanking.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/hooks/useFetchRanking.ts b/app/hooks/useFetchRanking.ts index 4ba69a6..9e72de3 100644 --- a/app/hooks/useFetchRanking.ts +++ b/app/hooks/useFetchRanking.ts @@ -43,7 +43,9 @@ export function useFetchRanking( limit = 20 ){ setLoading(false); - window.scrollTo(0, scrollPosition.current); + requestAnimationFrame(() => { + window.scrollTo(0, scrollPosition.current); + }); }, [page, limit]); useEffect(() => { From b5d17ce16f68dca403e5789263a3dd028cb632e8 Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Fri, 25 Oct 2024 04:01:01 +0900 Subject: [PATCH 03/14] =?UTF-8?q?=E6=9C=80=E4=BD=8E=E9=99=90=E3=81=AE?= =?UTF-8?q?=E3=83=87=E3=82=B6=E3=82=A4=E3=83=B3=EF=BC=88=EF=BC=9F=EF=BC=89?= =?UTF-8?q?=E3=81=AF=E3=81=97=E3=81=BE=E3=81=97=E3=81=9F=E3=80=80CSS?= =?UTF-8?q?=E5=88=9D=E5=BF=83=E8=80=85=E3=81=A7=E3=81=99=20=E3=83=A9?= =?UTF-8?q?=E3=83=B3=E3=82=AD=E3=83=B3=E3=82=B0=E6=A9=9F=E8=83=BD=E3=81=AE?= =?UTF-8?q?=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 | 59 ++++++++++++++++++++++++++++++++++++-- app/components/Ranking.tsx | 12 ++++++-- 2 files changed, 66 insertions(+), 5 deletions(-) diff --git a/app/Ranking.css b/app/Ranking.css index 787d8ec..6bd4a8e 100644 --- a/app/Ranking.css +++ b/app/Ranking.css @@ -3,10 +3,63 @@ justify-content: space-between; align-items: center; padding: 10px; - margin: 5px 0; + margin: 15px auto; + width: 800px; border-radius: 10px; - background-color: #525252; + background-color: #797878; font-size: 24px; border: 2px solid #333; - box-shadow: 3px 3px 5px rgba(0, 0, 0, 0.2); + box-shadow: 3px 3px 5px rgba(0, 0, 0, 1); + text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); +} + +.ranking-title{ + display: flex; + justify-content: center; + align-items: center; + margin: 5px auto; + width: 800px; + font-size: 36px; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); +} + +.rank-first{ + color: #ffd700; +} + +.rank-second{ + color: #c0c0c0; +} + +.rank-third{ + color: #cd7f32; +} + +.rank-default{ + +} + +.name{ + position: absolute; + left: 50%; + transform: translateX(-50%); +} + +.score{ + +} + +.ranking-load-button{ + display: flex; + justify-content: center; + align-items: center; + padding: 5px; + margin: 15px auto; + width: 400px; + border-radius: 10px; + background-color: #797878; + font-size: 18px; + border: 2px solid #333; + box-shadow: 3px 3px 5px rgba(0, 0, 0, 1); + text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); } \ No newline at end of file diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 55dc74c..7f91242 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -9,9 +9,16 @@ interface RankingData{ } export function RankingItem({ rank, name, score }: RankingData){ + const getRankClass = () => { + if (rank === 1) return 'rank-first'; + if (rank === 2) return 'rank-second'; + if (rank === 3) return 'rank-third'; + return 'rank-default'; + }; + return (
- {rank}位 + {rank}位 {name} {score}
@@ -30,6 +37,7 @@ export function RankingList(){ return (
+
ランキング
{ranking.map((item, index) => ( Loading...

) : ( - + )}
); From 9d9afe3da5b903a901e653ca7b0ed6a0519fe568 Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Fri, 25 Oct 2024 04:06:14 +0900 Subject: [PATCH 04/14] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AB=E3=81=AA?= =?UTF-8?q?=E3=81=A3=E3=81=9F=20export=20=E6=96=87=E3=82=92=E5=89=8A?= =?UTF-8?q?=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/Ranking.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 7f91242..7c58095 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -8,7 +8,7 @@ interface RankingData{ score: number | null; } -export function RankingItem({ rank, name, score }: RankingData){ +function RankingItem({ rank, name, score }: RankingData){ const getRankClass = () => { if (rank === 1) return 'rank-first'; if (rank === 2) return 'rank-second'; From 9a8707015f0f5953c2dfc2ac40d637012297a653 Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Fri, 25 Oct 2024 04:33:51 +0900 Subject: [PATCH 05/14] =?UTF-8?q?=E7=84=A1=E9=99=90=E3=82=B9=E3=82=AF?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E3=83=AB=E3=82=92=E5=AE=9F=E8=A3=85=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 | 18 ++++++++++++++---- app/components/Ranking.tsx | 34 +++++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/app/Ranking.css b/app/Ranking.css index 6bd4a8e..e2ea941 100644 --- a/app/Ranking.css +++ b/app/Ranking.css @@ -35,9 +35,9 @@ color: #cd7f32; } -.rank-default{ +/* .rank-default{ -} +} */ .name{ position: absolute; @@ -45,9 +45,9 @@ transform: translateX(-50%); } -.score{ +/* .score{ -} +} */ .ranking-load-button{ display: flex; @@ -62,4 +62,14 @@ border: 2px solid #333; box-shadow: 3px 3px 5px rgba(0, 0, 0, 1); text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); +} + +.ranking-loading-text{ + display: flex; + justify-content: center; + align-items: center; + margin: 5px auto; + width: 800px; + font-size: 18px; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); } \ No newline at end of file diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 7c58095..91fc30a 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { useEffect, useRef } from 'react'; import { useFetchRanking } from '~/hooks/useFetchRanking'; import '../Ranking.css' @@ -27,8 +27,29 @@ function RankingItem({ rank, name, score }: RankingData){ export function RankingList(){ const { ranking, loading, error, loadMore } = useFetchRanking(); + const observer = useRef(null); + const loadMoreRef = useRef(null); - if(loading) return
Loading...
; + useEffect(() => { + if(loading || !loadMoreRef.current) return; + + const observerCallback = (entries: IntersectionObserverEntry[]) => { + if(entries[0].isIntersecting){ + loadMore(); + } + }; + + observer.current = new IntersectionObserver(observerCallback); + observer.current.observe(loadMoreRef.current); + + return () => { + if(observer.current && loadMoreRef.current){ + observer.current.unobserve(loadMoreRef.current); + } + }; + }, [loading, loadMore]); + + // if(loading) return
Loading...
; if(error) return
Error!!
; if(!ranking || ranking.length === 0){ @@ -46,11 +67,14 @@ export function RankingList(){ score={item.high_score} /> ))} - {loading ? ( -

Loading...

+ {/* {loading ? ( +

Loading...

) : ( - )} + )} */} +
+ {loading &&

Loading...

} +
); } \ No newline at end of file From 924264f6e4f1524747ec93accca02ccfa9e8cdc7 Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Wed, 30 Oct 2024 02:22:24 +0900 Subject: [PATCH 06/14] =?UTF-8?q?=E3=82=B9=E3=82=AF=E3=83=AD=E3=83=BC?= =?UTF-8?q?=E3=83=AB=E4=BD=8D=E7=BD=AE=E3=81=AE=E4=BF=9D=E5=AD=98=E3=82=92?= =?UTF-8?q?=E5=89=8A=E9=99=A4=E3=81=97=E3=81=9F=E3=81=A4=E3=82=82=E3=82=8A?= =?UTF-8?q?=E3=81=AA=E3=82=93=E3=81=A7=E3=81=99=E3=81=8C=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/Ranking.tsx | 5 ----- app/hooks/useFetchRanking.ts | 6 ------ 2 files changed, 11 deletions(-) diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 91fc30a..94d795f 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -67,11 +67,6 @@ export function RankingList(){ score={item.high_score} /> ))} - {/* {loading ? ( -

Loading...

- ) : ( - - )} */}
{loading &&

Loading...

}
diff --git a/app/hooks/useFetchRanking.ts b/app/hooks/useFetchRanking.ts index 9e72de3..d7f2325 100644 --- a/app/hooks/useFetchRanking.ts +++ b/app/hooks/useFetchRanking.ts @@ -18,7 +18,6 @@ export function useFetchRanking( limit = 20 ){ 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); @@ -42,10 +41,6 @@ export function useFetchRanking( limit = 20 ){ } setLoading(false); - - requestAnimationFrame(() => { - window.scrollTo(0, scrollPosition.current); - }); }, [page, limit]); useEffect(() => { @@ -62,7 +57,6 @@ export function useFetchRanking( limit = 20 ){ }, [fetchRankings]); const loadMore = () => { - scrollPosition.current = window.scrollY; setPage((prev) => prev + 1); }; From 00e5092c3a8ea85ee0ad15f9b0b689b670f9aa45 Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Wed, 30 Oct 2024 03:07:33 +0900 Subject: [PATCH 07/14] =?UTF-8?q?useSWR=20=E3=82=92=E4=BD=BF=E7=94=A8?= =?UTF-8?q?=E3=81=99=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=E5=A4=89=E6=9B=B4?= =?UTF-8?q?=EF=BC=88=E4=B8=80=E6=97=A6=E7=84=A1=E9=99=90=E3=82=B9=E3=82=AF?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E3=83=AB=E3=81=AF=E5=89=8A=E9=99=A4=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/Ranking.tsx | 42 ++++++++++++------------ app/hooks/useFetchRanking.ts | 63 ++++++++++-------------------------- 2 files changed, 38 insertions(+), 67 deletions(-) diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 94d795f..0d95ed0 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -26,40 +26,40 @@ function RankingItem({ rank, name, score }: RankingData){ }; export function RankingList(){ - const { ranking, loading, error, loadMore } = useFetchRanking(); + const { data, error, isLoading } = useFetchRanking(); const observer = useRef(null); const loadMoreRef = useRef(null); - useEffect(() => { - if(loading || !loadMoreRef.current) return; + // useEffect(() => { + // if(loading || !loadMoreRef.current) return; - const observerCallback = (entries: IntersectionObserverEntry[]) => { - if(entries[0].isIntersecting){ - loadMore(); - } - }; + // const observerCallback = (entries: IntersectionObserverEntry[]) => { + // if(entries[0].isIntersecting){ + // loadMore(); + // } + // }; - observer.current = new IntersectionObserver(observerCallback); - observer.current.observe(loadMoreRef.current); + // observer.current = new IntersectionObserver(observerCallback); + // observer.current.observe(loadMoreRef.current); - return () => { - if(observer.current && loadMoreRef.current){ - observer.current.unobserve(loadMoreRef.current); - } - }; - }, [loading, loadMore]); + // return () => { + // if(observer.current && loadMoreRef.current){ + // observer.current.unobserve(loadMoreRef.current); + // } + // }; + // }, [loading, loadMore]); - // if(loading) return
Loading...
; + if(isLoading) return
Loading...
; if(error) return
Error!!
; - if(!ranking || ranking.length === 0){ + if(!data || data.length === 0){ return
No Ranking Data.
; } return (
ランキング
- {ranking.map((item, index) => ( + {data.map((item, index) => ( ))} -
+ {/*
{loading &&

Loading...

} -
+
*/}
); } \ No newline at end of file diff --git a/app/hooks/useFetchRanking.ts b/app/hooks/useFetchRanking.ts index d7f2325..0adc8b3 100644 --- a/app/hooks/useFetchRanking.ts +++ b/app/hooks/useFetchRanking.ts @@ -1,5 +1,6 @@ import { useState, useEffect, useCallback, useRef } from "react"; import { supabase } from "~/libs/supabase"; +import useSWR from "swr"; interface Stats{ id: string; @@ -12,53 +13,23 @@ interface Stats{ 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 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); - }, [page, limit]); - - useEffect(() => { - if(!hasFetchedInitial.current){ - fetchRankings(0); - hasFetchedInitial.current = true; - } - }) +const fetchRankingData = async(page: number, limit: number) => { + const start = limit * page; + const end = start + limit - 1; + const { data } = await supabase + .from('profiles_with_stats') + .select('*') + .order('rank', { ascending: true }) + .range(start, end); + return data; +}; - useEffect(() => { - if(page > 0){ - fetchRankings(page); - } - }, [fetchRankings]); +export function useFetchRanking( page = 0, limit = 20 ){ + const { data, error, isLoading } = useSWR([page, limit], ([page, limit]) => fetchRankingData(page, limit)); - const loadMore = () => { - setPage((prev) => prev + 1); + return { + data, + error, + isLoading }; - - return { ranking, loading, error, loadMore }; } \ No newline at end of file From f0745f925c5d39cfa96d242dd5f2010442e661c9 Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Wed, 30 Oct 2024 03:22:56 +0900 Subject: [PATCH 08/14] =?UTF-8?q?=E7=84=A1=E9=99=90=E3=82=B9=E3=82=AF?= =?UTF-8?q?=E3=83=AD=E3=83=BC=E3=83=AB=E3=82=92=E5=AE=9F=E8=A3=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/Ranking.tsx | 48 ++++++++++++++++++------------------ app/hooks/useFetchRanking.ts | 19 +++++++++++--- 2 files changed, 40 insertions(+), 27 deletions(-) diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 0d95ed0..5184508 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -2,13 +2,13 @@ import { useEffect, useRef } from 'react'; import { useFetchRanking } from '~/hooks/useFetchRanking'; import '../Ranking.css' -interface RankingData{ +interface RankingItemProps{ rank: number | null; name: string; score: number | null; } -function RankingItem({ rank, name, score }: RankingData){ +function RankingItem({ rank, name, score }: RankingItemProps){ const getRankClass = () => { if (rank === 1) return 'rank-first'; if (rank === 2) return 'rank-second'; @@ -26,40 +26,40 @@ function RankingItem({ rank, name, score }: RankingData){ }; export function RankingList(){ - const { data, error, isLoading } = useFetchRanking(); + const { ranking, error, isLoading, isValidating, loadMore, hasMore } = useFetchRanking(); const observer = useRef(null); const loadMoreRef = useRef(null); - // useEffect(() => { - // if(loading || !loadMoreRef.current) return; + useEffect(() => { + if(isValidating || !loadMoreRef.current) return; - // const observerCallback = (entries: IntersectionObserverEntry[]) => { - // if(entries[0].isIntersecting){ - // loadMore(); - // } - // }; + const observerCallback = (entries: IntersectionObserverEntry[]) => { + if(entries[0].isIntersecting && hasMore && !isValidating){ + loadMore(); + } + }; - // observer.current = new IntersectionObserver(observerCallback); - // observer.current.observe(loadMoreRef.current); + observer.current = new IntersectionObserver(observerCallback); + observer.current.observe(loadMoreRef.current); - // return () => { - // if(observer.current && loadMoreRef.current){ - // observer.current.unobserve(loadMoreRef.current); - // } - // }; - // }, [loading, loadMore]); + return () => { + if(observer.current && loadMoreRef.current){ + observer.current.unobserve(loadMoreRef.current); + } + }; + }, [isValidating, loadMore, hasMore]); if(isLoading) return
Loading...
; if(error) return
Error!!
; - if(!data || data.length === 0){ - return
No Ranking Data.
; + if(!ranking || ranking.length === 0){ + return
No Ranking ranking.
; } return (
ランキング
- {data.map((item, index) => ( + {ranking.map((item, index) => ( ))} - {/*
- {loading &&

Loading...

} -
*/} +
+ {isValidating &&

Loading...

} +
); } \ No newline at end of file diff --git a/app/hooks/useFetchRanking.ts b/app/hooks/useFetchRanking.ts index 0adc8b3..3eb9f61 100644 --- a/app/hooks/useFetchRanking.ts +++ b/app/hooks/useFetchRanking.ts @@ -1,6 +1,7 @@ import { useState, useEffect, useCallback, useRef } from "react"; import { supabase } from "~/libs/supabase"; import useSWR from "swr"; +import useSWRInfinite from "swr/infinite"; interface Stats{ id: string; @@ -25,11 +26,23 @@ const fetchRankingData = async(page: number, limit: number) => { }; export function useFetchRanking( page = 0, limit = 20 ){ - const { data, error, isLoading } = useSWR([page, limit], ([page, limit]) => fetchRankingData(page, limit)); + const getKey = (page: number, previousPageData: Stats[] | null) => { + if(previousPageData && previousPageData.length === 0) return null; + return [page, limit]; + }; + + const { data, error, isLoading, isValidating, size, setSize } = useSWRInfinite(getKey, ([page, limit]) => fetchRankingData(page, limit)); + + const ranking = data ? data.flat() : []; + + const loadMore = () => setSize(size + 1); return { - data, + ranking, error, - isLoading + isLoading, + isValidating, + loadMore, + hasMore: data?.[data.length - 1]?.length === limit }; } \ No newline at end of file From 3dfe13ac4f8f1b27672f0dbee011e7c0aeccbe04 Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Wed, 30 Oct 2024 03:24:35 +0900 Subject: [PATCH 09/14] =?UTF-8?q?ranking=20=E3=81=AE=20null=20=E3=83=81?= =?UTF-8?q?=E3=82=A7=E3=83=83=E3=82=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/Ranking.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 5184508..d01a28a 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -60,12 +60,12 @@ export function RankingList(){
ランキング
{ranking.map((item, index) => ( - + />) ))}
{isValidating &&

Loading...

} From 7ba40050a6c25e7932017857cca288983196bd0a Mon Sep 17 00:00:00 2001 From: log_K <36733349+K-Yoshizawa@users.noreply.github.com> Date: Wed, 30 Oct 2024 03:25:31 +0900 Subject: [PATCH 10/14] =?UTF-8?q?=E4=B8=8D=E8=A6=81=E3=81=AA=20import=20?= =?UTF-8?q?=E3=81=AA=E3=81=A9=E3=82=92=E5=89=8A=E9=99=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/Ranking.tsx | 2 +- app/hooks/useFetchRanking.ts | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index d01a28a..977e5a6 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -59,7 +59,7 @@ export function RankingList(){ return (
ランキング
- {ranking.map((item, index) => ( + {ranking.map((item) => ( item && ( Date: Wed, 30 Oct 2024 03:30:44 +0900 Subject: [PATCH 11/14] =?UTF-8?q?`pnpm=20run=20lint`=20=E3=81=AB=E6=80=92?= =?UTF-8?q?=E3=82=89=E3=82=8C=E3=81=9F=EF=BC=88=E6=82=B2=E3=81=97=E3=81=84?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Ranking.css | 106 ++++++++++++++-------------- app/components/Ranking.tsx | 130 ++++++++++++++++++----------------- app/hooks/useFetchRanking.ts | 75 ++++++++++---------- 3 files changed, 158 insertions(+), 153 deletions(-) diff --git a/app/Ranking.css b/app/Ranking.css index e2ea941..7270f33 100644 --- a/app/Ranking.css +++ b/app/Ranking.css @@ -1,75 +1,75 @@ -.ranking-item{ - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px; - margin: 15px auto; - width: 800px; - border-radius: 10px; - background-color: #797878; - font-size: 24px; - border: 2px solid #333; - box-shadow: 3px 3px 5px rgba(0, 0, 0, 1); - text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); +.ranking-item { + display: flex; + justify-content: space-between; + align-items: center; + padding: 10px; + margin: 15px auto; + width: 800px; + border-radius: 10px; + background-color: #797878; + font-size: 24px; + border: 2px solid #333; + box-shadow: 3px 3px 5px rgba(0, 0, 0, 1); + text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); } -.ranking-title{ - display: flex; - justify-content: center; - align-items: center; - margin: 5px auto; - width: 800px; - font-size: 36px; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); +.ranking-title { + display: flex; + justify-content: center; + align-items: center; + margin: 5px auto; + width: 800px; + font-size: 36px; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); } -.rank-first{ - color: #ffd700; +.rank-first { + color: #ffd700; } -.rank-second{ - color: #c0c0c0; +.rank-second { + color: #c0c0c0; } -.rank-third{ - color: #cd7f32; +.rank-third { + color: #cd7f32; } /* .rank-default{ } */ -.name{ - position: absolute; - left: 50%; - transform: translateX(-50%); +.name { + position: absolute; + left: 50%; + transform: translateX(-50%); } /* .score{ } */ -.ranking-load-button{ - display: flex; - justify-content: center; - align-items: center; - padding: 5px; - margin: 15px auto; - width: 400px; - border-radius: 10px; - background-color: #797878; - font-size: 18px; - border: 2px solid #333; - box-shadow: 3px 3px 5px rgba(0, 0, 0, 1); - text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); +.ranking-load-button { + display: flex; + justify-content: center; + align-items: center; + padding: 5px; + margin: 15px auto; + width: 400px; + border-radius: 10px; + background-color: #797878; + font-size: 18px; + border: 2px solid #333; + box-shadow: 3px 3px 5px rgba(0, 0, 0, 1); + text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); } -.ranking-loading-text{ - display: flex; - justify-content: center; - align-items: center; - margin: 5px auto; - width: 800px; - font-size: 18px; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); -} \ No newline at end of file +.ranking-loading-text { + display: flex; + justify-content: center; + align-items: center; + margin: 5px auto; + width: 800px; + font-size: 18px; + text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); +} diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 977e5a6..8d06d8f 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -1,75 +1,79 @@ -import { useEffect, useRef } from 'react'; -import { useFetchRanking } from '~/hooks/useFetchRanking'; -import '../Ranking.css' +import { useEffect, useRef } from "react"; +import { useFetchRanking } from "~/hooks/useFetchRanking"; +import "../Ranking.css"; -interface RankingItemProps{ - rank: number | null; - name: string; - score: number | null; +interface RankingItemProps { + rank: number | null; + name: string; + score: number | null; } -function RankingItem({ rank, name, score }: RankingItemProps){ - const getRankClass = () => { - if (rank === 1) return 'rank-first'; - if (rank === 2) return 'rank-second'; - if (rank === 3) return 'rank-third'; - return 'rank-default'; - }; +function RankingItem({ rank, name, score }: RankingItemProps) { + const getRankClass = () => { + if (rank === 1) return "rank-first"; + if (rank === 2) return "rank-second"; + if (rank === 3) return "rank-third"; + return "rank-default"; + }; - return ( -
- {rank}位 - {name} - {score} -
- ); -}; + return ( +
+ {rank}位 + {name} + {score} +
+ ); +} -export function RankingList(){ - const { ranking, error, isLoading, isValidating, loadMore, hasMore } = useFetchRanking(); - const observer = useRef(null); - const loadMoreRef = useRef(null); +export function RankingList() { + const { ranking, error, isLoading, isValidating, loadMore, hasMore } = + useFetchRanking(); + const observer = useRef(null); + const loadMoreRef = useRef(null); - useEffect(() => { - if(isValidating || !loadMoreRef.current) return; + useEffect(() => { + if (isValidating || !loadMoreRef.current) return; - const observerCallback = (entries: IntersectionObserverEntry[]) => { - if(entries[0].isIntersecting && hasMore && !isValidating){ - loadMore(); - } - }; + const observerCallback = (entries: IntersectionObserverEntry[]) => { + if (entries[0].isIntersecting && hasMore && !isValidating) { + loadMore(); + } + }; - observer.current = new IntersectionObserver(observerCallback); - observer.current.observe(loadMoreRef.current); + observer.current = new IntersectionObserver(observerCallback); + observer.current.observe(loadMoreRef.current); - return () => { - if(observer.current && loadMoreRef.current){ - observer.current.unobserve(loadMoreRef.current); - } - }; - }, [isValidating, loadMore, hasMore]); + return () => { + if (observer.current && loadMoreRef.current) { + observer.current.unobserve(loadMoreRef.current); + } + }; + }, [isValidating, loadMore, hasMore]); - if(isLoading) return
Loading...
; - if(error) return
Error!!
; + if (isLoading) return
Loading...
; + if (error) return
Error!!
; - if(!ranking || ranking.length === 0){ - return
No Ranking ranking.
; - } + if (!ranking || ranking.length === 0) { + return
No Ranking ranking.
; + } - return ( -
-
ランキング
- {ranking.map((item) => ( - item && () - ))} -
- {isValidating &&

Loading...

} -
-
- ); -} \ No newline at end of file + return ( +
+
ランキング
+ {ranking.map( + (item) => + item && ( + + ), + )} +
+ {isValidating &&

Loading...

} +
+
+ ); +} diff --git a/app/hooks/useFetchRanking.ts b/app/hooks/useFetchRanking.ts index c29f35b..b325c29 100644 --- a/app/hooks/useFetchRanking.ts +++ b/app/hooks/useFetchRanking.ts @@ -1,46 +1,47 @@ -import { supabase } from "~/libs/supabase"; import useSWRInfinite from "swr/infinite"; +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; -}; +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; +} -const fetchRankingData = async(page: number, limit: number) => { - const start = limit * page; - const end = start + limit - 1; - const { data } = await supabase - .from('profiles_with_stats') - .select('*') - .order('rank', { ascending: true }) - .range(start, end); - return data; +const fetchRankingData = async (page: number, limit: number) => { + const start = limit * page; + const end = start + limit - 1; + const { data } = await supabase + .from("profiles_with_stats") + .select("*") + .order("rank", { ascending: true }) + .range(start, end); + return data; }; -export function useFetchRanking( page = 0, limit = 20 ){ - const getKey = (page: number, previousPageData: Stats[] | null) => { - if(previousPageData && previousPageData.length === 0) return null; - return [page, limit]; - }; +export function useFetchRanking(page = 0, limit = 20) { + const getKey = (page: number, previousPageData: Stats[] | null) => { + if (previousPageData && previousPageData.length === 0) return null; + return [page, limit]; + }; - const { data, error, isLoading, isValidating, size, setSize } = useSWRInfinite(getKey, ([page, limit]) => fetchRankingData(page, limit)); + const { data, error, isLoading, isValidating, size, setSize } = + useSWRInfinite(getKey, ([page, limit]) => fetchRankingData(page, limit)); - const ranking = data ? data.flat() : []; + const ranking = data ? data.flat() : []; - const loadMore = () => setSize(size + 1); + const loadMore = () => setSize(size + 1); - return { - ranking, - error, - isLoading, - isValidating, - loadMore, - hasMore: data?.[data.length - 1]?.length === limit - }; -} \ No newline at end of file + return { + ranking, + error, + isLoading, + isValidating, + loadMore, + hasMore: data?.[data.length - 1]?.length === limit, + }; +} From 95f6bb9976d33b0f5c2ab0e0e01f9a6f2c5336d2 Mon Sep 17 00:00:00 2001 From: NISHIZAWA Shuntaro Date: Thu, 7 Nov 2024 00:05:29 +0900 Subject: [PATCH 12/14] =?UTF-8?q?refactor:=20Ranking=E3=81=AE=E5=9E=8B?= =?UTF-8?q?=E3=82=92=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/Ranking.stories.tsx | 11 ++++++ app/components/Ranking.tsx | 29 +++++++--------- app/features/profile/Profile.ts | 7 ++++ .../{useFetchRanking.ts => useRanking.ts} | 34 +++++++++++-------- 4 files changed, 50 insertions(+), 31 deletions(-) create mode 100644 app/components/Ranking.stories.tsx rename app/hooks/{useFetchRanking.ts => useRanking.ts} (53%) diff --git a/app/components/Ranking.stories.tsx b/app/components/Ranking.stories.tsx new file mode 100644 index 0000000..6225575 --- /dev/null +++ b/app/components/Ranking.stories.tsx @@ -0,0 +1,11 @@ +import type { Meta, StoryObj } from "@storybook/react"; +import { RankingList } from "./Ranking"; + +const meta: Meta = { + title: "Components/RankingList", + component: RankingList, +}; + +export default meta; + +export const Default: StoryObj = {}; diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 8d06d8f..78b3136 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -1,5 +1,5 @@ import { useEffect, useRef } from "react"; -import { useFetchRanking } from "~/hooks/useFetchRanking"; +import { useFetchRanking } from "~/hooks/useRanking"; import "../Ranking.css"; interface RankingItemProps { @@ -28,25 +28,22 @@ function RankingItem({ rank, name, score }: RankingItemProps) { export function RankingList() { const { ranking, error, isLoading, isValidating, loadMore, hasMore } = useFetchRanking(); - const observer = useRef(null); const loadMoreRef = useRef(null); useEffect(() => { if (isValidating || !loadMoreRef.current) return; - const observerCallback = (entries: IntersectionObserverEntry[]) => { - if (entries[0].isIntersecting && hasMore && !isValidating) { - loadMore(); - } - }; - - observer.current = new IntersectionObserver(observerCallback); - observer.current.observe(loadMoreRef.current); + const observer = new IntersectionObserver( + (entries: IntersectionObserverEntry[]) => { + if (entries[0].isIntersecting && hasMore && !isValidating) { + loadMore(); + } + }, + ); + observer.observe(loadMoreRef.current); return () => { - if (observer.current && loadMoreRef.current) { - observer.current.unobserve(loadMoreRef.current); - } + observer.disconnect(); }; }, [isValidating, loadMore, hasMore]); @@ -64,10 +61,10 @@ export function RankingList() { (item) => item && ( ), )} diff --git a/app/features/profile/Profile.ts b/app/features/profile/Profile.ts index e54fc38..2caa13e 100644 --- a/app/features/profile/Profile.ts +++ b/app/features/profile/Profile.ts @@ -33,3 +33,10 @@ export interface Profile { rank: number | null; characterSetting: CharacterSetting; } + +export interface Ranking { + id: string; + displayName: string; + highScore: number; + rank: number; +} diff --git a/app/hooks/useFetchRanking.ts b/app/hooks/useRanking.ts similarity index 53% rename from app/hooks/useFetchRanking.ts rename to app/hooks/useRanking.ts index b325c29..f1263a3 100644 --- a/app/hooks/useFetchRanking.ts +++ b/app/hooks/useRanking.ts @@ -1,30 +1,34 @@ import useSWRInfinite from "swr/infinite"; +import type { Ranking } from "~/features/profile/Profile"; 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; -} - -const fetchRankingData = async (page: number, limit: number) => { +const fetchRankingData = async ( + page: number, + limit: number, +): Promise => { const start = limit * page; const end = start + limit - 1; const { data } = await supabase .from("profiles_with_stats") - .select("*") + .select("user_id, display_name, high_score, play_count, rank") + .not("rank", "is", null) .order("rank", { ascending: true }) .range(start, end); - return data; + + if (!data) return []; + + return data.map((x) => ({ + id: x.user_id, + displayName: x.display_name, + // biome-ignore lint/style/noNonNullAssertion: high_scoreがnullでないことはクエリで保証されている + highScore: x.high_score!, + // biome-ignore lint/style/noNonNullAssertion: rankがnullでないことはクエリで保証されている + rank: x.rank!, + })); }; export function useFetchRanking(page = 0, limit = 20) { - const getKey = (page: number, previousPageData: Stats[] | null) => { + const getKey = (page: number, previousPageData: Ranking[] | null) => { if (previousPageData && previousPageData.length === 0) return null; return [page, limit]; }; From 0e79c30598b7b4b91aaf97a8a9343459fa5a5af6 Mon Sep 17 00:00:00 2001 From: NISHIZAWA Shuntaro Date: Thu, 7 Nov 2024 00:37:51 +0900 Subject: [PATCH 13/14] =?UTF-8?q?feat:=20Ranking=E3=81=AE=E3=82=B9?= =?UTF-8?q?=E3=82=BF=E3=82=A4=E3=83=AA=E3=83=B3=E3=82=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/Ranking.css | 75 ------------------------------------ app/components/Ranking.tsx | 78 ++++++++++++++++++++------------------ app/hooks/useRanking.ts | 10 +++-- 3 files changed, 48 insertions(+), 115 deletions(-) delete mode 100644 app/Ranking.css diff --git a/app/Ranking.css b/app/Ranking.css deleted file mode 100644 index 7270f33..0000000 --- a/app/Ranking.css +++ /dev/null @@ -1,75 +0,0 @@ -.ranking-item { - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px; - margin: 15px auto; - width: 800px; - border-radius: 10px; - background-color: #797878; - font-size: 24px; - border: 2px solid #333; - box-shadow: 3px 3px 5px rgba(0, 0, 0, 1); - text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); -} - -.ranking-title { - display: flex; - justify-content: center; - align-items: center; - margin: 5px auto; - width: 800px; - font-size: 36px; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); -} - -.rank-first { - color: #ffd700; -} - -.rank-second { - color: #c0c0c0; -} - -.rank-third { - color: #cd7f32; -} - -/* .rank-default{ - -} */ - -.name { - position: absolute; - left: 50%; - transform: translateX(-50%); -} - -/* .score{ - -} */ - -.ranking-load-button { - display: flex; - justify-content: center; - align-items: center; - padding: 5px; - margin: 15px auto; - width: 400px; - border-radius: 10px; - background-color: #797878; - font-size: 18px; - border: 2px solid #333; - box-shadow: 3px 3px 5px rgba(0, 0, 0, 1); - text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); -} - -.ranking-loading-text { - display: flex; - justify-content: center; - align-items: center; - margin: 5px auto; - width: 800px; - font-size: 18px; - text-shadow: 2px 2px 4px rgba(0, 0, 0, 1); -} diff --git a/app/components/Ranking.tsx b/app/components/Ranking.tsx index 78b3136..7fce61a 100644 --- a/app/components/Ranking.tsx +++ b/app/components/Ranking.tsx @@ -1,6 +1,6 @@ import { useEffect, useRef } from "react"; import { useFetchRanking } from "~/hooks/useRanking"; -import "../Ranking.css"; +import { cn } from "~/libs/utils"; interface RankingItemProps { rank: number | null; @@ -9,25 +9,34 @@ interface RankingItemProps { } function RankingItem({ rank, name, score }: RankingItemProps) { - const getRankClass = () => { - if (rank === 1) return "rank-first"; - if (rank === 2) return "rank-second"; - if (rank === 3) return "rank-third"; - return "rank-default"; - }; + let rankColorClass: string; + switch (rank) { + case 1: + rankColorClass = "text-yellow-400"; + break; + case 2: + rankColorClass = "text-gray-300"; + break; + case 3: + rankColorClass = "text-orange-500"; + break; + default: + rankColorClass = ""; + } return ( -
- {rank}位 - {name} - {score} -
+
  • + + {rank}位 + + {name} + {score} +
  • ); } export function RankingList() { - const { ranking, error, isLoading, isValidating, loadMore, hasMore } = - useFetchRanking(); + const { ranking, isValidating, loadMore, hasMore } = useFetchRanking(); const loadMoreRef = useRef(null); useEffect(() => { @@ -47,29 +56,26 @@ export function RankingList() { }; }, [isValidating, loadMore, hasMore]); - if (isLoading) return
    Loading...
    ; - if (error) return
    Error!!
    ; - - if (!ranking || ranking.length === 0) { - return
    No Ranking ranking.
    ; - } - return ( -
    -
    ランキング
    - {ranking.map( - (item) => - item && ( - - ), - )} -
    - {isValidating &&

    Loading...

    } +
    +
    ランキング
    +
      + {ranking.map( + (item) => + item && ( + + ), + )} +
    +
    + {isValidating && ( +
    + )}
    ); diff --git a/app/hooks/useRanking.ts b/app/hooks/useRanking.ts index f1263a3..d1699f7 100644 --- a/app/hooks/useRanking.ts +++ b/app/hooks/useRanking.ts @@ -27,18 +27,20 @@ const fetchRankingData = async ( })); }; -export function useFetchRanking(page = 0, limit = 20) { +export function useFetchRanking(limit = 20) { const getKey = (page: number, previousPageData: Ranking[] | null) => { if (previousPageData && previousPageData.length === 0) return null; return [page, limit]; }; - const { data, error, isLoading, isValidating, size, setSize } = - useSWRInfinite(getKey, ([page, limit]) => fetchRankingData(page, limit)); + const { data, error, isLoading, isValidating, setSize } = useSWRInfinite( + getKey, + ([page, limit]) => fetchRankingData(page, limit), + ); const ranking = data ? data.flat() : []; - const loadMore = () => setSize(size + 1); + const loadMore = () => setSize((prev) => prev + 1); return { ranking, From b221aeecac13e514dddc12fed49ed9845c4cf21f Mon Sep 17 00:00:00 2001 From: NISHIZAWA Shuntaro Date: Thu, 7 Nov 2024 00:52:24 +0900 Subject: [PATCH 14/14] =?UTF-8?q?feat:=20=E3=83=9B=E3=83=BC=E3=83=A0?= =?UTF-8?q?=E7=94=BB=E9=9D=A2=E3=81=AB=E3=83=A9=E3=83=B3=E3=82=AD=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/components/LogginCard.stories.tsx | 15 --------------- app/components/LoginCard.stories.tsx | 15 +++++++++++++++ app/components/{LogginCard.tsx => LoginCard.tsx} | 4 ++-- app/routes/_index/SignUp.tsx | 4 ++-- app/routes/_index/route.tsx | 8 ++++++-- 5 files changed, 25 insertions(+), 21 deletions(-) delete mode 100644 app/components/LogginCard.stories.tsx create mode 100644 app/components/LoginCard.stories.tsx rename app/components/{LogginCard.tsx => LoginCard.tsx} (88%) diff --git a/app/components/LogginCard.stories.tsx b/app/components/LogginCard.stories.tsx deleted file mode 100644 index 7b67577..0000000 --- a/app/components/LogginCard.stories.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import type { Meta, StoryObj } from "@storybook/react"; - -import { LogginCard } from "./LogginCard"; - -const meta: Meta = { - title: "Components/LogginCard", - component: LogginCard, - args: { - style: { width: "600px", height: "300px" }, - }, -}; - -export default meta; - -export const Default: StoryObj = {}; diff --git a/app/components/LoginCard.stories.tsx b/app/components/LoginCard.stories.tsx new file mode 100644 index 0000000..59953d9 --- /dev/null +++ b/app/components/LoginCard.stories.tsx @@ -0,0 +1,15 @@ +import type { Meta, StoryObj } from "@storybook/react"; + +import { LoginCard } from "./LoginCard"; + +const meta: Meta = { + title: "Components/LoginCard", + component: LoginCard, + args: { + style: { width: "600px", height: "300px" }, + }, +}; + +export default meta; + +export const Default: StoryObj = {}; diff --git a/app/components/LogginCard.tsx b/app/components/LoginCard.tsx similarity index 88% rename from app/components/LogginCard.tsx rename to app/components/LoginCard.tsx index 95e0dfa..992ee26 100644 --- a/app/components/LogginCard.tsx +++ b/app/components/LoginCard.tsx @@ -10,9 +10,9 @@ interface FormData { displayName: string; } -interface LogginCardProps extends ComponentPropsWithRef<"div"> {} +interface LoginCardProps extends ComponentPropsWithRef<"div"> {} -export function LogginCard({ className }: LogginCardProps): ReactNode { +export function LoginCard({ className }: LoginCardProps): ReactNode { const { register, handleSubmit } = useForm(); const onSubmit: SubmitHandler = async (data) => { diff --git a/app/routes/_index/SignUp.tsx b/app/routes/_index/SignUp.tsx index b0fa036..ae28128 100644 --- a/app/routes/_index/SignUp.tsx +++ b/app/routes/_index/SignUp.tsx @@ -1,11 +1,11 @@ import type { ReactNode } from "react"; -import { LogginCard } from "~/components/LogginCard"; +import { LoginCard } from "~/components/LoginCard"; export function SignUp(): ReactNode { return (
    RicoShot - +
    ); } diff --git a/app/routes/_index/route.tsx b/app/routes/_index/route.tsx index c047c94..b8c9b1f 100644 --- a/app/routes/_index/route.tsx +++ b/app/routes/_index/route.tsx @@ -1,7 +1,7 @@ import type { MetaFunction } from "@remix-run/react"; -import { Button } from "~/components/Button"; import { Heading } from "~/components/Heading"; import { ProfileCard } from "~/components/ProfileCard"; +import { RankingList } from "~/components/Ranking"; import { useMyProfile } from "~/features/profile/useMyProfile"; import { SignUp } from "./SignUp"; @@ -17,10 +17,14 @@ export default function Page() { >
    {myProfile ? ( - + <> + ホーム + + ) : ( )} +
    );