Skip to content

Commit f66cf76

Browse files
記事の分割
記事の検索機能などの実装。
1 parent b85c675 commit f66cf76

File tree

4 files changed

+179
-43
lines changed

4 files changed

+179
-43
lines changed

src/app/article/components/list.tsx

Lines changed: 68 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ export default function ArticleList({ articles }: ArticleListProps) {
1111
const t = useTranslations();
1212
const locale = t("info.lang");
1313
const [searchQuery, setSearchQuery] = useState("");
14+
const [startDate, setStartDate] = useState(""); // 範囲指定の開始日
15+
const [endDate, setEndDate] = useState(""); // 範囲指定の終了日
1416
const [currentPage, setCurrentPage] = useState(1);
1517

1618
const articlesPerPage = 8;
@@ -20,7 +22,14 @@ export default function ArticleList({ articles }: ArticleListProps) {
2022
.filter((a) => a.lang === locale)
2123
.filter((a) =>
2224
a.title.toLowerCase().includes(searchQuery.toLowerCase())
23-
);
25+
)
26+
.filter((a) => {
27+
if (!startDate && !endDate) return true; // 日付範囲が指定されていない場合はすべて通す
28+
const articleDate = new Date(a.date).toISOString().split("T")[0]; // 記事の日付をフォーマット
29+
if (startDate && articleDate < startDate) return false; // 開始日より前は除外
30+
if (endDate && articleDate > endDate) return false; // 終了日より後は除外
31+
return true;
32+
});
2433

2534
// ページネーション用の計算
2635
const totalPages = Math.ceil(filteredArticles.length / articlesPerPage);
@@ -38,34 +47,63 @@ export default function ArticleList({ articles }: ArticleListProps) {
3847
};
3948

4049
return (
41-
<section className="articles">
42-
<input
43-
type="text"
44-
placeholder="Search articles..."
45-
value={searchQuery}
46-
onChange={(e) => setSearchQuery(e.target.value)}
47-
className="search-input"
48-
/>
49-
{currentArticles.map(
50-
(article: Article): ReactNode => generateArticleButton(article)
51-
)}
52-
<div className="pagination">
53-
<button
54-
onClick={() => handlePageChange(currentPage - 1)}
55-
disabled={currentPage === 1}
56-
>
57-
{t("pages.article.words.previous")}
58-
</button>
59-
<span>
60-
Page {currentPage} of {totalPages}
61-
</span>
62-
<button
63-
onClick={() => handlePageChange(currentPage + 1)}
64-
disabled={currentPage === totalPages}
65-
>
66-
{t("pages.article.words.next")}
67-
</button>
68-
</div>
69-
</section>
50+
<>
51+
<section className="search">
52+
<input
53+
type="text"
54+
placeholder={t("pages.article.words.search")}
55+
value={searchQuery}
56+
onChange={(e) => setSearchQuery(e.target.value)}
57+
className="search-input"
58+
/>
59+
<details>
60+
<summary>{t("pages.article.words.advancedSearch")}</summary>
61+
<div className="advanced-search">
62+
<label>
63+
{t("pages.article.words.startDate")}
64+
<input
65+
type="date"
66+
value={startDate}
67+
onChange={(e) => setStartDate(e.target.value)}
68+
className="search-date"
69+
/>
70+
</label>
71+
<label>
72+
{t("pages.article.words.endDate")}
73+
<input
74+
type="date"
75+
value={endDate}
76+
onChange={(e) => setEndDate(e.target.value)}
77+
className="search-date"
78+
/>
79+
</label>
80+
</div>
81+
</details>
82+
</section>
83+
<section className="articles">
84+
{currentArticles.map(
85+
(article: Article): ReactNode => generateArticleButton(article)
86+
)}
87+
</section>
88+
<section className="pager">
89+
<div className="pagination">
90+
<button
91+
onClick={() => handlePageChange(currentPage - 1)}
92+
disabled={currentPage === 1}
93+
>
94+
{t("pages.article.words.previous")}
95+
</button>
96+
<span>
97+
Page {currentPage} of {totalPages}
98+
</span>
99+
<button
100+
onClick={() => handlePageChange(currentPage + 1)}
101+
disabled={currentPage === totalPages}
102+
>
103+
{t("pages.article.words.next")}
104+
</button>
105+
</div>
106+
</section>
107+
</>
70108
);
71109
}

src/app/article/page.css

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/* ページ全体のスタイル */
2+
.page-container {
3+
padding: 2rem;
4+
background-color: var(--background);
5+
color: var(--foreground);
6+
}
7+
8+
/* 検索バーのスタイル */
9+
.search-input {
10+
width: 100%;
11+
padding: 0.5rem;
12+
margin-bottom: 1rem;
13+
border: 1px solid var(--primary);
14+
border-radius: 4px;
15+
background-color: var(--primary);
16+
color: var(--foreground);
17+
font-size: 1rem;
18+
}
19+
20+
.search-input::placeholder {
21+
color: var(--foreground);
22+
opacity: 0.7;
23+
}
24+
25+
.search-date {
26+
width: 100%;
27+
padding: 0.5rem;
28+
margin-bottom: 1rem;
29+
border: 1px solid var(--primary);
30+
border-radius: 4px;
31+
background-color: var(--primary);
32+
color: var(--foreground);
33+
font-size: 1rem;
34+
}
35+
36+
/* 記事リストのスタイル */
37+
.articles {
38+
display: grid;
39+
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
40+
gap: 1rem;
41+
}
42+
43+
/* ページネーションのスタイル */
44+
.pagination {
45+
display: flex;
46+
justify-content: center;
47+
align-items: center;
48+
margin-top: 2rem;
49+
}
50+
51+
.pagination button {
52+
padding: 0.5rem 1rem;
53+
margin: 0 0.5rem;
54+
border: 1px solid var(--primary);
55+
background-color: var(--primary);
56+
color: var(--foreground);
57+
border-radius: 4px;
58+
cursor: pointer;
59+
transition: background-color 0.3s ease, color 0.3s ease;
60+
}
61+
62+
.pagination button:disabled {
63+
background-color: var(--background);
64+
color: var(--foreground);
65+
opacity: 0.5;
66+
cursor: not-allowed;
67+
}
68+
69+
.pagination span {
70+
margin: 0 1rem;
71+
font-size: 1rem;
72+
color: var(--foreground);
73+
}
74+
75+
/* ボタンのホバー効果 */
76+
.pagination button:hover:not(:disabled) {
77+
background-color: var(--link-color);
78+
color: var(--background);
79+
}
80+
81+
/* 高度な検索のスタイル */
82+
.advanced-search {
83+
margin-top: 1rem;
84+
display: flex;
85+
flex-direction: column;
86+
gap: 1rem;
87+
}
88+
89+
.advanced-search label {
90+
display: flex;
91+
flex-direction: column;
92+
font-size: 0.9rem;
93+
color: var(--foreground);
94+
}

src/app/article/page.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import "./article.css"; // CSSファイルをインポート
2+
import "./page.css";
23
import Explains from "./components/explains";
34
import ArticlePage from "./components/articlepage"; // クライアントコンポーネントをインポート
45

56
export default function Home() {
67
return (
78
<>
89
<Explains />
9-
<ArticlePage/>
10+
<ArticlePage />
1011
</>
1112
);
1213
}

src/i18n/ja/common.json

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
{
2-
"info":{
3-
"lang":"ja"
2+
"info": {
3+
"lang": "ja"
44
},
55
"pages": {
66
"home": {
77
"title": "The Infinity's",
88
"description": {
9-
"msg1": "こんにちは私はThe-Infinitysです。",
9+
"msg1": "こんにちは! 私はThe-Infinitysです。",
1010
"msg2": "プログラミングに情熱を注ぎ、GitHubでさまざまなプロジェクトに取り組んでいます。",
1111
"msg3": "私の個人ウェブサイトでは、作品やアイデアを公開しており、訪れる方に私の世界を覗いていただけます。",
1212
"msg4": "また、X(旧Twitter)では、技術的な話題や日常の出来事をシェアしています。",
13-
"msg5": "私の活動に興味を持っていただけたら、ぜひチェックしてみてください",
14-
"msg6": "そして、X (旧Twitter)およびGitHubのフォローをよろしくおねがいします"
13+
"msg5": "私の活動に興味を持っていただけたら、ぜひチェックしてみてください!",
14+
"msg6": "そして、X (旧Twitter)およびGitHubのフォローをよろしくおねがいします!"
1515
}
1616
},
1717
"article": {
@@ -22,15 +22,18 @@
2222
},
2323
"words": {
2424
"search": "検索",
25-
"previous":"前へ",
26-
"next":"次へ"
25+
"advancedSearch": "高度な検索",
26+
"startDate": "開始日",
27+
"endDate": "終了日",
28+
"previous": "前へ",
29+
"next": "次へ"
2730
},
28-
"content":{
29-
"words":{
30-
"index":"目次",
31-
"others":"他の記事"
31+
"content": {
32+
"words": {
33+
"index": "目次",
34+
"others": "他の記事"
3235
}
3336
}
3437
}
3538
}
36-
}
39+
}

0 commit comments

Comments
 (0)