Files
sharebooks/src/main/resources/templates/book.html

1353 lines
32 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>社内図書一覧 - 社内備品・図書管理システム</title>
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
font-family: "Yu Gothic", "Meiryo", sans-serif;
color: #18243a;
font-size: 14px;
}
a {
text-decoration: none;
color: inherit;
}
button,
input,
select {
font-family: inherit;
}
/* ===== ヘッダー ===== */
.header {
height: 56px;
border-bottom: 1px solid #d8e0e8;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 18px;
background: #fff;
}
.header-title {
font-size: 21px;
font-weight: 700;
display: flex;
align-items: center;
gap: 8px;
}
.book-icon {
font-size: 24px;
}
.header-right {
display: flex;
align-items: center;
gap: 16px;
}
.bell {
font-size: 21px;
position: relative;
}
.badge {
position: absolute;
top: -5px;
right: -6px;
background: #e33;
color: #fff;
border-radius: 9px;
min-width: 12px;
height: 12px;
line-height: 12px;
text-align: center;
font-size: 9px;
}
.user {
font-size: 13px;
font-weight: 600;
}
.logout {
height: 32px;
padding: 0 12px;
border: 1px solid #a8b3c0;
border-radius: 5px;
background: #fff;
font-size: 13px;
font-weight: bold;
cursor: pointer;
}
/* ===== レイアウト ===== */
.layout {
display: flex;
min-height: calc(100vh - 96px);
}
/* ===== サイドバー ===== */
.sidebar {
width: 180px;
flex: 0 0 180px;
background: #082957;
color: #fff;
padding: 10px 7px;
}
.side-label {
font-size: 12px;
font-weight: bold;
margin: 3px 7px 10px;
}
/* 今回指定されたサイドバー:
トップメニュー
新規図書登録
社内図書一覧
*/
.side-menu {
min-height: 42px;
display: flex;
align-items: center;
gap: 7px;
padding: 0 7px;
border-radius: 4px;
font-size: 13px;
font-weight: bold;
margin-bottom: 4px;
}
.side-menu:hover {
background: #104c91;
}
.side-menu.active {
background: #1267d9;
}
.side-icon {
font-size: 15px;
width: 18px;
text-align: center;
}
/* ===== メイン ===== */
.content {
flex: 1;
min-width: 0;
padding: 12px 14px;
}
.breadcrumb {
font-size: 13px;
color: #5c6675;
margin-bottom: 5px;
}
.breadcrumb span {
margin: 0 6px;
color: #9aa4b2;
}
.title {
font-size: 26px;
margin: 0 0 12px;
}
/* ===== 検索 ===== */
.search-panel {
border: 1px solid #d6dee8;
border-radius: 5px;
padding: 11px 12px;
margin-bottom: 10px;
}
.search-grid {
display: grid;
grid-template-columns: 1.45fr 1fr 1fr 1fr 1fr;
gap: 9px;
align-items: end;
}
.search-grid.second {
grid-template-columns: 1fr 1.8fr 1.25fr auto;
margin-top: 9px;
}
.form-group label {
display: block;
font-size: 14px;
font-weight: bold;
margin-bottom: 6px;
}
.input,
.select {
width: 100%;
height: 36px;
border: 1px solid #cbd5e1;
border-radius: 4px;
background: #fff;
padding: 0 9px;
color: #38465a;
font-size: 13px;
}
.keyword-wrap {
position: relative;
}
.keyword-wrap .input {
padding-right: 28px;
}
.search-small-icon {
position: absolute;
right: 8px;
top: 7px;
color: #657184;
font-size: 15px;
}
.date-range {
display: grid;
grid-template-columns: 1fr 18px 1fr;
gap: 5px;
align-items: center;
}
.date-input {
height: 36px;
width: 100%;
border: 1px solid #cbd5e1;
border-radius: 4px;
padding: 0 7px;
font-size: 13px;
color: #7b8796;
}
.date-separator {
text-align: center;
color: #687386;
}
.check-wrap {
display: flex;
align-items: center;
gap: 7px;
height: 31px;
padding-left: 5px;
font-size: 13px;
white-space: nowrap;
}
.check-wrap input {
width: 14px;
height: 14px;
}
.button-area {
display: flex;
justify-content: flex-end;
gap: 7px;
height: 31px;
}
.btn {
min-width: 58px;
height: 31px;
border-radius: 4px;
padding: 0 12px;
font-size: 13px;
font-weight: bold;
cursor: pointer;
}
.btn-clear {
background: #fff;
border: 1px solid #aeb9c7;
}
.btn-search {
background: #1467d8;
border: 1px solid #1467d8;
color: #fff;
}
/* ===== 一覧 ===== */
.list-header {
display: flex;
justify-content: flex-end;
align-items: center;
gap: 8px;
margin-bottom: 6px;
font-size: 13px;
font-weight: bold;
}
.page-size {
height: 28px;
border: 1px solid #cbd5e1;
border-radius: 4px;
background: #fff;
padding: 0 8px;
font-size: 13px;
}
.table-wrap {
width: 100%;
overflow-x: auto;
border: 1px solid #d8e0e8;
}
.book-table {
width: 100%;
min-width: 1800px;
/* ★ 全16列が余裕を持って表示できるよう幅を拡張 */
border-collapse: collapse;
table-layout: fixed;
}
.book-table th {
height: 42px;
padding: 7px 6px;
background: #f5f7fa;
border-right: 1px solid #d8e0e8;
border-bottom: 1px solid #d8e0e8;
font-size: 12px;
white-space: nowrap;
}
.book-table td {
height: 58px;
padding: 6px 7px;
border-right: 1px solid #e1e6ec;
border-bottom: 1px solid #e1e6ec;
font-size: 12px;
text-align: center;
vertical-align: middle;
overflow: hidden;
}
/*
* 長くなりやすい項目は折り返して表示
*/
.book-table td.title-cell,
.book-table td:nth-child(4),
.book-table td:nth-child(5),
.book-table td:nth-child(7),
.book-table td:nth-child(8),
.book-table td:nth-child(12),
.book-table td:nth-child(15) {
white-space: normal;
line-height: 1.35;
overflow-wrap: anywhere;
}
/* 書籍名は特に見切れにくいよう左揃え */
.book-table td.title-cell {
text-align: left;
display: table-cell;
}
/* 日付・ID・状態などは1行を維持 */
.book-table td:nth-child(1),
.book-table td:nth-child(2),
.book-table td:nth-child(6),
.book-table td:nth-child(9),
.book-table td:nth-child(10),
.book-table td:nth-child(11),
.book-table td:nth-child(13),
.book-table td:nth-child(14) {
white-space: nowrap;
}
/* 1. 図書ID */
.book-table th:nth-child(1) {
width: 70px;
}
/* 2. ISBN */
.book-table th:nth-child(2) {
width: 110px;
}
/* 3. 書籍名 */
.book-table th:nth-child(3) {
width: 160px;
}
/* 4. 著者名 */
.book-table th:nth-child(4) {
width: 100px;
}
/* 5. 出版社 */
.book-table th:nth-child(5) {
width: 110px;
}
/* 6. 出版日 */
.book-table th:nth-child(6) {
width: 95px;
}
/* 7. カテゴリー名 */
.book-table th:nth-child(7) {
width: 110px;
}
/* 8. サブカテゴリー名 */
.book-table th:nth-child(8) {
width: 110px;
}
/* 9. 保管場所 */
.book-table th:nth-child(9) {
width: 100px;
}
/* 10. 貸出状態 */
.book-table th:nth-child(10) {
width: 82px;
}
/* 11. 本の状態 */
.book-table th:nth-child(11) {
width: 82px;
}
/* 12. 備考 */
.book-table th:nth-child(12) {
width: 120px;
}
/* 13. 登録日時 */
.book-table th:nth-child(13) {
width: 100px;
}
/* 14. 更新日時 */
.book-table th:nth-child(14) {
width: 100px;
}
/* 15. 寄贈者 */
.book-table th:nth-child(15) {
width: 100px;
}
/* 16. 操作 */
.book-table th:nth-child(16) {
width: 160px;
}
/* 操作列は常に右端に固定表示する */
.book-table th:nth-child(16),
.book-table td:nth-child(16) {
position: sticky;
right: 0;
z-index: 3;
background: #fff;
box-shadow: -3px 0 5px rgba(0, 0, 0, 0.08);
min-width: 160px;
}
.book-table th:nth-child(16) {
background: #f5f7fa;
z-index: 4;
}
/* 操作ボタンは3個を横一列に固定 */
.book-table td:nth-child(16) .action {
display: flex;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
gap: 3px;
width: 100%;
}
.book-table td:nth-child(16) .action-btn {
flex: 0 0 auto;
width: 44px;
height: 36px;
padding: 5px 4px;
font-size: 13px;
line-height: 1.15;
text-align: center;
display: inline-flex;
align-items: center;
justify-content: center;
}
.status {
display: inline-block;
padding: 3px 5px;
border-radius: 3px;
font-size: 11px;
font-weight: bold;
white-space: nowrap;
}
.available {
background: #e8f7ea;
color: #36924a;
}
.lending {
background: #fff0d9;
color: #dc7b11;
}
.good {
background: #e7f1ff;
color: #2870c9;
}
/* 本の状態:condition_s = 1(新品同様) */
.brand-new {
background: #eef4fc;
color: #1a56c4;
}
/* 本の状態:condition_s = 3(使用感あり) */
.normal {
background: #fdf6e3;
color: #8a6d1f;
}
/* 本の状態:condition_s = 4(傷みあり) */
.bad {
background: #fde8e8;
color: #c0392b;
}
/* 本の状態:condition_s = 0(仮値・不明) */
.unknown {
background: #eef0f2;
color: #6b7686;
}
.overdue {
display: block;
color: #e33;
font-size: 11px;
margin-top: 2px;
}
.action {
display: flex;
justify-content: center;
align-items: center;
gap: 3px;
white-space: nowrap;
}
.action-btn {
border: 0;
border-radius: 3px;
color: #fff;
padding: 4px 6px;
font-size: 11px;
line-height: 1.2;
font-weight: bold;
cursor: pointer;
white-space: nowrap;
}
.update {
background: #1267d9;
}
.delete {
background: #e33b35;
}
.loan {
background: #20a85a;
}
.return {
background: #1267d9;
}
.loan.disabled {
background: #b8c0ca;
color: #fff;
cursor: not-allowed;
opacity: 0.75;
}
/* ===== ページネーション ===== */
.pagination {
display: flex;
justify-content: center;
margin-top: 9px;
}
.page-btn {
min-width: 34px;
height: 27px;
border: 1px solid #d1d9e3;
border-right: 0;
background: #fff;
font-size: 13px;
color: #364257;
cursor: pointer;
display: inline-flex;
align-items: center;
justify-content: center;
text-decoration: none;
box-sizing: border-box;
}
.page-btn.disabled {
color: #b7c0cc;
cursor: not-allowed;
pointer-events: none;
}
.page-btn:last-child {
border-right: 1px solid #d1d9e3;
}
.page-btn.active {
background: #1267d9;
color: #fff;
border-color: #1267d9;
}
.note {
color: #1267d9;
font-size: 12px;
margin-top: 8px;
}
/* ===== フッター ===== */
.footer {
height: 44px;
border-top: 1px solid #dfe4ea;
display: flex;
align-items: center;
justify-content: center;
color: #687386;
font-size: 12px;
}
@media (max-width : 900px) {
.sidebar {
width: 150px;
flex-basis: 150px;
}
.search-grid,
.search-grid.second {
grid-template-columns: repeat(2, 1fr);
}
.button-area {
justify-content: flex-start;
}
}
@media (max-width : 600px) {
.user {
display: none;
}
.layout {
display: block;
}
.sidebar {
width: 100%;
}
.search-grid,
.search-grid.second {
grid-template-columns: 1fr;
}
}
</style>
<style>
/* ===== 権限別表示 ===== */
.user-view .book-table {
min-width: 1800px;
/* ★ 一般ビュー側も幅を統一 */
}
.user-view {
padding-top: 15px;
}
.admin-view {
padding-top: 12px;
}
</style>
</head>
<body>
<header class="header">
<div class="header-title">
<span class="book-icon">📖</span> ShareBooks
</div>
<div class="header-right">
<span class="user">
<%=employeeName%>(<%=roleName%>)
</span>
<form action="${pageContext.request.contextPath}/logout" method="post"
onsubmit="return confirm('ログアウトしますか?');">
<button class="logout">ログアウト</button>
</form>
</div>
</header>
<div class="layout">
<% if (isAdmin) { %>
<aside class="sidebar">
<div class="side-label">共通画面</div>
<a class="side-menu" href="${pageContext.request.contextPath}/topmenu.jsp"> <span
class="side-icon">⌂</span> トップメニュー
</a> <a class="side-menu" href="${pageContext.request.contextPath}/insertBook"> <span
class="side-icon">⊞</span> 新規図書登録
</a> <a class="side-menu active" href="${pageContext.request.contextPath}/BookServlet"> <span
class="side-icon">📖</span> 社内図書一覧
</a>
</aside>
<main class="content admin-view">
<div class="breadcrumb">
トップメニュー <span>›</span> 社内図書一覧
</div>
<h1 class="title">社内図書一覧</h1>
<!-- ===== 検索フォーム ===== -->
<form action="${pageContext.request.contextPath}/BookServlet" method="get">
<section class="search-panel">
<div class="search-grid">
<div class="form-group">
<label>キーワード</label>
<div class="keyword-wrap">
<input class="input" type="text" name="keyword" placeholder="書籍名・著者名・出版社など"> <span
class="search-small-icon">⌕</span>
</div>
</div>
<div class="form-group">
<label>カテゴリー</label> <select class="select" name="category">
<option value="">すべて</option>
<% List<String> categoryList = (List<String>) request.getAttribute("categoryList");
if (categoryList != null) {
for (String categoryName : categoryList) {
%>
<option value="<%=categoryName%>">
<%=categoryName%>
</option>
<% } } %>
</select>
</div>
<div class="form-group">
<label>サブカテゴリー</label> <select class="select" name="subcategory">
<option value="">すべて</option>
<% List<String> subcategoryList = (List<String>)
request.getAttribute("subcategoryList");
if (subcategoryList != null) {
for (String subcategoryName : subcategoryList) {
%>
<option value="<%=subcategoryName%>">
<%=subcategoryName%>
</option>
<% } } %>
</select>
</div>
<div class="form-group">
<label>保管場所</label> <select class="select" name="location">
<option value="">すべて</option>
<% List<String> locationList = (List<String>) request.getAttribute("locationList");
if (locationList != null) {
for (String locationName : locationList) {
%>
<option value="<%=locationName%>">
<%=locationName%>
</option>
<% } } %>
</select>
</div>
<div class="form-group">
<label>貸出状態</label> <select class="select" name="loanStatus">
<option>すべて</option>
<option>貸出可</option>
<option>貸出中</option>
</select>
</div>
</div>
<div class="search-grid second">
<div class="form-group">
<label>本の状態</label> <select class="select" name="condition">
<option>すべて</option>
<option>良好</option>
<option>普通</option>
<option>要修繕</option>
</select>
</div>
<div class="form-group">
<label>登録期間</label>
<div class="date-range">
<input class="date-input" type="date" name="fromDate"> <span
class="date-separator">~</span> <input class="date-input" type="date"
name="toDate">
</div>
</div>
<label class="check-wrap"> <input type="checkbox" name="showDeleted"> 削除済みを表示する
</label>
<div class="button-area">
<button type="reset" class="btn btn-clear">クリア</button>
<button type="submit" class="btn btn-search">🔍 検索</button>
</div>
</div>
</section>
</form>
<div class="list-header">
<span>全 <%=totalCount%> 件(10件ずつ表示)</span>
</div>
<!-- ===== 図書一覧(管理者用) ===== -->
<div class="table-wrap">
<table class="book-table">
<thead>
<tr>
<th>図書ID</th>
<th>ISBN</th>
<th>書籍名</th>
<th>著者名</th>
<th>出版社</th>
<th>出版日</th>
<th>カテゴリー名</th>
<th>サブカテゴリー名</th>
<th>保管場所</th>
<th>貸出状態</th>
<th>本の状態</th>
<th>備考</th>
<th>登録日時</th>
<th>更新日時</th>
<th>寄贈者</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<% if (bookList.isEmpty()) { %>
<tr>
<td colspan="16" style="text-align: center; padding: 24px;">
表示できる図書がありません。</td>
</tr>
<% } else { for (Book book : bookList) { boolean isLending=(book.getBookStatus()==1);
String statusLabel=isLending ? "貸出中" : "貸出可" ; String statusClass=isLending
? "lending" : "available" ; String conditionLabel; String conditionClass; switch
(book.getCondition()) { case 1 : conditionLabel="新品同様" ; conditionClass="brand-new"
; break; case 2 : conditionLabel="良好" ; conditionClass="good" ; break; case 3 :
conditionLabel="使用感あり" ; conditionClass="normal" ; break; case 4 :
conditionLabel="傷みあり" ; conditionClass="bad" ; break; default : conditionLabel="不明"
; conditionClass="unknown" ; break; } %>
<tr>
<td>
<%=book.getBookManageId()%>
</td>
<td>
<%=book.getIsbn() !=null ? book.getIsbn() : "-" %>
</td>
<td class="title-cell">
<%=book.getTitle()%>
</td>
<td>
<%=book.getAuthor()%>
</td>
<td>
<%=book.getPublisher() !=null ? book.getPublisher() : "-" %>
</td>
<td>
<%=book.getPublicationDate() !=null ?
dateFormat.format(book.getPublicationDate()) : "-" %>
</td>
<td>
<%=book.getCategoryName()%>
</td>
<td>
<%=book.getSubcategoryName()%>
</td>
<td>
<%=book.getLocationName()%>
</td>
<td><span class="status <%=statusClass%>">
<%=statusLabel%>
</span></td>
<td><span class="status <%=conditionClass%>">
<%=conditionLabel%>
</span></td>
<td>
<%=book.getDescription() !=null ? book.getDescription() : "-" %>
</td>
<td>
<%=book.getCreatedAt() !=null ? dateFormat.format(book.getCreatedAt()) : "-"
%>
</td>
<td>
<%=book.getUpdatedAt() !=null ? dateFormat.format(book.getUpdatedAt()) : "-"
%>
</td>
<td>
<%=book.getDonorName() !=null ? book.getDonorName() : "-" %>
</td>
<td>
<div class="action">
<a class="action-btn update"
href="${pageContext.request.contextPath}/book/update?bookId=<%= book.getBookManageId() %>">更新</a>
<button type="button" class="action-btn delete"
onclick="return confirmBookDelete('<%=book.getBookManageId()%>');">削除</button>
<% if (isLending) { %>
<button type="button" class="action-btn loan disabled" disabled
title="貸出中のため貸出できません">貸出</button>
<% } else { %>
<a class="action-btn loan"
href="${pageContext.request.contextPath}/book/loan?bookId=<%= book.getBookManageId() %>">貸出</a>
<% } %>
</div>
</td>
</tr>
<% } } %>
</tbody>
</table>
</div>
<div class="pagination">
<% String bookServletUrl=request.getContextPath() + "/BookServlet" ; String
keywordParam=request.getParameter("keyword"); String keywordQuery="" ; if (keywordParam !=null
&& !keywordParam.trim().isEmpty()) { keywordQuery="&keyword=" +
java.net.URLEncoder.encode(keywordParam.trim(), "UTF-8" ); } if (currentPage <=1) { %>
<span class="page-btn disabled">« 最初</span> <span class="page-btn disabled">‹ 前へ</span>
<% } else { %>
<a class="page-btn" href="<%=bookServletUrl%>?page=1<%=keywordQuery%>">« 最初</a> <a
class="page-btn" href="<%=bookServletUrl%>?page=<%=currentPage - 1%><%=keywordQuery%>">‹
前へ</a>
<% } int windowStart=Math.max(1, currentPage - 2); int windowEnd=Math.min(totalPages,
currentPage + 2); if (windowStart> 1) {
%>
<a class="page-btn" href="<%=bookServletUrl%>?page=1">1</a>
<% if (windowStart> 2) {
%>
<span class="page-btn disabled">…</span>
<% } %>
<% } for (int p=windowStart; p <=windowEnd; p++) { if (p==currentPage) { %>
<span class="page-btn active">
<%=p%>
</span>
<% } else { %>
<a class="page-btn"
href="<%=bookServletUrl%>?page=<%=p%><%=keywordQuery%>">
<%=p%>
</a>
<% } } if (windowEnd < totalPages) { if (windowEnd < totalPages - 1) {
%>
<span class="page-btn disabled">…</span>
<% } %>
<a class="page-btn"
href="<%=bookServletUrl%>?page=<%=totalPages%><%=keywordQuery%>">
<%=totalPages%>
</a>
<% } if (currentPage>= totalPages) {
%>
<span class="page-btn disabled">次へ ›</span> <span
class="page-btn disabled">最後 »</span>
<% } else { %>
<a class="page-btn"
href="<%=bookServletUrl%>?page=<%=currentPage + 1%><%=keywordQuery%>">次へ
›</a> <a class="page-btn"
href="<%=bookServletUrl%>?page=<%=totalPages%><%=keywordQuery%>">最後
»</a>
<% } %>
</div>
<div class="note">※「貸出中」の場合、返却予定日を赤字で表示しています。</div>
<% } else { %>
<aside class="sidebar">
<div class="side-label">一般メニュー</div>
<a class="side-menu" href="${pageContext.request.contextPath}/topmenu.jsp"> <span
class="side-icon">⌂</span> トップメニュー
</a> <a class="side-menu active" href="${pageContext.request.contextPath}/BookServlet"> <span
class="side-icon">📖</span> 社内図書一覧
</a>
</aside>
<main class="content user-view">
<div class="breadcrumb">
トップメニュー <span>›</span> 社内図書一覧
</div>
<h1 class="title">社内図書一覧</h1>
<p class="description">社内で所蔵している図書の一覧を表示します。</p>
<!-- ===== 検索 ===== -->
<form action="${pageContext.request.contextPath}/BookServlet" method="get">
<section class="search-panel">
<div class="search-grid">
<div class="form-group">
<label>キーワード</label>
<div class="keyword-wrap">
<input class="input" type="text" name="keyword"
placeholder="タイトル・著者名・出版社など"> <span class="search-small-icon">⌕</span>
</div>
</div>
<div class="form-group">
<label>カテゴリー</label> <select class="select" name="category">
<option value="">すべて</option>
<% List<String> categoryList = (List<String>)
request.getAttribute("categoryList");
if (categoryList != null) {
for (String categoryName : categoryList) {
%>
<option value="<%=categoryName%>">
<%=categoryName%>
</option>
<% } } %>
</select>
</div>
<div class="form-group">
<label>サブカテゴリー</label> <select class="select" name="subcategory">
<option value="">すべて</option>
<% List<String> subcategoryList = (List<String>)
request.getAttribute("subcategoryList");
if (subcategoryList != null) {
for (String subcategoryName : subcategoryList) {
%>
<option value="<%=subcategoryName%>">
<%=subcategoryName%>
</option>
<% } } %>
</select>
</div>
<div class="form-group">
<label>貸出状態</label> <select class="select" name="loanStatus">
<option>すべて</option>
<option>貸出可能</option>
<option>貸出中</option>
</select>
</div>
<div class="form-group">
<label>保管場所</label> <select class="select" name="location">
<option value="">すべて</option>
<% List<String> locationList = (List<String>)
request.getAttribute("locationList");
if (locationList != null) {
for (String locationName : locationList) {
%>
<option value="<%=locationName%>">
<%=locationName%>
</option>
<% } } %>
</select>
</div>
</div>
<div class="search-grid second">
<div class="form-group">
<label>本の状態</label> <select class="select" name="condition">
<option>すべて</option>
<option>良好</option>
<option>普通</option>
<option>要修繕</option>
</select>
</div>
<div></div>
<div></div>
<div class="button-area">
<button type="reset" class="btn btn-clear">クリア</button>
<button type="submit" class="btn btn-search">🔍 検索</button>
</div>
</div>
</section>
</form>
<div class="list-header">
<span>全 <%=totalCount%> 件(10件ずつ表示)</span>
</div>
<!-- ===== 一般ユーザー用図書一覧 ===== -->
<!-- ===== 一般ユーザー用図書一覧 ===== -->
<div class="table-wrap">
<table class="book-table">
<thead>
<tr>
<th>図書ID</th>
<th>ISBN</th>
<th>タイトル</th>
<th>著者名</th>
<th>出版社</th>
<th>カテゴリー名</th>
<th>サブカテゴリー名</th>
<th>保管場所</th>
<th>貸出状態</th>
<th>本の状態</th>
<th>備考</th>
<th>登録日時</th>
<th>更新日時</th>
</tr>
</thead>
<tbody>
<% if (bookList.isEmpty()) { %>
<tr>
<td colspan="13" style="text-align: center; padding: 24px;">
表示できる図書がありません。</td>
</tr>
<% } else { for (Book book : bookList) { boolean
isLending=(book.getBookStatus()==1); String statusLabel=isLending ? "貸出中"
: "貸出可" ; String statusClass=isLending ? "lending" : "available" ; String
conditionLabel; String conditionClass; switch (book.getCondition()) { case 1
: conditionLabel="新品同様" ; conditionClass="brand-new" ; break; case 2 :
conditionLabel="良好" ; conditionClass="good" ; break; case 3 :
conditionLabel="使用感あり" ; conditionClass="normal" ; break; case 4 :
conditionLabel="傷みあり" ; conditionClass="bad" ; break; default :
conditionLabel="不明" ; conditionClass="unknown" ; break; } %>
<tr>
<td>
<%=book.getBookManageId()%>
</td>
<td>
<%=book.getIsbn() !=null ? book.getIsbn() : "-" %>
</td>
<td class="title-cell">
<%=book.getTitle()%>
</td>
<td>
<%=book.getAuthor()%>
</td>
<td>
<%=book.getPublisher() !=null ? book.getPublisher() : "-" %>
</td>
<td>
<%=book.getCategoryName()%>
</td>
<td>
<%=book.getSubcategoryName()%>
</td>
<td>
<%=book.getLocationName()%>
</td>
<td><span class="status <%=statusClass%>">
<%=statusLabel%>
</span></td>
<td><span class="status <%=conditionClass%>">
<%=conditionLabel%>
</span></td>
<td>
<%=book.getDescription() !=null ? book.getDescription() : "-" %>
</td>
<td>
<%=book.getCreatedAt() !=null ?
dateFormat.format(book.getCreatedAt()) : "-" %>
</td>
<td>
<%=book.getUpdatedAt() !=null ?
dateFormat.format(book.getUpdatedAt()) : "-" %>
</td>
</tr>
<% } } %>
</tbody>
</table>
</div>
<div class="pagination">
<% String bookServletUrl=request.getContextPath() + "/BookServlet" ; String
keywordParam=request.getParameter("keyword"); String keywordQuery="" ; if (keywordParam
!=null && !keywordParam.trim().isEmpty()) { keywordQuery="&keyword=" +
java.net.URLEncoder.encode(keywordParam.trim(), "UTF-8" ); } if (currentPage <=1) { %>
<span class="page-btn disabled">« 最初</span> <span class="page-btn disabled">‹ 前へ</span>
<% } else { %>
<a class="page-btn" href="<%=bookServletUrl%>?page=1<%=keywordQuery%>">« 最初</a> <a
class="page-btn"
href="<%=bookServletUrl%>?page=<%=currentPage - 1%><%=keywordQuery%>">‹
前へ</a>
<% } int windowStart=Math.max(1, currentPage - 2); int
windowEnd=Math.min(totalPages, currentPage + 2); if (windowStart> 1) {
%>
<a class="page-btn" href="<%=bookServletUrl%>?page=1">1</a>
<% if (windowStart> 2) {
%>
<span class="page-btn disabled">…</span>
<% } %>
<% } for (int p=windowStart; p <=windowEnd; p++) { if (p==currentPage) {
%>
<span class="page-btn active">
<%=p%>
</span>
<% } else { %>
<a class="page-btn"
href="<%=bookServletUrl%>?page=<%=p%><%=keywordQuery%>">
<%=p%>
</a>
<% } } if (windowEnd < totalPages) { if (windowEnd < totalPages
- 1) { %>
<span class="page-btn disabled">…</span>
<% } %>
<a class="page-btn"
href="<%=bookServletUrl%>?page=<%=totalPages%><%=keywordQuery%>">
<%=totalPages%>
</a>
<% } if (currentPage>= totalPages) {
%>
<span class="page-btn disabled">次へ ›</span> <span
class="page-btn disabled">最後 »</span>
<% } else { %>
<a class="page-btn"
href="<%=bookServletUrl%>?page=<%=currentPage + 1%><%=keywordQuery%>">次へ
›</a> <a class="page-btn"
href="<%=bookServletUrl%>?page=<%=totalPages%><%=keywordQuery%>">最後
»</a>
<% } %>
</div>
<% } %>
</main>
</div>
<footer class="footer"> © 2026 社内備品・図書管理システム </footer>
<!-- ===== 削除用フォーム ===== -->
<form id="deleteForm" method="post" action="${pageContext.request.contextPath}/book/delete" style="display: none;">
<input type="hidden" id="deleteBookId" name="bookId">
</form>
<script>
function confirmBookDelete(bookId) {
var result = window.confirm("この本を削除しますか?");
if (!result) {
return false;
}
document.getElementById("deleteBookId").value = bookId;
document.getElementById("deleteForm").submit();
return false;
}
</script>
</body>
</html>