-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #88 from PaulKo121/develop
更新css 新增僅供閱讀的用戶資料頁面
- Loading branch information
Showing
10 changed files
with
290 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import React, { useState, useEffect } from 'react'; | ||
import styles from "../styles/components/UserArticles.module.css"; | ||
import articleService from '../services/ArticleService'; | ||
import { useNavigate } from 'react-router-dom'; | ||
|
||
// 用來顯示用戶發表的文章列表 | ||
const UserArticlesReadOnly = ({ authorId }) => { | ||
// 管理文章資料 | ||
const [articles, setArticles] = useState([]); | ||
const [error, setError] = useState(null); // 用來顯示錯誤 | ||
const [loading, setLoading] = useState(true); // 加入 loading 狀態 | ||
const navigate = useNavigate(); | ||
|
||
// 獲取文章資料 | ||
useEffect(() => { | ||
const initialize = async () => { | ||
try { | ||
const userArticles = await articleService.getUserArticleByAuthorId(authorId); | ||
setArticles(userArticles); | ||
// console.log(articles); | ||
} catch (err) { | ||
setError("無法獲取文章資料,請稍後再試。"); | ||
} finally { | ||
setLoading(false); | ||
} | ||
}; | ||
|
||
if (authorId) { | ||
initialize(); | ||
} | ||
}, [authorId]); | ||
|
||
if (loading) { | ||
return <div className="col-12"><p>載入中...</p></div>; | ||
} | ||
|
||
if (error) { | ||
return <div className="col-12"><p>{error}</p></div>; | ||
} | ||
|
||
if (articles.length === 0) { | ||
return <div className="col-12"><p>沒有發表過的文章。</p></div>; | ||
} | ||
|
||
return ( | ||
<div className="col-12"> | ||
<h2 className="mb-4 fw-bold">發表過的文章</h2> | ||
<ul className="list-group"> | ||
{articles.map((article, index) => ( | ||
<li className="list-group-item mb-3 p-3 border rounded shadow-sm" key={index}> | ||
<div className="d-flex flex-column"> | ||
<h4 className="mb-2"> | ||
<a href={`/singleArticle/${article.articleId}`} className="text-decoration-none text-dark fw-bold"> | ||
{article.title} | ||
</a> | ||
</h4> | ||
<p className={`lh-base text-muted mb-2 ${styles.truncate}`}>{article.contentTEXT}</p> | ||
</div> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
); | ||
}; | ||
|
||
export default UserArticlesReadOnly; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
import React, { useState, useEffect, useContext } from 'react'; | ||
import styles from "../styles/components/UserAvatar.module.css"; | ||
import Modal from 'react-modal'; | ||
import ImageUpload from "./ImageUpload"; | ||
import { UserContext } from './UserContext'; | ||
|
||
const UserAvatarReadOnly = ({ id }) => { | ||
|
||
// 用來管理用戶資料 | ||
const [userData, setUserData] = useState({ | ||
username: '', | ||
imagelink: '' | ||
}); | ||
const [loading, setLoading] = useState(false); | ||
const [error, setError] = useState(''); | ||
|
||
// 透過圖片路徑顯示圖片 | ||
// 獲取後端資料 | ||
useEffect(() => { | ||
setLoading(true); | ||
|
||
fetch(`http://localhost:8080/blog/api/userProfile/${id}`) | ||
.then(response => { | ||
// console.log('網頁回應:', response); | ||
return response.json(); | ||
}) | ||
.then(data => { | ||
// console.log("得到的數據", data) | ||
setUserData(data); | ||
|
||
setLoading(false); | ||
}) | ||
.catch(error => { | ||
console.error("獲取用戶資料失敗", error); | ||
setError("獲取用戶資料失敗"); | ||
setLoading(false); | ||
}) | ||
}, [id]); | ||
|
||
return ( | ||
<div className={`${styles.profile_picture_wrapper} text-center`}> | ||
{loading && <p className={styles.p}>載入中...</p>} | ||
{error && <p className={styles.p}>{error}</p>} | ||
<label className={`${styles.avatarName} form_label d_block`}>{userData.username}的頭像</label> | ||
<div className="image-container mb-3"> | ||
<img | ||
id={styles.profile_avatar} | ||
src={userData.imagelink} | ||
alt="頭像" | ||
className="img-fluid rounded border border-3 border-dark" | ||
/> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default UserAvatarReadOnly; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import React, { useState, useEffect, useContext } from 'react'; | ||
import styles from "../styles/components/UserProfile.module.css"; | ||
|
||
// 用來顯示和編輯用戶的基本資料(用戶名、電子郵件、密碼) | ||
const UserProfileReadOnly = ({ userId }) => { | ||
|
||
// 用來管理用戶資料 | ||
const [userData, setUserData] = useState({ | ||
username: '', | ||
email: '', | ||
createdDate: '', | ||
lastLoginDate: '' | ||
}); | ||
|
||
// 變換時間格式 | ||
const formattedDate1 = new Date(userData.createdDate).toLocaleString('zh-TW', { | ||
year: 'numeric', | ||
month: '2-digit', | ||
day: '2-digit', | ||
hour: '2-digit', | ||
minute: '2-digit', | ||
second: '2-digit' | ||
}); | ||
|
||
const formattedDate2 = new Date(userData.lastLoginDate).toLocaleString('zh-TW', { | ||
year: 'numeric', | ||
month: '2-digit', | ||
day: '2-digit', | ||
hour: '2-digit', | ||
minute: '2-digit', | ||
second: '2-digit' | ||
}); | ||
|
||
// 防止用戶在請求未完成時重複提交 | ||
const [loading, setLoading] = useState(false); | ||
const [error, setError] = useState(''); | ||
|
||
// 獲取後端資料 | ||
useEffect(() => { | ||
|
||
setLoading(true); | ||
|
||
fetch(`http://localhost:8080/blog/api/userProfile/${userId}`) | ||
.then(response => response.json()) | ||
.then(data => { | ||
setUserData(data); | ||
console.log(data); | ||
setLoading(false); | ||
}) | ||
.catch(error => { | ||
console.error("獲取用戶資料失敗", error); | ||
setError("獲取用戶資料失敗"); | ||
setLoading(false); | ||
}); | ||
}, [userId]); | ||
|
||
return ( | ||
<div className="row"> | ||
{loading && <p>載入中...</p>} | ||
{error && <p className="text-danger">{error}</p>} | ||
|
||
<div className="col-12 mb-1"> | ||
<label htmlFor="username" className={`form-label fw-bold ${styles.label}`}>用戶名:</label> | ||
<div className="d-flex"> | ||
<p className={`fw-bold ${styles.time}`}>{userData.username}</p> | ||
</div> | ||
</div> | ||
|
||
<div className="col-12 mb-3"> | ||
<label htmlFor="email" className={`form-label fw-bold ${styles.label}`}>電子郵件:</label> | ||
<div className="d-flex"> | ||
<p className={`fw-bold ${styles.time}`}>{userData.email}</p> | ||
</div> | ||
</div> | ||
|
||
<div className="col-12 mb-3"> | ||
<label htmlFor="registrationDate" className={`form-label fw-bold ${styles.label}`}>用戶註冊日期:</label> | ||
<p className={`fw-bold ${styles.time}`}>{formattedDate1}</p> | ||
</div> | ||
|
||
<div className="col-12"> | ||
<label htmlFor="lastLogin" className={`form-label fw-bold ${styles.label}`}>最後上線時間:</label> | ||
<p className={`fw-bold ${styles.time}`}>{formattedDate2}</p> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default UserProfileReadOnly; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React, { useState, useEffect } from "react"; | ||
import UserProfileReadOnly from "../components/UserProfileReadOnly"; | ||
import UserAvatarReadOnly from "../components/UserAvatarReadOnly"; | ||
import UserArticlesReadOnly from "../components/UserArticlesReadOnly"; | ||
import { useParams } from 'react-router-dom'; | ||
import styles from "../styles/pages/UserData.module.css" | ||
import { UserContext } from '../components/UserContext'; | ||
|
||
|
||
const UserDataReadOnly = () => { | ||
|
||
const { userId } = useParams(); // 從路由參數中獲取 userId | ||
|
||
return ( | ||
<div className="container mt-2"> | ||
<h1 className="text-center mb-4">Account Name 的小窩</h1> | ||
<div className="card mx-auto" style={{ maxWidth: '70%' }}> | ||
<div className="card-body p-1"> | ||
<main className="mt-4"> | ||
<div className="row"> | ||
<div className="col-md-6 mb-3"> | ||
<UserProfileReadOnly userId={userId} /> | ||
</div> | ||
<div className="col-md-6 mb-3 d-flex justify-content-center align-items-center"> | ||
<UserAvatarReadOnly id={userId} /> | ||
</div> | ||
</div> | ||
<div className="row"> | ||
<div className="col-12"> | ||
<UserArticlesReadOnly authorId={userId} /> | ||
</div> | ||
</div> | ||
</main> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
export default UserDataReadOnly; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.