1353 lines
32 KiB
HTML
1353 lines
32 KiB
HTML
<!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> |