2
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;
Leave a Comment