diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 34bf9c9..e09f98b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: run: echo "${{ secrets.DOTENV }}" > .env - name: npm-install - run: npm i + run: npm i --legacy-peer-deps - name: npm-build run: npm run build \ No newline at end of file diff --git a/next.config.ts b/next.config.ts index a6ba807..8e82640 100644 --- a/next.config.ts +++ b/next.config.ts @@ -21,6 +21,9 @@ const nextConfig: NextConfig = { }, ], }, + experimental: { + useCache: true, + }, } export default nextConfig diff --git a/package-lock.json b/package-lock.json index b6c5288..2ee4c91 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17,7 +17,7 @@ "date-fns": "^4.1.0", "highcharts": "^11.4.8", "highcharts-react-official": "^3.2.1", - "next": "15.1.3", + "next": "^15.2.0-canary.56", "react": "^18.3.1", "react-dom": "^18.3.1", "recharts": "^2.13.0-alpha.5", @@ -660,9 +660,10 @@ } }, "node_modules/@next/env": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/env/-/env-15.1.3.tgz", - "integrity": "sha512-Q1tXwQCGWyA3ehMph3VO+E6xFPHDKdHFYosadt0F78EObYxPio0S09H9UGYznDe6Wc8eLKLG89GqcFJJDiK5xw==" + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/@next/env/-/env-15.2.0-canary.56.tgz", + "integrity": "sha512-QQQdvJeXdXb2lLzaTTib08gUft7PSQwur0ARuKl0deukW5z3icrjdIjKaBFHhSvQzDdO5TZav3UwC5LXE5Zeww==", + "license": "MIT" }, "node_modules/@next/eslint-plugin-next": { "version": "15.0.3", @@ -675,12 +676,13 @@ } }, "node_modules/@next/swc-darwin-arm64": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.1.3.tgz", - "integrity": "sha512-aZtmIh8jU89DZahXQt1La0f2EMPt/i7W+rG1sLtYJERsP7GRnNFghsciFpQcKHcGh4dUiyTB5C1X3Dde/Gw8gg==", + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-15.2.0-canary.56.tgz", + "integrity": "sha512-zFc4Fz3xRwIWnOIoFqIAZ6M2P5OtY4WGqtDpUKTJyQp19MTvIzTAXaZbkDjNSHd4i53gzX07Y56O7KF1L16QwA==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -690,12 +692,13 @@ } }, "node_modules/@next/swc-darwin-x64": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.1.3.tgz", - "integrity": "sha512-aw8901rjkVBK5mbq5oV32IqkJg+CQa6aULNlN8zyCWSsePzEG3kpDkAFkkTOh3eJ0p95KbkLyWBzslQKamXsLA==", + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-15.2.0-canary.56.tgz", + "integrity": "sha512-qIQ2PfkrBS3TZPQ489hCVYL0WKdhEJIXL+GhK8qN17U2+fow75Xp6VDH5lV5vjpCCAf2jM2Vt7fqqq9V6G8hEQ==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "darwin" @@ -705,12 +708,13 @@ } }, "node_modules/@next/swc-linux-arm64-gnu": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.1.3.tgz", - "integrity": "sha512-YbdaYjyHa4fPK4GR4k2XgXV0p8vbU1SZh7vv6El4bl9N+ZSiMfbmqCuCuNU1Z4ebJMumafaz6UCC2zaJCsdzjw==", + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-15.2.0-canary.56.tgz", + "integrity": "sha512-Xw/8v4CoH9pGTGWfdRZEiVEymHSWepaZGOOxUO9iakWE/vn1RAQ3zDcRMWf/4iXBRrnOCpjaL2V0hSpFBBYu3Q==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -720,12 +724,13 @@ } }, "node_modules/@next/swc-linux-arm64-musl": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.1.3.tgz", - "integrity": "sha512-qgH/aRj2xcr4BouwKG3XdqNu33SDadqbkqB6KaZZkozar857upxKakbRllpqZgWl/NDeSCBYPmUAZPBHZpbA0w==", + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-15.2.0-canary.56.tgz", + "integrity": "sha512-xFouHVVWV4ek9krTVcH7QjQVnHLdGBjghpbywtMq5ECx348/ayBIzpPX212tqFubnL7sHgWspVG/3DPcU308Qg==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -735,12 +740,13 @@ } }, "node_modules/@next/swc-linux-x64-gnu": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.1.3.tgz", - "integrity": "sha512-uzafnTFwZCPN499fNVnS2xFME8WLC9y7PLRs/yqz5lz1X/ySoxfaK2Hbz74zYUdEg+iDZPd8KlsWaw9HKkLEVw==", + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-15.2.0-canary.56.tgz", + "integrity": "sha512-+wKHUGxqAi7LGCXluoM3fdukLL5GKoufpKB7/o46gtdxoUGyVvwAfh1Y10kV3IWYo7rK77T8h3upRz8nKhvsug==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -750,12 +756,13 @@ } }, "node_modules/@next/swc-linux-x64-musl": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.1.3.tgz", - "integrity": "sha512-el6GUFi4SiDYnMTTlJJFMU+GHvw0UIFnffP1qhurrN1qJV3BqaSRUjkDUgVV44T6zpw1Lc6u+yn0puDKHs+Sbw==", + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-15.2.0-canary.56.tgz", + "integrity": "sha512-sGolcgd/ZZgiZAP3sTNRXS5csavhp+SZgBuniA4EerXy6HbvJcb8ioiigmfLim8BYouZN51EvPtiYh6yMD55rw==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "linux" @@ -765,12 +772,13 @@ } }, "node_modules/@next/swc-win32-arm64-msvc": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.1.3.tgz", - "integrity": "sha512-6RxKjvnvVMM89giYGI1qye9ODsBQpHSHVo8vqA8xGhmRPZHDQUE4jcDbhBwK0GnFMqBnu+XMg3nYukNkmLOLWw==", + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-15.2.0-canary.56.tgz", + "integrity": "sha512-FM4qC7pFfsYvJFgOmQC68DJJFmDvqeloS4PYLxvfxOksXyDOb4HFlqmJ3tfTA6NHnm/c7PHXswVeR/6wyGX8Fg==", "cpu": [ "arm64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -780,12 +788,13 @@ } }, "node_modules/@next/swc-win32-x64-msvc": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.1.3.tgz", - "integrity": "sha512-VId/f5blObG7IodwC5Grf+aYP0O8Saz1/aeU3YcWqNdIUAmFQY3VEPKPaIzfv32F/clvanOb2K2BR5DtDs6XyQ==", + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-15.2.0-canary.56.tgz", + "integrity": "sha512-lNdyWbZcT8u9tCvG+yjBtLtDt5O5DhtYN/+GjAq0aQ5DGnvJhdza3PkvAW28zjFU1QAHGvjXQGI/fWFl6V+a5A==", "cpu": [ "x64" ], + "license": "MIT", "optional": true, "os": [ "win32" @@ -1667,9 +1676,9 @@ "license": "ISC" }, "node_modules/@vercel/analytics": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.4.1.tgz", - "integrity": "sha512-ekpL4ReX2TH3LnrRZTUKjHHNpNy9S1I7QmS+g/RQXoSUQ8ienzosuX7T9djZ/s8zPhBx1mpHP/Rw5875N+zQIQ==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vercel/analytics/-/analytics-1.5.0.tgz", + "integrity": "sha512-MYsBzfPki4gthY5HnYN7jgInhAZ7Ac1cYDoRWFomwGHWEX7odTEzbtg9kf/QSo7XEsEAqlQugA6gJ2WS2DEa3g==", "license": "MPL-2.0", "peerDependencies": { "@remix-run/react": "^2", @@ -4652,7 +4661,7 @@ "version": "5.0.2", "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.2.tgz", "integrity": "sha512-1NU7hWZDkV7hJ4PJ9dur9gTNQ4ePNPN4k9/0YhwjzykTi/+3Q5pF93YU5QoVj8BuOnhLgaY8gs0U2pj4kSYVcw==", - "devOptional": true, + "dev": true, "license": "MIT" }, "node_modules/import-fresh": { @@ -6003,11 +6012,12 @@ "license": "MIT" }, "node_modules/next": { - "version": "15.1.3", - "resolved": "https://registry.npmjs.org/next/-/next-15.1.3.tgz", - "integrity": "sha512-5igmb8N8AEhWDYzogcJvtcRDU6n4cMGtBklxKD4biYv4LXN8+awc/bbQ2IM2NQHdVPgJ6XumYXfo3hBtErg1DA==", + "version": "15.2.0-canary.56", + "resolved": "https://registry.npmjs.org/next/-/next-15.2.0-canary.56.tgz", + "integrity": "sha512-DgMJ7OednjNUN+fWSCUvaf+e5yJKdprHkHe5FB2UUdVkAqX2Kr6PbGNkEz2MV6ayG+8gQ8u2nrZ1yUhuSRkSdA==", + "license": "MIT", "dependencies": { - "@next/env": "15.1.3", + "@next/env": "15.2.0-canary.56", "@swc/counter": "0.1.3", "@swc/helpers": "0.5.15", "busboy": "1.6.0", @@ -6022,14 +6032,14 @@ "node": "^18.18.0 || ^19.8.0 || >= 20.0.0" }, "optionalDependencies": { - "@next/swc-darwin-arm64": "15.1.3", - "@next/swc-darwin-x64": "15.1.3", - "@next/swc-linux-arm64-gnu": "15.1.3", - "@next/swc-linux-arm64-musl": "15.1.3", - "@next/swc-linux-x64-gnu": "15.1.3", - "@next/swc-linux-x64-musl": "15.1.3", - "@next/swc-win32-arm64-msvc": "15.1.3", - "@next/swc-win32-x64-msvc": "15.1.3", + "@next/swc-darwin-arm64": "15.2.0-canary.56", + "@next/swc-darwin-x64": "15.2.0-canary.56", + "@next/swc-linux-arm64-gnu": "15.2.0-canary.56", + "@next/swc-linux-arm64-musl": "15.2.0-canary.56", + "@next/swc-linux-x64-gnu": "15.2.0-canary.56", + "@next/swc-linux-x64-musl": "15.2.0-canary.56", + "@next/swc-win32-arm64-msvc": "15.2.0-canary.56", + "@next/swc-win32-x64-msvc": "15.2.0-canary.56", "sharp": "^0.33.5" }, "peerDependencies": { @@ -7237,7 +7247,7 @@ "version": "1.81.0", "resolved": "https://registry.npmjs.org/sass/-/sass-1.81.0.tgz", "integrity": "sha512-Q4fOxRfhmv3sqCLoGfvrC9pRV8btc0UtqL9mN6Yrv6Qi9ScL55CVH1vlPP863ISLEEMNLLuu9P+enCeGHlnzhA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "chokidar": "^4.0.0", @@ -7299,7 +7309,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz", "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "readdirp": "^4.0.1" @@ -7315,7 +7325,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz", "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">= 14.16.0" diff --git a/package.json b/package.json index 6e2b505..28c14c8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "medusa", - "version": "0.1.0", + "version": "0.2.0", "private": true, "scripts": { "dev": "next dev --turbopack", @@ -10,7 +10,8 @@ "lint": "next lint --fix", "format": "prettier --write .", "prepare": "husky", - "check:deps": "depcruise src" + "check:deps": "depcruise src", + "check:types": "tsx --noEmit" }, "dependencies": { "@date-fns/tz": "^1.2.0", @@ -22,7 +23,7 @@ "date-fns": "^4.1.0", "highcharts": "^11.4.8", "highcharts-react-official": "^3.2.1", - "next": "15.1.3", + "next": "^15.2.0-canary.56", "react": "^18.3.1", "react-dom": "^18.3.1", "recharts": "^2.13.0-alpha.5", diff --git a/public/image/banner.png b/public/image/banner.png new file mode 100644 index 0000000..c8722dc Binary files /dev/null and b/public/image/banner.png differ diff --git a/public/image/icon.png b/public/image/icon.png new file mode 100644 index 0000000..7974afb Binary files /dev/null and b/public/image/icon.png differ diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 42741d1..ba92805 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -1,3 +1,5 @@ +'use cache' + import { Analytics } from '@vercel/analytics/react' import { SpeedInsights } from '@vercel/speed-insights/next' @@ -12,9 +14,22 @@ export const metadata: Metadata = { default: '閻魔帳', }, description: 'チェイスチェイスジョーカーズのプレイ履歴を分析します。', + openGraph: { + title: '閻魔帳', + description: 'チェイスチェイスジョーカーズのプレイ履歴を分析します。', + url: 'https://放課後天地創造.club', + images: '/image/banner.png', + }, + twitter: { + title: '閻魔帳', + description: 'チェイスチェイスジョーカーズのプレイ履歴を分析します。', + site: '@sweshelo', + images: '/image/banner.png', + }, + icons: '/image/icon.png', } -export default function RootLayout({ +export default async function RootLayout({ children, }: Readonly<{ children: React.ReactNode diff --git a/src/app/player/[name]/page.tsx b/src/app/player/[name]/page.tsx index e2e1adb..c9db3a7 100644 --- a/src/app/player/[name]/page.tsx +++ b/src/app/player/[name]/page.tsx @@ -1,3 +1,5 @@ +'use cache' + import { Metadata } from 'next' import { PlayerPage } from '@/features/player' diff --git a/src/app/ranking/page.tsx b/src/app/ranking/page.tsx index 3999cb1..743ac09 100644 --- a/src/app/ranking/page.tsx +++ b/src/app/ranking/page.tsx @@ -1,3 +1,5 @@ +'use cache' + import { Metadata } from 'next' import RankingPage from '@/features/ranking' diff --git a/src/components/header/index.tsx b/src/components/header/index.tsx index 2928b6a..7058987 100644 --- a/src/components/header/index.tsx +++ b/src/components/header/index.tsx @@ -3,11 +3,9 @@ import Link from 'next/link' export const Header = () => { return ( -
+
-
-
-
+

閻魔帳

v2 "medusa" - @sweshelo

diff --git a/src/components/revalidater/action.ts b/src/components/revalidater/action.ts new file mode 100644 index 0000000..66e11f6 --- /dev/null +++ b/src/components/revalidater/action.ts @@ -0,0 +1,7 @@ +'use server' + +import { revalidateTag } from 'next/cache' + +export const revalidateUserData = async (user: string) => { + revalidateTag(user) +} diff --git a/src/components/revalidater/index.tsx b/src/components/revalidater/index.tsx new file mode 100644 index 0000000..215e3e6 --- /dev/null +++ b/src/components/revalidater/index.tsx @@ -0,0 +1,17 @@ +'use client' + +import { revalidateUserData } from './action' + +interface Props { + player: string +} + +export const Revalidater = ({ player }: Props) => { + return ( +
+ +
+ ) +} diff --git a/src/features/player/index.tsx b/src/features/player/index.tsx index 58fc5a4..f01957a 100644 --- a/src/features/player/index.tsx +++ b/src/features/player/index.tsx @@ -1,18 +1,23 @@ +import { cacheTag } from 'next/dist/server/use-cache/cache-tag' + import { AchievementView } from '@/components/achievement' import { PointsLineChart } from '@/components/charts/line-chart' -// import { Shiny } from '@/components/common/shiny' +import { Shiny } from '@/components/common/shiny' import { SmallHeadline } from '@/components/common/small-headline' import { PlayerCard } from '@/components/player/card' import { RecordsTable } from '@/components/records-table' +// import { Revalidater } from '@/components/revalidater' import { Database } from '@/types/database.types' interface PlayerPageProps { player: Database['public']['Tables']['player']['Row'] & { records: Database['public']['Tables']['record']['Row'][] + maxPoints?: number } } export const PlayerPage = ({ player }: PlayerPageProps) => { + cacheTag(player.name) const [digest] = player.records return digest ? ( @@ -22,64 +27,86 @@ export const PlayerPage = ({ player }: PlayerPageProps) => {
-
-
-
-

最高ランキング

-
-
-

- 位

-
-
-
+
+ { + switch (player.ranking) { + case 1: + return 'shiny-rainbow' + case 2: + return 'shiny-silver' + case 3: + return 'shiny-copper' + default: + return 'shiny-none' + } + })()} + >
-

最高貢献P

+

最高ランキング

-

-

+

{player.ranking && `${player.ranking}位`}

-
-
-
-

平均貢献P

-
-
-

-

-
-
-
-
-

有効平均貢献P

-
-
-

-

-
-
-
+ + { + if (!player.average) return 'shiny-none' + if (player.average > 230) { + return 'shiny-rainbow' + } else if (player.average > 210) { + return 'shiny-gold' + } else if (player.average > 190) { + return 'shiny-silver' + } else if (player.average > 180) { + return 'shiny-copper' + } else { + return 'shiny-none' + } + })()} + >
-

自己標準偏差

+

平均貢献P

-

-

+

{player.average ?? '-'}

-
-
-
-

全国偏差値

-
-
-

-

+ + { + if (!player.deviation_value) return 'shiny-none' + if (player.deviation_value > 70) { + return 'shiny-rainbow' + } else if (player.deviation_value > 65) { + return 'shiny-gold' + } else if (player.deviation_value > 60) { + return 'shiny-silver' + } else if (player.deviation_value > 55) { + return 'shiny-copper' + } else { + return 'shiny-none' + } + })()} + > +
+
+

全国偏差値

+
+
+

{player.deviation_value ?? '-'}

+
-
-
- 準備中 -
+
+ {/**/}
diff --git a/src/service/supabase/player.ts b/src/service/supabase/player.ts index e395c0a..ed97e7e 100644 --- a/src/service/supabase/player.ts +++ b/src/service/supabase/player.ts @@ -2,16 +2,18 @@ import { supabase } from './client' export const fetchPlayer = async (playerName: string) => { // プレイヤー情報を取得 - const { data: player, error: playerError } = await supabase + const { data: players, error: playerError } = await supabase .from('player') .select('*') .eq('name', playerName) - .single() + .limit(1) if (playerError) { throw new Error(`Error fetching player: ${playerError.message}`) } + const [player] = players + // レコードを取得(新しい順に300件まで) const { data: records, error: recordsError } = await supabase .from('record') @@ -24,8 +26,28 @@ export const fetchPlayer = async (playerName: string) => { throw new Error(`Error fetching records: ${recordsError.message}`) } + // 最高ランキング + const { data: rankings } = await supabase + .from('record') + .select('ranking') + .eq('player_name', playerName) + .order('ranking', { ascending: true }) + .limit(1) + const ranking = rankings?.[0].ranking ?? null + + // 最高貢献度 + const { data: max } = await supabase + .from('record') + .select('diff') + .eq('player_name', playerName) + .order('diff', { ascending: false }) + .limit(1) + const maxPoint = max?.[0].diff + return { ...player, + maxPoint, + ranking, records, } } diff --git a/src/styles/shiny.module.scss b/src/styles/shiny.module.scss index 56b564c..8179b9c 100644 --- a/src/styles/shiny.module.scss +++ b/src/styles/shiny.module.scss @@ -50,6 +50,11 @@ animation-timing-function: linear; } +.shiny-none { + $color: white; + background: white; +} + @keyframes shine { 0% { background-position-x: 400%;