KIM-JINO5 2 месяцев назад
Родитель
Сommit
1b62cdb9a9

+ 59 - 57
app/(account)/exp-logs/page.tsx

@@ -3,7 +3,7 @@
 import './style.scss';
 import { useState, useEffect } from 'react';
 import { LoginLogType } from '@/constants/common';
-import { fetchApi, throwError, formatDate } from '@/lib/utils/client';
+import { fetchApi, throwError, getDateTime } from '@/lib/utils/client';
 import type { ExpLogsResponse } from '@/types/response/account/expLogs';
 import Loading from '@/app/component/Loading';
 import Pagination from '@/app/component/Pagination';
@@ -59,67 +59,69 @@ export default function ExpLogs()
 			{ loading && <Loading /> }
 
 			<h1>경험치 내역</h1>
-			<table className="table-auto max-2xl:w-full 2xl:w-[1000px]">
-				<caption>
-					<div className="grid grid-cols-[auto,1fr] gap-4 items-center">
-						<div>
-							합계: {data.total}
-						</div>
-						<div id="expTypeTab" className="justify-self-end">
-							{tabItems.map((item, i) => (
-								<button type="button" key={i} className={`flex-1 py-2 px-4 text-center text-sm font-medium
-									${type === item.value ? "border-b-2 border-blue-500 text-blue-500" : "text-gray-500"}
-								`} onClick={() => setType(item.value)}>{item.label}
-								</button>
-							))}
-						</div>
-					</div>
-				</caption>
-				<colgroup>
-					<col width="20%"/>
-					<col />
-					<col width="15%"/>
-					<col width="15%"/>
-				</colgroup>
-				<thead>
-					<tr>
-						<th>일시</th>
-						<th>사유</th>
-						<th>변동</th>
-						<th>잔액</th>
-					</tr>
-				</thead>
-				<tbody>
+			<div className="list-header">
+				<div className="summary">합계: {data.total}</div>
+				<div id="expTypeTab">
+					{tabItems.map((item, i) => (
+						<button type="button" key={i} className={type === item.value ? 'active' : ''}
+							onClick={() => setType(item.value)}>{item.label}
+						</button>
+					))}
+				</div>
+			</div>
+
+			<section className="mypage-list">
+				<article>
+					<ul>
+						<li>일시</li>
+						<li>사유</li>
+						<li>변동</li>
+						<li>잔액</li>
+					</ul>
+				</article>
+				<article>
 					{data.list.length > 0 ? (
 						data.list.map((row) => (
-							<tr key={row.id} className="hover:bg-gray-100">
-								<td>{formatDate(row.createdAt)}</td>
-								<td>{row.reason}</td>
-								<td className={`font-semibold ${row.amount > 0 ? "text-green-500" : "text-red-500"}`}>
-									{row.amount > 0 ? `+${row.amount}` : row.amount}
-								</td>
-								<td>{row.balance.toLocaleString()}</td>
-							</tr>
+							<section key={row.id}>
+								{/* PC */}
+								<ol>
+									<li>{getDateTime(row.createdAt)}</li>
+									<li className="reason">{row.reason}</li>
+									<li>
+										<span className={row.amount > 0 ? 'amount-plus' : 'amount-minus'}>
+											{row.amount > 0 ? `+${row.amount}` : row.amount}
+										</span>
+									</li>
+									<li>{row.balance.toLocaleString()}</li>
+								</ol>
+
+								{/* Mobile */}
+								<dl hidden>
+									<dt>{row.reason}</dt>
+									<dd>
+										<ul>
+											<li>
+												<span className={row.amount > 0 ? 'amount-plus' : 'amount-minus'}>
+													{row.amount > 0 ? `+${row.amount}` : row.amount}
+												</span>
+											</li>
+											<li>잔액 {row.balance.toLocaleString()}</li>
+											<li>{getDateTime(row.createdAt)}</li>
+										</ul>
+									</dd>
+								</dl>
+							</section>
 						))
 					) : (
-						<tr>
-							<td colSpan={4} className="border p-2 text-center text-gray-500">
-								기록이 없습니다.
-							</td>
-						</tr>
+						<p className="empty">기록이 없습니다.</p>
 					)}
-				</tbody>
-				{data.list.length > 0 && (
-				<tfoot>
-					<tr>
-						<td colSpan={4}>
-							<Pagination total={data.total} page={page} perPage={20} onChange={setPage} />
-						</td>
-					</tr>
-				</tfoot>
-				)}
-			</table>
+				</article>
+			</section>
+
+			{data.list.length > 0 && (
+				<Pagination total={data.total} page={page} perPage={20} onChange={setPage} />
+			)}
 		</div>
 		</>
 	);
-}
+}

+ 141 - 41
app/(account)/exp-logs/style.scss

@@ -6,64 +6,164 @@
 		margin-bottom: 10px;
 	}
 
-	table {
-		border: 1px solid #ccc;
+	.list-header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-bottom: 10px;
+		flex-wrap: wrap;
+		gap: 0.5rem;
 
-		caption {
-			text-align: left;
+		.summary {
 			font-size: 16px;
-			margin-bottom: 10px;
-
-			#expTypeTab {
-				button {
-					&:hover {
-						color: #e47911;
-						font-weight: bold;
-						border-bottom: 2px solid #e47911;
-					}
-				}
-			}
 		}
+	}
 
-		tr {
-			th, td {
-				font-size: 14px;
-				text-align: center;
-				border: 1px solid #ccc;
-				padding: 6px 13px;
+	#expTypeTab {
+		display: flex;
+
+		button {
+			padding: 0.5rem 1rem;
+			font-size: 0.875rem;
+			color: #666;
+			border-bottom: 2px solid transparent;
+			transition: color 0.2s, border-color 0.2s;
+
+			&:hover {
+				color: #e47911;
+				border-bottom-color: #e47911;
 			}
-		}
 
-		thead {
-			tr {
-				th {
-					background: #f9f9f9;
-					font-weight: bold;
-				}
+			&.active {
+				color: #0060a9;
+				font-weight: 600;
+				border-bottom-color: #0060a9;
 			}
 		}
+	}
+
+	.mypage-list {
+		border-top: 1px solid #eaeaea;
+		margin: 0.75rem 0;
+
+		article:nth-of-type(1) {
+			background-color: #f9fafb;
+			border-bottom: 1px solid #eaeaea;
+			padding: 0.5rem 0;
 
-		tbody {
-			tr {
-				td {
-					font-weight: normal;
+			ul {
+				display: grid;
+				grid-template-columns:
+					clamp(100px, 18%, 160px)
+					1fr
+					clamp(60px, 12%, 100px)
+					clamp(60px, 12%, 100px);
+				column-gap: 0.75rem;
+
+				li {
+					text-align: center;
+					font-size: 0.875rem;
+					color: #666;
 				}
 			}
+
+			@media (max-width: 1024px) {
+				display: none;
+			}
 		}
 
-		tfoot {
-			background: #fbfbfb;
+		article:nth-of-type(2) {
+			box-sizing: border-box;
 
-			tr {
-				td {
-					text-align: center;
-					padding: 8px;
+			section {
+				padding: 0.5rem 0;
+				box-sizing: inherit;
+				border-bottom: 1px solid #eaeaea;
+
+				&:hover {
+					background-color: #faffd1;
+				}
 
-					button, a {
-						padding: 6px 20px;
+				// PC
+				ol {
+					display: grid;
+					grid-template-columns:
+						clamp(100px, 18%, 160px)
+						1fr
+						clamp(60px, 12%, 100px)
+						clamp(60px, 12%, 100px);
+					column-gap: 0.75rem;
+					align-items: center;
+
+					li {
+						text-align: center;
+						font-size: 0.875rem;
+
+						&.reason {
+							text-align: left;
+							min-width: 0;
+							overflow: hidden;
+							text-overflow: ellipsis;
+							white-space: nowrap;
+						}
+					}
+				}
+
+				// Mobile
+				dl {
+					dt {
+						font-size: 1rem;
+						word-break: keep-all;
+						overflow-wrap: break-word;
+					}
+
+					dd {
+						ul {
+							display: flex;
+							flex-direction: row;
+							flex-wrap: nowrap;
+							justify-content: start;
+							padding-top: 0.4rem;
+							column-gap: 1rem;
+
+							li {
+								font-size: 0.813rem;
+								color: #888;
+
+								&:last-child {
+									flex-grow: 1;
+									text-align: right;
+								}
+							}
+						}
+					}
+				}
+
+				@media (max-width: 1024px) {
+					ol {
+						display: none;
+					}
+					dl {
+						display: block;
 					}
 				}
 			}
+
+			> .empty {
+				text-align: center;
+				padding: 2.5rem;
+				color: #999;
+			}
+		}
+
+		.amount-plus {
+			font-weight: 600;
+			color: #15803d;
+		}
+
+		.amount-minus {
+			font-weight: 600;
+			color: #dc2626;
 		}
 	}
-}
+}

+ 66 - 68
app/(account)/login-log/page.tsx

@@ -3,8 +3,7 @@
 import './style.scss';
 import { useState, useEffect } from 'react';
 import { LoginLogType } from '@/constants/common';
-import { fetchApi, throwError } from '@/lib/utils/client';
-import type { LoginLog } from '@/types/account/loginLog';
+import { fetchApi, throwError, getDateTime } from '@/lib/utils/client';
 import { LoginLogsResponse } from '@/types/response/account/loginLogs';
 import Loading from '@/app/component/Loading';
 import Pagination from '@/app/component/Pagination';
@@ -56,76 +55,75 @@ export default function LoginLog()
 		<>
 		<NavTabs />
 
-		<div id="loginLog" >
+		<div id="loginLog">
 			{ loading && <Loading /> }
 
 			<h1>로그인 기록</h1>
-			<table className="table-auto max-2xl:w-full 2xl:w-[1000px]">
-				<caption>
-					<div className="grid grid-cols-[auto,1fr] gap-4 items-center">
-						<div>
-							합계: {logs.total}
-						</div>
-						<div id="loginTypeTab" className="justify-self-end">
-							{tabItems.map((item, i) => (
-								<button type="button" key={i} className={`flex-1 py-2 px-4 text-center text-sm font-medium
-									${type === item.value ? "border-b-2 border-blue-500 text-blue-500" : "text-gray-500"}
-								`} onClick={() => setType(item.value)}>{item.label}
-								</button>
-							))}
-						</div>
-					</div>
-				</caption>
-				<colgroup>
-					<col width="20%"/>
-					<col />
-					<col />
-					<col />
-					<col width="15%"/>
-				</colgroup>
-				<thead>
-					<tr>
-						<th>일시</th>
-						<th>접속 IP</th>
-						<th>접속 기기</th>
-						<th>브라우저</th>
-						<th>결과</th>
-					</tr>
-				</thead>
-				<tbody>
+			<div className="list-header">
+				<div className="summary">합계: {logs.total}</div>
+				<div id="loginTypeTab">
+					{tabItems.map((item, i) => (
+						<button type="button" key={i} className={type === item.value ? 'active' : ''}
+							onClick={() => setType(item.value)}>{item.label}
+						</button>
+					))}
+				</div>
+			</div>
+
+			<section className="mypage-list">
+				<article>
+					<ul>
+						<li>일시</li>
+						<li>접속 IP</li>
+						<li>접속 기기</li>
+						<li>브라우저</li>
+						<li>결과</li>
+					</ul>
+				</article>
+				<article>
 					{logs.list.length > 0 ? (
-						logs.list.map((row) => {
-							return (
-								<tr key={row.id} className="hover:bg-gray-100">
-									<td>{row.createdAt}</td>
-									<td>{row.ipAddress}</td>
-									<td>{row.ipAddress}</td>
-									<td>{row.userAgent}</td>
-									<td className={`border p-2 font-semibold ${row.success ? "text-green-500" : "text-red-500"}`}>
-										{row.success ? "성공" : "실패"}
-									</td>
-								</tr>
-							);
-						})
-						) : (
-							<tr>
-								<td colSpan={5} className="border p-2 text-center text-gray-500">
-									기록이 없습니다.
-								</td>
-							</tr>
-						)}
-				</tbody>
-				{logs.list.length > 0 && (
-				<tfoot>
-					<tr>
-						<td colSpan={5}>
-							<Pagination total={logs.total} page={page} perPage={20} onChange={setPage} />
-						</td>
-					</tr>
-				</tfoot>
-				)}
-			</table>
+						logs.list.map((row) => (
+							<section key={row.id}>
+								{/* PC */}
+								<ol>
+									<li>{getDateTime(row.createdAt)}</li>
+									<li>{row.ipAddress}</li>
+									<li>{row.ipAddress}</li>
+									<li className="ua">{row.userAgent}</li>
+									<li>
+										<span className={row.success ? 'badge-success' : 'badge-fail'}>
+											{row.success ? '성공' : '실패'}
+										</span>
+									</li>
+								</ol>
+
+								{/* Mobile */}
+								<dl hidden>
+									<dt>
+										{getDateTime(row.createdAt)}
+										<span className={row.success ? 'badge-success' : 'badge-fail'}>
+											{row.success ? '성공' : '실패'}
+										</span>
+									</dt>
+									<dd>
+										<ul>
+											<li>{row.ipAddress}</li>
+											<li className="ua">{row.userAgent}</li>
+										</ul>
+									</dd>
+								</dl>
+							</section>
+						))
+					) : (
+						<p className="empty">기록이 없습니다.</p>
+					)}
+				</article>
+			</section>
+
+			{logs.list.length > 0 && (
+				<Pagination total={logs.total} page={page} perPage={20} onChange={setPage} />
+			)}
 		</div>
 		</>
 	);
-}
+}

+ 155 - 41
app/(account)/login-log/style.scss

@@ -6,64 +6,178 @@
 		margin-bottom: 10px;
 	}
 
-	table {
-		border: 1px solid #ccc;
+	.list-header {
+		display: flex;
+		justify-content: space-between;
+		align-items: center;
+		margin-bottom: 10px;
+		flex-wrap: wrap;
+		gap: 0.5rem;
 
-		caption {
-			text-align: left;
+		.summary {
 			font-size: 16px;
-			margin-bottom: 10px;
-
-			#loginTypeTab {
-				button {
-					&:hover {
-						color: #e47911;
-						font-weight: bold;
-						border-bottom: 2px solid #e47911;
-					}
-				}
-			}
 		}
+	}
 
-		tr {
-			th, td {
-				font-size: 14px;
-				text-align: center;
-				border: 1px solid #ccc;
-				padding: 6px 13px;
+	#loginTypeTab {
+		display: flex;
+
+		button {
+			padding: 0.5rem 1rem;
+			font-size: 0.875rem;
+			color: #666;
+			border-bottom: 2px solid transparent;
+			transition: color 0.2s, border-color 0.2s;
+
+			&:hover {
+				color: #e47911;
+				border-bottom-color: #e47911;
 			}
-		}
 
-		thead {
-			tr {
-				th {
-					background: #f9f9f9;
-					font-weight: bold;
-				}
+			&.active {
+				color: #0060a9;
+				font-weight: 600;
+				border-bottom-color: #0060a9;
 			}
 		}
+	}
+
+	.mypage-list {
+		border-top: 1px solid #eaeaea;
+		margin: 0.75rem 0;
+
+		article:nth-of-type(1) {
+			background-color: #f9fafb;
+			border-bottom: 1px solid #eaeaea;
+			padding: 0.5rem 0;
 
-		tbody {
-			tr {
-				td {
-					font-weight: normal;
+			ul {
+				display: grid;
+				grid-template-columns:
+					clamp(100px, 18%, 160px)
+					1fr
+					1fr
+					1fr
+					clamp(50px, 10%, 80px);
+				column-gap: 0.75rem;
+
+				li {
+					text-align: center;
+					font-size: 0.875rem;
+					color: #666;
 				}
 			}
+
+			@media (max-width: 1024px) {
+				display: none;
+			}
 		}
 
-		tfoot {
-			background: #fbfbfb;
+		article:nth-of-type(2) {
+			box-sizing: border-box;
 
-			tr {
-				td {
-					text-align: center;
-					padding: 8px;
+			section {
+				padding: 0.5rem 0;
+				box-sizing: inherit;
+				border-bottom: 1px solid #eaeaea;
+
+				&:hover {
+					background-color: #faffd1;
+				}
 
-					button, a {
-						padding: 6px 20px;
+				// PC
+				ol {
+					display: grid;
+					grid-template-columns:
+						clamp(100px, 18%, 160px)
+						1fr
+						1fr
+						1fr
+						clamp(50px, 10%, 80px);
+					column-gap: 0.75rem;
+					align-items: center;
+
+					li {
+						text-align: center;
+						font-size: 0.875rem;
+
+						&.ua {
+							overflow: hidden;
+							text-overflow: ellipsis;
+							white-space: nowrap;
+						}
+					}
+				}
+
+				// Mobile
+				dl {
+					dt {
+						font-size: 1rem;
+						display: flex;
+						align-items: center;
+						gap: 0.5rem;
+					}
+
+					dd {
+						ul {
+							display: flex;
+							flex-direction: row;
+							flex-wrap: nowrap;
+							justify-content: start;
+							padding-top: 0.4rem;
+							column-gap: 1rem;
+
+							li {
+								font-size: 0.813rem;
+								color: #888;
+
+								&.ua {
+									overflow: hidden;
+									text-overflow: ellipsis;
+									white-space: nowrap;
+									flex: 1;
+									min-width: 0;
+								}
+							}
+						}
+					}
+				}
+
+				@media (max-width: 1024px) {
+					ol {
+						display: none;
+					}
+					dl {
+						display: block;
 					}
 				}
 			}
+
+			> .empty {
+				text-align: center;
+				padding: 2.5rem;
+				color: #999;
+			}
+		}
+
+		.badge-success {
+			display: inline-block;
+			padding: 0.125rem 0.5rem;
+			border-radius: 0.25rem;
+			font-size: 0.75rem;
+			font-weight: 600;
+			color: #15803d;
+			background-color: #dcfce7;
+		}
+
+		.badge-fail {
+			display: inline-block;
+			padding: 0.125rem 0.5rem;
+			border-radius: 0.25rem;
+			font-size: 0.75rem;
+			font-weight: 600;
+			color: #dc2626;
+			background-color: #fee2e2;
 		}
 	}
-}
+}

+ 56 - 53
app/(account)/my-comments/page.tsx

@@ -3,11 +3,13 @@
 import './style.scss';
 import { useState, useEffect } from 'react';
 import Link from 'next/link';
-import { fetchApi, throwError, formatDate } from '@/lib/utils/client';
+import { fetchApi, throwError, getDateTime } from '@/lib/utils/client';
 import type { MyCommentsResponse } from '@/types/response/account/myComments';
 import Loading from '@/app/component/Loading';
 import Pagination from '@/app/component/Pagination';
 import NavTabs from '../navTabs';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faThumbsUp } from '@fortawesome/free-regular-svg-icons';
 
 export default function MyComments()
 {
@@ -46,63 +48,64 @@ export default function MyComments()
 			{ loading && <Loading /> }
 
 			<h1>작성 댓글</h1>
-			<table className="table-auto max-2xl:w-full 2xl:w-[1000px]">
-				<caption>
-					<div>
-						합계: {data.total}
-					</div>
-				</caption>
-				<colgroup>
-					<col width="8%"/>
-					<col width="12%"/>
-					<col width="20%"/>
-					<col />
-					<col width="10%"/>
-					<col width="15%"/>
-				</colgroup>
-				<thead>
-					<tr>
-						<th>번호</th>
-						<th>게시판</th>
-						<th>게시글</th>
-						<th>댓글 내용</th>
-						<th>추천</th>
-						<th>작성일</th>
-					</tr>
-				</thead>
-				<tbody>
+			<div className="summary">합계: {data.total}</div>
+
+			<section className="mypage-list">
+				<article>
+					<ul>
+						<li>번호</li>
+						<li>게시판</li>
+						<li>게시글</li>
+						<li>댓글 내용</li>
+						<li>추천</li>
+						<li>작성일</li>
+					</ul>
+				</article>
+				<article>
 					{data.list.length > 0 ? (
 						data.list.map((row) => (
-							<tr key={row.id} className="hover:bg-gray-100">
-								<td>{row.num}</td>
-								<td>{row.boardName}</td>
-								<td className="text-left">
-									<Link href={`/post/${row.postID}`}>{row.postSubject}</Link>
-								</td>
-								<td className="text-left">{row.content}</td>
-								<td>{row.likes}</td>
-								<td>{formatDate(row.createdAt)}</td>
-							</tr>
+							<section key={row.id}>
+								{/* PC */}
+								<ol>
+									<li>{row.num}</li>
+									<li>{row.boardName}</li>
+									<li>
+										<Link href={`/post/${row.postID}`}>
+											<em>{row.postSubject}</em>
+										</Link>
+									</li>
+									<li className="comment-content">{row.content}</li>
+									<li>{row.likes}</li>
+									<li>{getDateTime(row.createdAt)}</li>
+								</ol>
+
+								{/* Mobile */}
+								<dl hidden>
+									<dt>{row.content}</dt>
+									<dd>
+										<ul>
+											<li>
+												<Link href={`/post/${row.postID}`}>
+													[{row.boardName}] {row.postSubject}
+												</Link>
+											</li>
+											<li><FontAwesomeIcon icon={faThumbsUp} /> {row.likes}</li>
+											<li>{getDateTime(row.createdAt)}</li>
+										</ul>
+									</dd>
+								</dl>
+							</section>
 						))
 					) : (
-						<tr>
-							<td colSpan={6} className="border p-2 text-center text-gray-500">
-								작성한 댓글이 없습니다.
-							</td>
-						</tr>
+						<p className="empty">작성한 댓글이 없습니다.</p>
 					)}
-				</tbody>
-				{data.list.length > 0 && (
-				<tfoot>
-					<tr>
-						<td colSpan={6}>
-							<Pagination total={data.total} page={page} perPage={20} onChange={setPage} />
-						</td>
-					</tr>
-				</tfoot>
-				)}
-			</table>
+				</article>
+			</section>
+
+			{data.list.length > 0 && (
+				<Pagination total={data.total} page={page} perPage={20} onChange={setPage} />
+			)}
 		</div>
 		</>
 	);
-}
+}

+ 141 - 35
app/(account)/my-comments/style.scss

@@ -6,54 +6,160 @@
 		margin-bottom: 10px;
 	}
 
-	table {
-		border: 1px solid #ccc;
+	.summary {
+		font-size: 16px;
+		margin-bottom: 10px;
+	}
 
-		caption {
-			text-align: left;
-			font-size: 16px;
-			margin-bottom: 10px;
-		}
+	.mypage-list {
+		border-top: 1px solid #eaeaea;
+		margin: 0.75rem 0;
 
-		tr {
-			th, td {
-				font-size: 14px;
-				text-align: center;
-				border: 1px solid #ccc;
-				padding: 6px 13px;
-			}
-		}
+		article:nth-of-type(1) {
+			background-color: #f9fafb;
+			border-bottom: 1px solid #eaeaea;
+			padding: 0.5rem 0;
+
+			ul {
+				display: grid;
+				grid-template-columns:
+					clamp(40px, 5%, 60px)
+					clamp(60px, 10%, 120px)
+					clamp(100px, 18%, 200px)
+					1fr
+					clamp(40px, 7%, 70px)
+					clamp(70px, 12%, 110px);
+				column-gap: 0.75rem;
 
-		thead {
-			tr {
-				th {
-					background: #f9f9f9;
-					font-weight: bold;
+				li {
+					text-align: center;
+					font-size: 0.875rem;
+					color: #666;
 				}
 			}
-		}
 
-		tbody {
-			tr {
-				td {
-					font-weight: normal;
-				}
+			@media (max-width: 1024px) {
+				display: none;
 			}
 		}
 
-		tfoot {
-			background: #fbfbfb;
+		article:nth-of-type(2) {
+			box-sizing: border-box;
 
-			tr {
-				td {
-					text-align: center;
-					padding: 8px;
+			section {
+				padding: 0.5rem 0;
+				box-sizing: inherit;
+				border-bottom: 1px solid #eaeaea;
+
+				&:hover {
+					background-color: #faffd1;
+				}
+
+				// PC
+				ol {
+					display: grid;
+					grid-template-columns:
+						clamp(40px, 5%, 60px)
+						clamp(60px, 10%, 120px)
+						clamp(100px, 18%, 200px)
+						1fr
+						clamp(40px, 7%, 70px)
+						clamp(70px, 12%, 110px);
+					column-gap: 0.75rem;
+					align-items: center;
+
+					li {
+						text-align: center;
+						font-size: 0.875rem;
 
-					button, a {
-						padding: 6px 20px;
+						&:nth-child(3) {
+							min-width: 0;
+							text-align: left;
+							word-break: keep-all;
+							overflow-wrap: break-word;
+						}
+
+						&.comment-content {
+							min-width: 0;
+							text-align: left;
+							overflow: hidden;
+							text-overflow: ellipsis;
+							white-space: nowrap;
+						}
 					}
 				}
+
+				// Mobile
+				dl {
+					dt {
+						font-size: 1.063rem;
+						word-break: keep-all;
+						overflow-wrap: break-word;
+						display: -webkit-box;
+						-webkit-line-clamp: 2;
+						-webkit-box-orient: vertical;
+						overflow: hidden;
+					}
+
+					dd {
+						ul {
+							display: flex;
+							flex-direction: row;
+							flex-wrap: nowrap;
+							justify-content: start;
+							padding-top: 0.4rem;
+							column-gap: 1rem;
+
+							li {
+								font-size: 0.813rem;
+								color: #888;
+
+								&:first-child {
+									min-width: 0;
+									overflow: hidden;
+									text-overflow: ellipsis;
+									white-space: nowrap;
+								}
+
+								&:last-child {
+									flex-shrink: 0;
+									text-align: right;
+								}
+							}
+						}
+					}
+				}
+
+				a {
+					color: #0060a9;
+					text-decoration: none;
+
+					&:hover {
+						text-decoration: underline;
+						color: #c7511f;
+					}
+
+					> em {
+						display: inherit;
+						font-style: normal;
+					}
+				}
+
+				@media (max-width: 1024px) {
+					ol {
+						display: none;
+					}
+					dl {
+						display: block;
+					}
+				}
+			}
+
+			> .empty {
+				text-align: center;
+				padding: 2.5rem;
+				color: #999;
 			}
 		}
 	}
-}
+}

+ 70 - 56
app/(account)/my-posts/page.tsx

@@ -3,11 +3,14 @@
 import './style.scss';
 import { useState, useEffect } from 'react';
 import Link from 'next/link';
-import { fetchApi, throwError, formatDate } from '@/lib/utils/client';
+import { fetchApi, throwError, getDateTime } from '@/lib/utils/client';
 import type { MyPostsResponse } from '@/types/response/account/myPosts';
 import Loading from '@/app/component/Loading';
 import Pagination from '@/app/component/Pagination';
 import NavTabs from '../navTabs';
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
+import { faThumbsUp, faEye } from '@fortawesome/free-regular-svg-icons';
+import { faLock, faReply, faFloppyDisk, faImage, faVideo } from '@fortawesome/free-solid-svg-icons';
 
 export default function MyPosts()
 {
@@ -46,66 +49,77 @@ export default function MyPosts()
 			{ loading && <Loading /> }
 
 			<h1>작성 게시글</h1>
-			<table className="table-auto max-2xl:w-full 2xl:w-[1000px]">
-				<caption>
-					<div>
-						합계: {data.total}
-					</div>
-				</caption>
-				<colgroup>
-					<col width="8%"/>
-					<col width="12%"/>
-					<col />
-					<col width="10%"/>
-					<col width="10%"/>
-					<col width="10%"/>
-					<col width="15%"/>
-				</colgroup>
-				<thead>
-					<tr>
-						<th>번호</th>
-						<th>게시판</th>
-						<th>제목</th>
-						<th>조회</th>
-						<th>추천</th>
-						<th>댓글</th>
-						<th>작성일</th>
-					</tr>
-				</thead>
-				<tbody>
+			<div className="summary">합계: {data.total}</div>
+
+			<section className="mypage-list">
+				<article>
+					<ul>
+						<li>번호</li>
+						<li>게시판</li>
+						<li>제목</li>
+						<li>조회</li>
+						<li>추천</li>
+						<li>댓글</li>
+						<li>작성일</li>
+					</ul>
+				</article>
+				<article>
 					{data.list.length > 0 ? (
 						data.list.map((row) => (
-							<tr key={row.id} className="hover:bg-gray-100">
-								<td>{row.num}</td>
-								<td>{row.boardName}</td>
-								<td className="text-left">
-									<Link href={`/post/${row.id}`}>{row.subject}</Link>
-								</td>
-								<td>{row.views}</td>
-								<td>{row.likes}</td>
-								<td>{row.comments}</td>
-								<td>{formatDate(row.createdAt)}</td>
-							</tr>
+							<section key={row.id}>
+								{/* PC */}
+								<ol>
+									<li>{row.num}</li>
+									<li>{row.boardName}</li>
+									<li>
+										{row.isSecret && <FontAwesomeIcon icon={faLock} />}
+										{row.isReply && <FontAwesomeIcon icon={faReply} />}
+										<Link href={`/post/${row.id}`}>
+											<em>{row.subject} {row.comments > 0 && <span>[{row.comments}]</span>}</em>
+											{row.files > 0 && <FontAwesomeIcon icon={faFloppyDisk} />}
+											{row.images > 0 && <FontAwesomeIcon icon={faImage} />}
+											{row.medias > 0 && <FontAwesomeIcon icon={faVideo} />}
+										</Link>
+									</li>
+									<li>{row.views}</li>
+									<li>{row.likes}</li>
+									<li>{row.comments}</li>
+									<li>{getDateTime(row.createdAt)}</li>
+								</ol>
+
+								{/* Mobile */}
+								<dl hidden>
+									<dt>
+										{row.isSecret && <FontAwesomeIcon icon={faLock} />}
+										{row.isReply && <FontAwesomeIcon icon={faReply} />}
+										<Link href={`/post/${row.id}`}>
+											<em>{row.subject} {row.comments > 0 && <span>[{row.comments}]</span>}</em>
+											{row.files > 0 && <FontAwesomeIcon icon={faFloppyDisk} />}
+											{row.images > 0 && <FontAwesomeIcon icon={faImage} />}
+											{row.medias > 0 && <FontAwesomeIcon icon={faVideo} />}
+										</Link>
+									</dt>
+									<dd>
+										<ul>
+											<li>{row.boardName}</li>
+											<li><FontAwesomeIcon icon={faEye} /> {row.views}</li>
+											<li><FontAwesomeIcon icon={faThumbsUp} /> {row.likes}</li>
+											<li>{getDateTime(row.createdAt)}</li>
+										</ul>
+									</dd>
+								</dl>
+							</section>
 						))
 					) : (
-						<tr>
-							<td colSpan={7} className="border p-2 text-center text-gray-500">
-								작성한 게시글이 없습니다.
-							</td>
-						</tr>
+						<p className="empty">작성한 게시글이 없습니다.</p>
 					)}
-				</tbody>
-				{data.list.length > 0 && (
-				<tfoot>
-					<tr>
-						<td colSpan={7}>
-							<Pagination total={data.total} page={page} perPage={20} onChange={setPage} />
-						</td>
-					</tr>
-				</tfoot>
-				)}
-			</table>
+				</article>
+			</section>
+
+			{data.list.length > 0 && (
+				<Pagination total={data.total} page={page} perPage={20} onChange={setPage} />
+			)}
 		</div>
 		</>
 	);
-}
+}

+ 145 - 34
app/(account)/my-posts/style.scss

@@ -6,54 +6,165 @@
 		margin-bottom: 10px;
 	}
 
-	table {
-		border: 1px solid #ccc;
+	.summary {
+		font-size: 16px;
+		margin-bottom: 10px;
+	}
 
-		caption {
-			text-align: left;
-			font-size: 16px;
-			margin-bottom: 10px;
-		}
+	.mypage-list {
+		border-top: 1px solid #eaeaea;
+		margin: 0.75rem 0;
 
-		tr {
-			th, td {
-				font-size: 14px;
-				text-align: center;
-				border: 1px solid #ccc;
-				padding: 6px 13px;
-			}
-		}
+		article:nth-of-type(1) {
+			background-color: #f9fafb;
+			border-bottom: 1px solid #eaeaea;
+			padding: 0.5rem 0;
+
+			ul {
+				display: grid;
+				grid-template-columns:
+					clamp(40px, 5%, 60px)
+					clamp(60px, 10%, 120px)
+					1fr
+					clamp(40px, 7%, 70px)
+					clamp(40px, 7%, 70px)
+					clamp(40px, 7%, 70px)
+					clamp(70px, 12%, 110px);
+				column-gap: 0.75rem;
 
-		thead {
-			tr {
-				th {
-					background: #f9f9f9;
-					font-weight: bold;
+				li {
+					text-align: center;
+					font-size: 0.875rem;
+					color: #666;
 				}
 			}
-		}
 
-		tbody {
-			tr {
-				td {
-					font-weight: normal;
-				}
+			@media (max-width: 1024px) {
+				display: none;
 			}
 		}
 
-		tfoot {
-			background: #fbfbfb;
+		article:nth-of-type(2) {
+			box-sizing: border-box;
 
-			tr {
-				td {
-					text-align: center;
-					padding: 8px;
+			section {
+				padding: 0.5rem 0;
+				box-sizing: inherit;
+				border-bottom: 1px solid #eaeaea;
+
+				&:hover {
+					background-color: #faffd1;
+				}
+
+				// PC
+				ol {
+					display: grid;
+					grid-template-columns:
+						clamp(40px, 5%, 60px)
+						clamp(60px, 10%, 120px)
+						1fr
+						clamp(40px, 7%, 70px)
+						clamp(40px, 7%, 70px)
+						clamp(40px, 7%, 70px)
+						clamp(70px, 12%, 110px);
+					column-gap: 0.75rem;
+					align-items: center;
+
+					li {
+						text-align: center;
+						font-size: 0.875rem;
+
+						&:nth-child(3) {
+							min-width: 0;
+							text-align: left;
+							word-break: keep-all;
+							overflow-wrap: break-word;
+
+							> svg {
+								padding-right: 4px;
+								color: #9c9898;
+							}
+						}
+					}
+				}
+
+				// Mobile
+				dl {
+					dt {
+						font-size: 1.063rem;
+						word-break: keep-all;
+						overflow-wrap: break-word;
 
-					button, a {
-						padding: 6px 20px;
+						> svg {
+							padding-right: 4px;
+							color: #9c9898;
+						}
+					}
+
+					dd {
+						ul {
+							display: flex;
+							flex-direction: row;
+							flex-wrap: nowrap;
+							justify-content: start;
+							padding-top: 0.4rem;
+							column-gap: 1rem;
+
+							li {
+								font-size: 0.813rem;
+								color: #888;
+
+								&:last-child {
+									flex-grow: 1;
+									text-align: right;
+								}
+							}
+						}
+					}
+				}
+
+				a {
+					color: #0060a9;
+					text-decoration: none;
+
+					&:hover {
+						text-decoration: underline;
+						color: #c7511f;
+					}
+
+					> em {
+						display: inherit;
+						font-style: normal;
+
+						> span {
+							color: #d13232;
+							font-size: 0.813rem;
+							vertical-align: text-top;
+							padding-right: 4px;
+						}
+					}
+
+					> svg {
+						padding-right: 4px;
+						color: #9c9898;
+					}
+				}
+
+				@media (max-width: 1024px) {
+					ol {
+						display: none;
+					}
+					dl {
+						display: block;
 					}
 				}
 			}
+
+			> .empty {
+				text-align: center;
+				padding: 2.5rem;
+				color: #999;
+			}
 		}
 	}
 }

+ 1 - 1
lib/utils/client.ts

@@ -95,7 +95,7 @@ export function getDateTime(dateString: string|null) {
         minute: '2-digit',
         second: '2-digit',
         hour12: false
-    }).replace(/\. /g, '.');
+    }).replace(/\. /g, '.').replace(/\.(\d{2}:)/, ' $1');
 }
 
 // 파일 이름 생성

+ 5 - 0
types/response/account/myPosts.ts

@@ -7,9 +7,14 @@ export interface MyPostsResponse {
         boardID: number;
         boardName: string;
         subject: string;
+        isSecret: boolean;
+        isReply: boolean;
         views: number;
         likes: number;
         comments: number;
+        images: number;
+        medias: number;
+        files: number;
         createdAt: string;
     }[]
 }