2
unknown
plain_text
a year ago
13 kB
7
Indexable
import React, { useState, useEffect } from "react";
import QrScanner from "react-qr-scanner";
import "./BorrowBook.css";
import Navbar from "../components/Navbar";
import Sidebar from "../components/Sidebar";
import { BASE_URL } from "../server/Endpoint";
import { Link } from "react-router-dom";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faArrowLeft,
faArrowRight,
faTimes,
} from "@fortawesome/free-solid-svg-icons";
const BorrowBook = () => {
const [formData, setFormData] = useState({
memberId: "",
bookCopyId: "",
additionalDays: "",
fullName: "",
username: "",
gender: "",
title: "",
author: "",
category: "",
});
const [message, setMessage] = useState({ text: "", type: "" });
const [showMemberScanner, setShowMemberScanner] = useState(false);
const [showBookScanner, setShowBookScanner] = useState(false);
const [loanHistory, setLoanHistory] = useState([]);
const [currentPage, setCurrentPage] = useState(0);
const [totalPages, setTotalPages] = useState(1);
useEffect(() => {
const fetchLoanHistory = async (page) => {
try {
const token = localStorage.getItem("token");
const response = await fetch(
`${BASE_URL}api/staff/loans/allLoanHistory/${page}?page=${page}`,
{
method: "GET",
headers: {
"ngrok-skip-browser-warning": "69420",
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
}
);
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
setLoanHistory(data.content); // Assuming the API returns a paginated response with `content`
setTotalPages(data.totalPages);
} catch (error) {
console.error("Error fetching loan history:", error);
setMessage({
text: "Không thể lấy lịch sử mượn sách. Vui lòng thử lại sau !!!",
type: "error",
});
}
};
fetchLoanHistory(currentPage);
}, [currentPage]);
const handlePageChange = (page) => {
setCurrentPage(page);
};
const handleSubmit = async (e) => {
e.preventDefault();
const { memberId, bookCopyId, additionalDays } = formData;
const token = localStorage.getItem("token");
const staffId = localStorage.getItem("userId");
const role = localStorage.getItem("role");
if (role !== "STAFF") {
setMessage({
text: "Bạn không có quyền thực hiện chức năng này.",
type: "error",
});
return;
}
const url = `${BASE_URL}api/staff/loans/borrow?memberId=${memberId}&bookCopyId=${bookCopyId}&additionalDays=${additionalDays}&createBy=${staffId}`;
try {
const response = await fetch(url, {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"ngrok-skip-browser-warning": "69420",
Authorization: `Bearer ${token}`,
},
});
if (!response.ok) {
const errorText = await response.text();
if (errorText.includes("No book found")) {
setMessage({
text: "Không có sách nào mượn với UserID này.",
type: "error",
});
} else if (errorText.includes("No user found")) {
setMessage({
text: "Không có người dùng nào với UserID này.",
type: "error",
});
} else {
setMessage({
text: "Không thể mượn sách. Vui lòng thử lại !!!",
type: "error",
});
}
return;
}
setMessage({
text: "Mượn sách thành công!",
type: "success",
});
setFormData({
memberId: "",
bookCopyId: "",
additionalDays: "",
fullName: "",
username: "",
gender: "",
title: "",
author: "",
category: "",
});
} catch (error) {
setMessage({
text: "Không thể mượn sách. Vui lòng thử lại !!!",
type: "error",
});
}
};
const handleScanMember = (data) => {
if (data) {
try {
const parsedData = JSON.parse(data.text);
setFormData((prevFormData) => ({
...prevFormData,
memberId: parsedData.memberid || "",
fullName: parsedData.fullName || "",
username: parsedData.username || "",
gender: parsedData.gender || "",
}));
setShowMemberScanner(false);
} catch (error) {
console.error("Error parsing QR code data:", error);
}
}
};
const handleScanBook = (data) => {
if (data) {
try {
const parsedData = JSON.parse(data.text);
setFormData((prevFormData) => ({
...prevFormData,
bookCopyId: parsedData.bookCopyId || "",
title: parsedData.title || "",
author: parsedData.author || "",
category: parsedData.categoryCode || "",
}));
setShowBookScanner(false);
} catch (error) {
console.error("Error parsing QR code data:", error);
}
}
};
const handleChange = (e) => {
const { name, value } = e.target;
setFormData((prevFormData) => ({
...prevFormData,
[name]: value,
}));
};
const handleError = (err) => {
console.error(err);
};
const formatDate = (dateString) => {
const options = { day: "numeric", month: "long", year: "numeric" };
const date = new Date(dateString);
return date.toLocaleDateString("vi-VN", options);
};
const previewStyle = {
height: 240,
width: 400,
};
return (
<div className="borrow-book-container">
<Navbar />
<div className="borrow-book-main">
<Sidebar className="borrow-book-sidebar" />
<div className="borrow-book-content">
<h2 className="borrow-book-title">Borrow Books</h2>
<form onSubmit={handleSubmit} className="borrow-book-form">
<div className="borrow-book-form-group">
<label>Member ID:</label>
<div className="borrow-book-input-group">
<input
type="number"
name="memberId"
value={formData.memberId}
onChange={handleChange}
required
/>
<button
type="button"
onClick={() => setShowMemberScanner((prev) => !prev)}
className="scan-button"
>
{showMemberScanner ? "Close Scanner" : "Scan QR"}
</button>
</div>
</div>
<div className="borrow-book-member-info">
<p>
Full Name:{" "}
<span className="info-text">{formData.fullName}</span>
</p>
<p>
Username: <span className="info-text">{formData.username}</span>
</p>
<p>
Gender: <span className="info-text">{formData.gender}</span>
</p>
</div>
{showMemberScanner && (
<div className="borrow-book-qr-scanner-container">
<QrScanner
delay={300}
style={previewStyle}
onError={handleError}
onScan={handleScanMember}
/>
<button
type="button"
onClick={() => setShowMemberScanner(false)}
className="borrow-book-close-button"
>
X
</button>
</div>
)}
<div className="borrow-book-form-group">
<label>Book ID:</label>
<div className="borrow-book-input-group">
<input
type="number"
name="bookCopyId"
value={formData.bookCopyId}
onChange={handleChange}
required
/>
<button
type="button"
onClick={() => setShowBookScanner((prev) => !prev)}
className="scan-button"
>
{showBookScanner ? "Close Scanner" : "Scan QR"}
</button>
</div>
</div>
{showBookScanner && (
<div className="qr-scanner-container">
<QrScanner
delay={300}
style={previewStyle}
onError={handleError}
onScan={handleScanBook}
/>
<button
type="button"
onClick={() => setShowBookScanner(false)}
className="borrow-book-close-button"
>
X
</button>
</div>
)}
<div className="borrow-book-book-info">
<p>
Title: <span className="info-text">{formData.title}</span>
</p>
<p>
Author: <span className="info-text">{formData.author}</span>
</p>
<p>
Category: <span className="info-text">{formData.category}</span>
</p>
</div>
<div className="borrow-book-form-group">
<label>Additional Days:</label>
<input
type="number"
name="additionalDays"
value={formData.additionalDays}
onChange={handleChange}
required
/>
</div>
<button type="submit" className="submit-button">
Borrow Book
</button>
{message.text && (
<div
className={`borrow-book-message ${
message.type === "error" ? "error" : "success"
}`}
>
{message.text}
</div>
)}
</form>
<div className="borrow-book-history">
<h3>Loan History</h3>
<table className="loan-history-table">
<thead>
<tr>
<th className="member-id">Loan ID</th>
<th className="title">Title</th>
<th className="user-name">User name</th>
<th className="borrowed-date">Borrowed Date</th>
<th className="returned-date">Returned Date</th>
<th className="status">Status</th>
<th className="action"></th>
</tr>
</thead>
<tbody>
{loanHistory.map((loan, index) => (
<tr key={index}>
<td className="member-id">{loan.loanId}</td>
<td className="title">{loan.copyBookTitle}</td>
<td className="user-name">{loan.userFullName}</td>
<td className="borrowed-date">
{formatDate(loan.loanDate)}
</td>
<td className="returned-date">
{formatDate(loan.dueDate)}
</td>
<td className="status">{loan.status}</td>
<td className="action">
<Link to={`/borroweddetail/${loan.loanId}`}>View</Link>
</td>
</tr>
))}
</tbody>
</table>
</div>
<div className="pagination">
<button
className="prev"
onClick={() => handlePageChange(currentPage - 1)}
disabled={currentPage === 0}
>
<FontAwesomeIcon icon={faArrowLeft} />
</button>
{Array.from({ length: totalPages }).map((_, index) => (
<button
key={index}
onClick={() => handlePageChange(index)}
className={index === currentPage ? "active" : ""}
>
{index + 1}
</button>
))}
<button
className="next"
onClick={() => handlePageChange(currentPage + 1)}
disabled={currentPage === totalPages - 1}
>
<FontAwesomeIcon icon={faArrowRight} />
</button>
</div>
</div>
</div>
</div>
);
};
export default BorrowBook;
Editor is loading...
Leave a Comment