Skip to content

Commit 5de5931

Browse files
arkwnetCopiloth-takeyeah
authored
Feat/frontend/improve UI (#246)
## チケットへのリンク 無し ## やったこと UIデザインの軽微な改善 (特にGamePreとGameResult) ## やらないこと 挙動及び大規模なデザインの変更 ## できるようになること(ユーザ目線) 無し ## できなくなること(ユーザ目線) 無し ## 動作確認 全機能を目視で確認していますが、レビューされる方はお手元の環境でダブルチェックをお願いします (特に生協指定PCをお持ちの方) ## その他 無し <!-- devin-review-badge-begin --> --- <a href="https://app.devin.ai/review/su-its/typing/pull/246" target="_blank"> <picture> <source media="(prefers-color-scheme: dark)" srcset="https://static.devin.ai/assets/gh-open-in-devin-review-dark.svg?v=1"> <img src="https://static.devin.ai/assets/gh-open-in-devin-review-light.svg?v=1" alt="Open with Devin"> </picture> </a> <!-- devin-review-badge-end --> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: h-takeyeah <61489178+h-takeyeah@users.noreply.github.com>
1 parent c5e49c5 commit 5de5931

11 files changed

Lines changed: 124 additions & 34 deletions

File tree

-5.1 KB
Loading

typing-app/src/app/DisableTab.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
"use client";
2+
import { useEffect } from "react";
3+
export default function DisableTab() {
4+
useEffect(() => {
5+
const handleKeyDown = (e: KeyboardEvent) => {
6+
if (e.key === "Tab") {
7+
e.preventDefault();
8+
}
9+
};
10+
window.addEventListener("keydown", handleKeyDown);
11+
return () => {
12+
window.removeEventListener("keydown", handleKeyDown);
13+
};
14+
}, []);
15+
return null;
16+
}

typing-app/src/app/globals.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
padding: 0;
1010
font-family: "メイリオ", "Meiryo", "Hiragino Kaku Gothic Pro", "ヒラギノ角ゴ Pro W3", "MS Pゴシック", sans-serif;
1111
box-sizing: border-box;
12+
user-select: none;
1213
}
1314

1415
body {

typing-app/src/app/layout.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Metadata } from "next";
2+
import DisableTab from "./DisableTab";
23
import Header from "../components/organism/Header";
34
import Footer from "../components/organism/Footer";
45
import Toast from "../components/organism/Toast";
@@ -16,6 +17,7 @@ export default async function RootLayout({
1617
return (
1718
<html lang="ja">
1819
<body>
20+
<DisableTab />
1921
<Header />
2022
<Footer />
2123
<div className="children">{children}</div>

typing-app/src/assets/sass/color.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
$black: #000;
22
$white: #fff;
3+
$red-200: #ef9a9a;
34
$red-500: #f44336;
45
$red-800: #c62828;
56
$yellow-500: #ffeb3b;
7+
$blue-200: #90caf9;
68
$blue-500: #2196f3;
79
$blue-800: #1565c0;
810
$green-500: #4caf50;

typing-app/src/components/molecules/LoginModal.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import React, { useActionState } from "react";
3+
import React, { useActionState, useEffect } from "react";
44
import { login } from "@/app/actions";
55
import { showWarningToast } from "@/utils/toast";
66
import styles from "@/assets/sass/molecules/LoginModal.module.scss";
@@ -14,18 +14,19 @@ interface LoginModalProps {
1414
}
1515

1616
const LoginModalPresenter: React.FC<LoginModalProps> = ({ isOpen, onClose, state, dispatchAction, pending }) => {
17+
useEffect(() => {
18+
if (!pending && state.error) {
19+
showWarningToast(state.error);
20+
}
21+
}, [pending, state.error]);
22+
1723
return (
1824
<>
1925
{isOpen && (
2026
<div className={styles.modal}>
2127
<div className={styles.overlay}></div>
2228
<div className={styles.content}>
23-
<form
24-
action={async (formData: FormData) => {
25-
await dispatchAction(formData);
26-
state.error && showWarningToast(state.error);
27-
}}
28-
>
29+
<form action={dispatchAction}>
2930
<div className={styles.header}>続けるにはログインが必要です</div>
3031
<div className={styles.body}>
3132
<input

typing-app/src/components/templates/GamePre.module.scss

Lines changed: 35 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,27 +19,48 @@
1919
height: calc(100% - 150px);
2020
top: 70px;
2121
}
22+
@media (max-width: 1024px) {
23+
width: 90%;
24+
left: 5%;
25+
}
26+
@media (max-height: 800px) {
27+
height: calc(100% - 80px);
28+
top: -10px;
29+
}
2230
}
2331

2432
.header {
25-
margin-top: 40px;
26-
margin-bottom: 20px;
33+
padding-left: 14px;
34+
padding-top: 6px;
35+
position: absolute;
36+
left: 30px;
37+
top: 0;
2738
color: color.$white;
28-
font-size: 40px;
39+
font-size: 48px;
2940
font-weight: bold;
30-
display: flex;
41+
display: block;
3142
justify-content: center;
3243
align-items: center;
3344
flex-shrink: 0;
45+
border-left: solid 20px color.$red-500;
46+
3447
@media (max-width: 768px) {
3548
font-size: 32px;
3649
margin-top: 20px;
3750
margin-bottom: 10px;
3851
}
52+
53+
span {
54+
padding-left: 10px;
55+
font-size: 28px;
56+
color: color.$red-200;
57+
}
3958
}
4059

4160
.main {
61+
margin-top: 100px;
4262
overflow: auto;
63+
overflow-x: hidden;
4364
flex-grow: 1;
4465

4566
.left {
@@ -53,6 +74,10 @@
5374
margin-bottom: 5px;
5475
}
5576

77+
@media (max-height: 800px) {
78+
font-size: 22px;
79+
}
80+
5681
@media (max-width: 768px) {
5782
float: none;
5883
width: 90%;
@@ -76,6 +101,12 @@
76101
height: 300px;
77102
}
78103

104+
@media (max-height: 800px) {
105+
img {
106+
height: 260px;
107+
}
108+
}
109+
79110
@media (max-width: 768px) {
80111
float: none;
81112
width: 90%;

typing-app/src/components/templates/GamePre.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ const GamePre: React.FC<GamePreProps> = ({ nextPage }) => {
2323

2424
return (
2525
<div className={styles["game-pre"]}>
26-
<div className={styles.header}>操作説明</div>
26+
<div className={styles.header}>
27+
操作説明<span>HOW TO PLAY</span>
28+
</div>
2729
<div className={styles.main}>
2830
<div className={styles.left}>
2931
<p>

typing-app/src/components/templates/GameResult.module.scss

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,18 +22,31 @@
2222
top: 70px;
2323
padding: 10px 15px;
2424
}
25+
@media (max-height: 800px) {
26+
height: calc(100% - 80px);
27+
top: -10px;
28+
}
2529

2630
.header {
27-
width: 100%;
28-
padding: 10px 0;
29-
margin-bottom: 20px;
31+
padding-left: 14px;
32+
padding-top: 6px;
33+
position: absolute;
34+
left: 30px;
35+
top: 0;
3036
color: color.$white;
31-
background-color: color.$blue-800;
32-
border-radius: 4px;
33-
font-size: 32px;
37+
font-size: 48px;
3438
font-weight: bold;
35-
text-align: center;
39+
display: block;
40+
justify-content: center;
41+
align-items: center;
3642
flex-shrink: 0;
43+
border-left: solid 20px color.$red-500;
44+
45+
span {
46+
padding-left: 10px;
47+
font-size: 28px;
48+
color: color.$red-200;
49+
}
3750

3851
@media (max-width: 768px) {
3952
font-size: 24px;
@@ -43,13 +56,17 @@
4356
}
4457

4558
.table {
59+
margin-top: 70px;
4660
overflow: auto;
4761
flex-grow: 1;
4862

4963
.row {
5064
width: 50%;
51-
margin: 10px auto;
65+
height: 60px;
66+
margin: 0 auto;
67+
padding-top: 6px;
5268
overflow: hidden;
69+
border-bottom: solid 1px color.$gray-300;
5370

5471
@media (max-width: 768px) {
5572
width: 90%;
@@ -68,12 +85,21 @@
6885
}
6986

7087
.left {
88+
padding-top: 14px;
7189
float: left;
7290
}
7391

7492
.right {
7593
float: right;
7694
text-align: right;
95+
font-size: 42px;
96+
color: color.$blue-200;
97+
98+
span {
99+
padding-left: 6px;
100+
font-size: 28px;
101+
color: color.$white;
102+
}
77103
}
78104
}
79105
}

typing-app/src/components/templates/GameResult.tsx

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,45 @@ const GameResult: React.FC<GameResultProps> = ({ nextPage, score }) => {
1717

1818
return (
1919
<div className={styles.box}>
20-
<div className={styles.header}>Result</div>
20+
<div className={styles.header}>
21+
タイピング結果<span>RESULT</span>
22+
</div>
2123
<div className={styles.table}>
2224
<div className={styles.row}>
2325
<div className={styles.left}>打鍵数</div>
24-
<div className={styles.right}>{score.keystrokes}</div>
26+
<div className={styles.right}>
27+
{score.keystrokes}
28+
<span></span>
29+
</div>
2530
</div>
2631
<div className={styles.row}>
2732
<div className={styles.left}>ミス入力数</div>
28-
<div className={styles.right}>{score.miss}</div>
33+
<div className={styles.right}>
34+
{score.miss}
35+
<span></span>
36+
</div>
2937
</div>
3038
<div className={styles.row}>
3139
<div className={styles.left}>入力時間</div>
32-
<div className={styles.right}>{String(score.time)}</div>
40+
<div className={styles.right}>
41+
{String(score.time)}
42+
<span></span>
43+
</div>
3344
</div>
3445
<div className={styles.row}>
3546
<div className={styles.left}>WPM</div>
36-
<div className={styles.right}>{Math.floor(score.wpm)} 字/分</div>
47+
<div className={styles.right}>
48+
{Math.floor(score.wpm)}
49+
<span>字/分</span>
50+
</div>
3751
</div>
3852
<div className={styles.row}>
3953
<div className={styles.left}>正打率</div>
4054
<div className={styles.right}>
4155
{new Intl.NumberFormat("en-US", {
42-
style: "percent",
4356
maximumFractionDigits: 2,
44-
}).format(score.accuracy)}
57+
}).format(score.accuracy * 100)}
58+
<span>%</span>
4559
</div>
4660
</div>
4761
</div>

0 commit comments

Comments
 (0)