Skip to content

Commit d13b981

Browse files
committed
fix: mobile layouts
1 parent ec3de82 commit d13b981

File tree

19 files changed

+577
-85
lines changed

19 files changed

+577
-85
lines changed

app/[lang]/(common)/Header/index.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,9 @@ function MobileNavMenus(
148148
<nav
149149
className={clsx(
150150
'absolute top-14 right-0 w-full bg-basic pb-2',
151+
'max-h-[calc(100vh-56px)] overflow-y-auto',
151152
'flex flex-col',
153+
'z-50',
152154
isNavCollapsed ? 'hidden' : 'flex',
153155
)}
154156
>

app/[lang]/error.tsx

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
'use client';
2+
3+
import {useEffect} from 'react';
4+
import {useParams} from 'next/navigation';
5+
import {Inter} from 'next/font/google';
6+
import clsx from 'clsx';
7+
import Logo from 'public/assets/logo.svg';
8+
9+
const inter = Inter({subsets: ['latin']});
10+
11+
// Client-side translations fallback
12+
const translations = {
13+
en: {
14+
serverError: 'Something Went Wrong',
15+
serverErrorDesc: 'An unexpected error occurred. Please try again later.',
16+
goHome: 'Go Home',
17+
tryAgain: 'Try Again',
18+
},
19+
ko: {
20+
serverError: '오류가 발생했습니다',
21+
serverErrorDesc: '예기치 않은 오류가 발생했습니다. 잠시 후 다시 시도해주세요.',
22+
goHome: '홈으로',
23+
tryAgain: '다시 시도',
24+
},
25+
};
26+
27+
export default function Error({
28+
error,
29+
reset,
30+
}: {
31+
error: Error & {digest?: string};
32+
reset: () => void;
33+
}) {
34+
const params = useParams();
35+
const lang = (params?.lang as 'en' | 'ko') || 'en';
36+
const t = translations[lang];
37+
38+
useEffect(() => {
39+
console.error('Error:', error);
40+
}, [error]);
41+
42+
return (
43+
<div
44+
className={clsx(
45+
'flex-1 w-full overflow-hidden',
46+
'flex flex-col justify-center items-center',
47+
'px-4',
48+
)}
49+
>
50+
<div
51+
className={clsx(
52+
'bg-modal max-w-[480px] w-full rounded-2xl px-12 py-16',
53+
'flex flex-col items-center justify-center',
54+
)}
55+
>
56+
<Logo className="w-20 h-20 mb-2 text-brand" />
57+
<p className={clsx('text-brand pb-8', inter.className)}>github-stats</p>
58+
59+
<h1
60+
className={clsx(
61+
'text-9xl font-bold text-contrast mb-4',
62+
inter.className,
63+
)}
64+
>
65+
500
66+
</h1>
67+
<h2
68+
className={clsx(
69+
'text-3xl font-semibold text-contrast mb-4',
70+
inter.className,
71+
)}
72+
>
73+
{t.serverError}
74+
</h2>
75+
<p
76+
className={clsx(
77+
'text-placeholder text-center mb-8 max-w-md',
78+
inter.className,
79+
)}
80+
>
81+
{t.serverErrorDesc}
82+
</p>
83+
84+
<div className="flex gap-4 justify-center">
85+
<button
86+
onClick={reset}
87+
className={clsx(
88+
'px-8 py-3 rounded-lg',
89+
'bg-border hover:opacity-80',
90+
'text-contrast font-medium',
91+
'transition-all duration-200',
92+
inter.className,
93+
)}
94+
>
95+
{t.tryAgain}
96+
</button>
97+
<a
98+
href={`/${lang}`}
99+
className={clsx(
100+
'inline-block px-8 py-3 rounded-lg',
101+
'bg-btn-primary hover:opacity-80',
102+
'text-btn-primary-text font-medium',
103+
'transition-all duration-200',
104+
inter.className,
105+
)}
106+
>
107+
{t.goHome}
108+
</a>
109+
</div>
110+
</div>
111+
</div>
112+
);
113+
}

app/[lang]/layout.tsx

Lines changed: 21 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
export const revalidate = 3600
22

33
import 'server-only';
4-
import '../../styles/output.css';
54

65
import type {ReactElement, ReactNode} from 'react';
76
import clsx from 'clsx';
@@ -18,48 +17,33 @@ type Props = {
1817
params: Promise<{lang: string}>;
1918
};
2019

21-
export default async function RootLayout(props: Props): Promise<ReactElement> {
20+
export default async function LangLayout(props: Props): Promise<ReactElement> {
2221
const params = await props.params;
2322
const lang = params.lang as Locale;
2423
const {children} = props;
2524

2625
const {langs, nav} = await getTranslates(lang);
2726

2827
return (
29-
<html lang={lang} className="dark">
30-
<title>github-stats</title>
31-
<meta content="width=device-width, initial-scale=1" name="viewport" />
32-
<meta name="description" content="All stats for developers" />
33-
<link rel="icon" href="/favicon.ico" />
34-
<head>
35-
<script
36-
async
37-
src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8181493727238996"
38-
crossOrigin="anonymous"
39-
></script>
40-
</head>
41-
<body>
42-
<RootProvider initialLocale={lang}>
43-
<main
44-
className={clsx(
45-
'text-center flex-1 self-stretch relative',
46-
'flex flex-col-reverse',
47-
)}
48-
>
49-
<div className={clsx('h-[calc(100vh-56px)]', 'flex')}>
50-
{children}
51-
</div>
52-
<Header
53-
t={nav}
54-
lang={lang}
55-
langs={{
56-
en: langs.en,
57-
ko: langs.ko,
58-
}}
59-
/>
60-
</main>
61-
</RootProvider>
62-
</body>
63-
</html>
28+
<RootProvider initialLocale={lang}>
29+
<main
30+
className={clsx(
31+
'text-center flex-1 self-stretch relative',
32+
'flex flex-col-reverse',
33+
)}
34+
>
35+
<div className={clsx('h-[calc(100vh-56px)]', 'flex')}>
36+
{children}
37+
</div>
38+
<Header
39+
t={nav}
40+
lang={lang}
41+
langs={{
42+
en: langs.en,
43+
ko: langs.ko,
44+
}}
45+
/>
46+
</main>
47+
</RootProvider>
6448
);
6549
}

app/[lang]/not-found.tsx

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import type {ReactElement} from 'react';
2+
import Link from 'next/link';
3+
import {Inter} from 'next/font/google';
4+
import clsx from 'clsx';
5+
import Logo from 'public/assets/logo.svg';
6+
7+
import {getTranslates} from '../../src/localization';
8+
9+
import type {Locale} from '~/i18n';
10+
11+
const inter = Inter({subsets: ['latin']});
12+
13+
type Props = {
14+
params: Promise<{lang: string}>;
15+
};
16+
17+
export default async function NotFound(props: Props): Promise<ReactElement> {
18+
const params = await props.params;
19+
const lang = (params?.lang || 'en') as Locale;
20+
const {error} = await getTranslates(lang);
21+
22+
return (
23+
<div
24+
className={clsx(
25+
'flex-1 w-full overflow-hidden',
26+
'flex flex-col justify-center items-center',
27+
'px-4',
28+
)}
29+
>
30+
<div
31+
className={clsx(
32+
'bg-modal max-w-[480px] w-full rounded-2xl px-12 py-16',
33+
'flex flex-col items-center justify-center',
34+
)}
35+
>
36+
<Logo className="w-20 h-20 mb-2 text-brand" />
37+
<p className={clsx('text-brand pb-8', inter.className)}>github-stats</p>
38+
39+
<h1
40+
className={clsx(
41+
'text-9xl font-bold text-contrast mb-4',
42+
inter.className,
43+
)}
44+
>
45+
404
46+
</h1>
47+
<h2
48+
className={clsx(
49+
'text-3xl font-semibold text-contrast mb-4',
50+
inter.className,
51+
)}
52+
>
53+
{error.notFound}
54+
</h2>
55+
<p
56+
className={clsx(
57+
'text-placeholder text-center mb-8 max-w-md',
58+
inter.className,
59+
)}
60+
>
61+
{error.notFoundDesc}
62+
</p>
63+
64+
<Link
65+
href={`/${lang}`}
66+
className={clsx(
67+
'inline-block px-8 py-3 rounded-lg',
68+
'bg-btn-primary hover:opacity-80',
69+
'text-btn-primary-text font-medium',
70+
'transition-all duration-200',
71+
inter.className,
72+
)}
73+
>
74+
{error.goHome}
75+
</Link>
76+
</div>
77+
</div>
78+
);
79+
}

app/[lang]/recent-list/page.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default async function Page(props: Props): Promise<ReactElement> {
3939
className={clsx(
4040
'mt-4 mb-[32px] px-6 w-full',
4141
'flex flex-row items-center justify-between gap-4',
42-
'max-[480px]:flex-col max-[480px]:items-start max-[480px]:mb-0 max-[480px]:my-4',
42+
'max-[480px]:flex-col max-[480px]:items-start max-[480px]:mb-6 max-[480px]:mt-2',
4343
)}
4444
>
4545
<H1
@@ -52,7 +52,7 @@ export default async function Page(props: Props): Promise<ReactElement> {
5252
{recentList.title}
5353
</H1>
5454
<GreatFrontEnd
55-
className="max-w-[400px] shrink-0 max-[480px]:mt-4 max-[480px]:max-w-full"
55+
className="max-w-[400px] shrink-0 max-[480px]:mt-2 max-[480px]:max-w-full"
5656
href="https://www.greatfrontend.com/questions/formats/quiz?fpr=hyo73"
5757
title="Quiz interview questions"
5858
/>

app/[lang]/stats/Container.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ export default function Container({t, children, headerSearch, headerRight}: Prop
2020
return (
2121
<div
2222
className={clsx(
23-
'flex-1 bg-paper overflow-hidden px-6',
24-
'max-[480px]:px-0',
23+
'flex-1 bg-paper overflow-y-auto overflow-x-hidden',
24+
'px-6 max-[768px]:px-4 max-[480px]:px-2',
2525
'flex flex-col',
2626
)}
2727
>
@@ -31,7 +31,7 @@ export default function Container({t, children, headerSearch, headerRight}: Prop
3131
<H1
3232
className={clsx(
3333
'text-[44px] font-bold mt-12 mb-[28px]',
34-
'max-[480px]:px-6 max-[480px]:text-[28px] max-[480px]:mb-0 max-[480px]:mt-4',
34+
'max-[480px]:px-6 max-[480px]:text-[28px] max-[480px]:mb-4 max-[480px]:mt-4',
3535
'max-[380px]:hidden',
3636
inter.className,
3737
)}
@@ -46,7 +46,7 @@ export default function Container({t, children, headerSearch, headerRight}: Prop
4646
<H1
4747
className={clsx(
4848
'text-[44px] font-bold mt-12 mb-[28px] text-center',
49-
'max-[480px]:px-6 max-[480px]:text-[28px] max-[480px]:mb-0 max-[480px]:mt-4',
49+
'max-[480px]:px-6 max-[480px]:text-[28px] max-[480px]:mb-4 max-[480px]:mt-4',
5050
'max-[380px]:hidden',
5151
inter.className,
5252
)}

app/[lang]/stats/[login]/Scouter/StatsDetails/SectionEarth.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ function SectionBody({stats}: SectionProps): ReactElement {
7777

7878
return (
7979
<div key={el.name} className={clsx('mb-6', 'flex flex-col')}>
80-
<p
80+
<div
8181
className={clsx(
8282
'text-basic font-bold mb-6',
8383
'flex flex-row items-center',
@@ -95,12 +95,12 @@ function SectionBody({stats}: SectionProps): ReactElement {
9595
maximumFractionDigits: 0,
9696
})}
9797
</div>
98-
</p>
99-
{details.map((detail: StatsDetail) => {
98+
</div>
99+
{details.map((detail: StatsDetail, index: number) => {
100100
switch (detail.type) {
101101
case 'repository':
102102
return (
103-
<div key={`${el.name}-${detail.name}`}>
103+
<div key={`${el.name}-${detail.name}-${index}`}>
104104
<a href={detail.url} className="mb-4">
105105
<p
106106
className={clsx(
@@ -116,7 +116,7 @@ function SectionBody({stats}: SectionProps): ReactElement {
116116
case 'commit':
117117
return (
118118
<div
119-
key={`${el.name}-${detail.name}`}
119+
key={`${el.name}-${detail.name}-${detail.sha || ''}-${index}`}
120120
className="flex flex-col"
121121
>
122122
<div className="flex flex-row items-center">

app/[lang]/stats/[login]/Scouter/StatsDetails/SectionFire.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ function SectionBody({stats}: SectionProps): ReactElement {
7575

7676
return (
7777
<div key={el.name} className={clsx('mb-6', 'flex flex-col')}>
78-
<p
78+
<div
7979
className={clsx(
8080
'text-basic font-bold mb-6',
8181
'flex flex-row items-center',
@@ -93,14 +93,13 @@ function SectionBody({stats}: SectionProps): ReactElement {
9393
maximumFractionDigits: 0,
9494
})}
9595
</div>
96-
</p>
96+
</div>
9797
{details.map((detail: StatsDetail) => {
9898
switch (detail.type) {
9999
case 'repository':
100100
return (
101-
<div>
101+
<div key={`${el.name}-${detail.name}`}>
102102
<a
103-
key={`${el.name}-${detail.name}`}
104103
href={detail.url}
105104
className="mb-4"
106105
>

0 commit comments

Comments
 (0)