Skip to content

Commit fbf97ab

Browse files
authored
fix(anime): notes showing issue on hover and mobile (#141)
## 🐛 Bug Fix && ✨ Features Updates ### 📌 Description Addressing anime page issue with notes on hover (desktop) and on click (mobile), ### 🔍 Feature Changes - [ ] New component or page - [ ] API update - [ ] UI/UX improvement - [X] Other: Update some CI related files (PR template, releases.yml, added workflow). ### 🛠 Bug Fixes - [X] Fixed issue: #140 - Extract `AnimeCard` and `Notes` components from `AnimeList`. - Handle hover logic differently for desktop. - Add onClick() event to show notes on mobile. - [ ] Improved error handling - [ ] Performance fix - [ ] Other: ... ### ✅ Checklist - [X] Code follows project coding style. - [X] Tested in a Next.js environment. - [ ] Relevant documentation is updated. - [X] Bug has been reproduced and verified. - [X] Fix does not introduce new issues. - [ ] Added necessary tests. ### 📸 Screenshots (if applicable) ![image](https://github.com/user-attachments/assets/8cabd91d-eb47-4a1e-aab5-4fdd13fb7708)
1 parent 0c9c327 commit fbf97ab

File tree

7 files changed

+300
-171
lines changed

7 files changed

+300
-171
lines changed

.github/PULL_REQUEST_TEMPLATE.md

+26-65
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,25 @@
1-
## Feature Request
1+
## Features Updates && 🐛 Bug Fix && 🛠 Code Refactor && 📦 Dependency Update
22

33
### 📌 Description
44

55
<!-- Clearly describe the feature you have added or updated. -->
66
<!-- Explain why this feature is necessary. -->
77

8-
### 🔍 Changes
8+
### 🔍 Feature Changes
99

1010
- [ ] New component or page
1111
- [ ] API update
1212
- [ ] UI/UX improvement
1313
- [ ] Other: ...
1414

15-
### ✅ Checklist
16-
17-
- [ ] Code follows project coding style.
18-
- [ ] Tested in a Next.js environment.
19-
- [ ] Relevant documentation is updated.
20-
21-
### 📸 Screenshots (if applicable)
22-
23-
<!-- Attach screenshots or GIFs here -->
24-
25-
### 💬 Additional Notes
26-
27-
<!-- Add any extra context -->
28-
29-
---
30-
31-
## 🐛 Bug Fix
32-
33-
### 📌 Description
15+
### 🔄 Refactor Changes
3416

35-
<!-- Describe the bug and how you fixed it. -->
36-
<!-- Include related issue references, e.g., "Closes #123". -->
17+
- [ ] Code optimization
18+
- [ ] Improve maintainability
19+
- [ ] Remove unnecessary code
20+
- [ ] Other: ...
3721

38-
### 🛠 Changes
22+
### 🛠 Bug Fixes
3923

4024
- [ ] Fixed issue: ...
4125
- [ ] Improved error handling
@@ -44,54 +28,28 @@
4428

4529
### ✅ Checklist
4630

47-
- [ ] Bug has been reproduced and verified.
48-
- [ ] Fix does not introduce new issues.
49-
- [ ] Added necessary tests.
50-
51-
### 📝 Steps to Reproduce (before fix)
52-
53-
<!-- Provide steps for reproducing the original issue -->
54-
55-
### 📸 Screenshots (if applicable)
56-
57-
<!-- Attach screenshots showing the fix -->
58-
59-
### 💬 Additional Notes
60-
61-
<!-- Add any extra context -->
62-
63-
---
64-
65-
## 🛠 Code Refactor
66-
67-
### 📌 Description
31+
1. Feature Updates:
6832

69-
<!-- Describe the refactor and why it was needed. -->
33+
- [ ] Code follows project coding style.
34+
- [ ] Tested in a Next.js environment.
35+
- [ ] Relevant documentation is updated.
7036

71-
### 🔄 Changes
37+
2. Bug Fixes:
7238

73-
- [ ] Code optimization
74-
- [ ] Improve maintainability
75-
- [ ] Remove unnecessary code
76-
- [ ] Other: ...
39+
- [ ] Bug has been reproduced and verified.
40+
- [ ] Fix does not introduce new issues.
41+
- [ ] Added necessary tests.
7742

78-
### ✅ Checklist
43+
3. Code Refactor:
7944

8045
- [ ] No breaking changes introduced.
8146
- [ ] Performance improvement validated.
8247
- [ ] Documentation updated if necessary.
8348

84-
### 💬 Additional Notes
85-
86-
<!-- Add any extra context -->
87-
88-
---
49+
4. Dependency Updates:
8950

90-
## 📦 Dependency Update
91-
92-
### 📌 Description
93-
94-
<!-- Describe why this dependency update is needed. -->
51+
- [ ] Verified functionality after update.
52+
- [ ] Checked for security vulnerabilities using `npm audit` / `pnpm audit`.
9553

9654
### 📜 Dependency Changes
9755

@@ -101,11 +59,14 @@
10159
| React | 18.3.1 | 19.0.0 | Required for Next.js compatibility |
10260
| Tailwind CSS | 3.4.3 | 4.0.1 | Performance improvements |
10361

104-
### ✅ Checklist
62+
### 📝 Steps to Reproduce (before fix)
10563

106-
- [ ] Verified functionality after update.
107-
- [ ] Checked for security vulnerabilities using `npm audit` / `pnpm audit`.
64+
<!-- Provide steps for reproducing the original issue -->
10865

10966
### 💬 Additional Notes
11067

11168
<!-- Add any extra context -->
69+
70+
### 📸 Screenshots (if applicable)
71+
72+
<!-- Attach screenshots or GIFs here -->

.github/release.yml

+29-11
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,32 @@
11
changelog:
22
exclude:
3-
labels:
4-
- ignore-for-release
3+
labels: [ignore-for-release, wip, dependencies]
4+
authors: ['dependabot[bot]', renovate-bot]
5+
56
categories:
6-
- title: new features 🚀
7-
labels:
8-
- enhancement
9-
- title: bug fixes and improvements ✨
10-
labels:
11-
- bug-fix
12-
- title: other changes 🛠️
13-
labels:
14-
- '*'
7+
- title: 🚀 Features / 新功能
8+
labels: [feature, enhancement]
9+
10+
- title: 🐛 Bug Fixes / 修复
11+
labels: [bug, fix]
12+
13+
- title: 🛠️ Improvements / 改进
14+
labels: [refactor, optimization, performance]
15+
16+
- title: 📦 Dependencies / 依赖更新
17+
labels: [dependencies]
18+
19+
- title: 📖 Documentation / 文档更新
20+
labels: [docs]
21+
22+
- title: 🧰 Internal / 内部变更
23+
labels: [internal, ci, workflow, build]
24+
25+
- title: 💥 Breaking Changes / 破坏性变更
26+
labels: [breaking-change, Semver-Major]
27+
28+
- title: 🎨 UI UX & Styling / UI UX & 样式
29+
labels: [ui, ux, design]
30+
31+
- title: 🔄 Miscellaneous / 其他变更
32+
labels: ['*']

.github/workflows/auto-release.yml

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
name: Auto Release
2+
3+
on:
4+
push:
5+
tags:
6+
- "v*" # Listen to tags like v1.0.0
7+
8+
jobs:
9+
release:
10+
runs-on: ubuntu-latest
11+
12+
steps:
13+
- name: Checkout repository
14+
uses: actions/checkout@v4
15+
16+
- name: Get Previous Tag
17+
id: get_prev_tag
18+
run: echo "LAST_TAG=$(git describe --tags --abbrev=0 --exclude=${{ github.ref_name }})" >> $GITHUB_ENV
19+
20+
- name: Generate GitHub Release
21+
uses: softprops/action-gh-release@v2
22+
with:
23+
tag_name: ${{ github.ref_name }} # Tag Name
24+
name: ${{ github.ref_name }} # Release Name (same as Tag Name)
25+
body: |
26+
📢 **SuzuBlog new version released!** 🚀
27+
新版本发布!请查看自动生成的 Release Notes 🔽
28+
29+
## What's Changed
30+
- Automatically generated Release Notes based on changes in this release.
31+
32+
## Full Changelog
33+
[View Full Changelog](https://github.com/ZL-Asica/SuzuBlog/compare/${{ github.event.before }}...${{ github.ref }})
34+
35+
## Contributors
36+
🏆 Thank you to everyone who contributed to this release!
37+
38+
${{ github.event.release.body }}
39+
draft: false
40+
prerelease: false
41+
generate_release_notes: true

src/app/about/anime/page.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { getConfig } from '@/services/config'
77
import Head from 'next/head'
88
import { notFound } from 'next/navigation'
99

10-
export const revalidate = 3600
10+
export const revalidate = 300 // 5 minutes for whole page
1111

1212
export async function generateMetadata(): Promise<Metadata> {
1313
const config = getConfig()
@@ -48,7 +48,7 @@ export default async function AnimePage() {
4848
: 'http://localhost:3000'
4949

5050
const response = await fetch(`${API_BASE_URL}/api/anime?userName=${anilist_username}`, {
51-
next: { tags: ['anime'], revalidate: 3600 }, // Cache for 1 hour
51+
next: { tags: ['anime'], revalidate: 600 }, // Cache for 10 minutes
5252
})
5353

5454
if (!response.ok) {

src/components/anime/AnimeCard.tsx

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
'use client'
2+
3+
import type { AniListList, AniListListEntry } from '@/schemas/anime'
4+
import { MessageCircle, Star } from 'lucide-react'
5+
import Image from 'next/image'
6+
import { useEffect, useState } from 'react'
7+
import Notes from './Notes'
8+
9+
interface AnimeCardProps {
10+
sortedLists: AniListList[]
11+
lang: string
12+
translation: Translation
13+
}
14+
15+
const AnimeCard = ({ sortedLists, lang, translation }: AnimeCardProps) => {
16+
const [isMobile, setIsMobile] = useState<boolean>(false)
17+
const [showNotes, setShowNotes] = useState<number | null>(null)
18+
19+
useEffect(() => {
20+
// Detect if the device is mobile
21+
const checkMobile = () => {
22+
setIsMobile(window.matchMedia('(hover: none)').matches)
23+
}
24+
25+
checkMobile()
26+
27+
window.addEventListener('resize', checkMobile)
28+
return () => {
29+
window.removeEventListener('resize', checkMobile)
30+
}
31+
}, [])
32+
33+
return (
34+
<>
35+
{sortedLists.map((list: AniListList, index) => (
36+
<div key={list.name} className="mt-10">
37+
<h2 className="text-2xl font-semibold border-b border-gray-700 pb-2">
38+
<a id={list.name} href={`#${list.name}`}>
39+
{`${index + 1}. ${translation.anime.status[list.name.toLowerCase()]}`}
40+
</a>
41+
</h2>
42+
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-6 xl:grid-cols-7 2xl:grid-cols-8 gap-6 mt-4">
43+
{/* Show each anime entry */}
44+
{list.entries
45+
.sort((a, b) =>
46+
(b.score ?? 0) - (a.score ?? 0)
47+
|| (b.progress ?? 0) - (a.progress ?? 0)
48+
|| (b.notes !== null ? 1 : 0) - (a.notes !== null ? 1 : 0),
49+
)
50+
.map((entry: AniListListEntry, entryIndex) => (
51+
<div
52+
key={entry.media.id}
53+
className="relative group bg-gray-800 rounded-lg shadow-md transition-all duration-300 hover:scale-105"
54+
onClick={() => {
55+
if (isMobile) {
56+
setShowNotes(showNotes === entry.media.id ? null : entry.media.id)
57+
}
58+
}}
59+
>
60+
{/* Show note indicator */}
61+
{(entry.notes !== null && entry.notes.trim() !== '') && (
62+
<div
63+
className="absolute top-2 right-2 z-1 flex items-center bg-black/70 px-2 py-1 rounded-lg shadow-md"
64+
>
65+
<MessageCircle className="text-[var(--sakuraPinkDark)] fill-current" size={20} />
66+
</div>
67+
)}
68+
69+
{/* Cover Image (16:9) */}
70+
<div className="relative w-full aspect-[9/16] rounded-lg overflow-hidden">
71+
<Image
72+
src={
73+
entry.media.coverImage.extraLarge
74+
?? entry.media.coverImage.large
75+
?? entry.media.coverImage.medium
76+
?? '/images/image-not-found.webp'
77+
}
78+
alt={lang === 'ja' && entry.media.title.native !== null
79+
? entry.media.title.native
80+
: lang === 'en' && entry.media.title.english !== null
81+
? entry.media.title.english
82+
: entry.media.title.romaji}
83+
fill
84+
className="object-cover"
85+
unoptimized
86+
priority={index === 1 && entryIndex <= 16}
87+
/>
88+
</div>
89+
90+
{/* Title & Progress */}
91+
<div className="absolute bottom-0 left-0 w-full bg-gradient-to-t from-black/90 to-transparent p-2 text-white shadow-lg">
92+
<h3 className="text-lg font-semibold leading-tight">
93+
{lang === 'ja' && entry.media.title.native !== null
94+
? entry.media.title.native
95+
: lang === 'en' && entry.media.title.english !== null
96+
? entry.media.title.english
97+
: entry.media.title.romaji}
98+
</h3>
99+
<p className="text-md font-semibold text-gray-300 mt-1">
100+
{entry.progress ?? 0}
101+
{' '}
102+
/
103+
{entry.media.episodes ?? '?'}
104+
</p>
105+
</div>
106+
107+
{/* Rating */}
108+
<div
109+
className={`absolute bottom-2 right-2 flex items-center bg-black/60 px-2 py-1 rounded-lg ${
110+
entry.score !== null && entry.score !== 0 ? 'text-[var(--sakuraPinkDark)]' : 'text-gray-400'
111+
}`}
112+
>
113+
<p className="text-sm font-medium">{entry.score ?? 'N/A'}</p>
114+
<Star className="ml-1 fill-current" size={20} />
115+
</div>
116+
117+
{/* Hover Note */}
118+
{(entry.notes !== null && entry.notes.trim() !== '')
119+
&& (
120+
<Notes
121+
text={entry.notes}
122+
isMobile={isMobile}
123+
showNotes={showNotes === entry.media.id}
124+
/>
125+
)}
126+
127+
</div>
128+
))}
129+
</div>
130+
</div>
131+
))}
132+
</>
133+
)
134+
}
135+
136+
export default AnimeCard

0 commit comments

Comments
 (0)