import React, { useState, useEffect, useRef } from "react"; import jsPDF from "jspdf"; import autoTable from "jspdf-autotable"; export default function ReceiptApp() { const sidebarRef = useRef(null); const [sidebarOpen, setSidebarOpen] = useState(false); const [formData, setFormData] = useState({ name: "", amount: "", idCard: null, email: "", phone: "", }); const [receipts, setReceipts] = useState([]); const [visits, setVisits] = useState(0); const [step, setStep] = useState("กรอกข้อมูล"); useEffect(() => { const stored = localStorage.getItem("visits") || 0; const handleMouseMove = (e) => { setSidebarOpen(true); setSidebarOpen(false); } }; window.addEventListener("mousemove", handleMouseMove); return () => window.removeEventListener("mousemove", handleMouseMove); }, []); const handleChange = (e) => { const { name, value, files } = e.target; if (name === "idCard") { setFormData({ ...formData, idCard: files[0] }); } else { setFormData({ ...formData, [name]: value }); } }; const generateReferenceCode = () => { return "REF-" + Math.random().toString(36).substring(2, 8).toUpperCase(); }; const handleSubmit = (e) => { e.preventDefault(); alert("⚠️ กรุณากรอกข้อมูลให้ครบทุกช่องก่อนส่ง"); return; } if (!confirm("คุณต้องการยืนยันการบันทึกข้อมูลใช่หรือไม่?")) return; const newReceipt = { ...formData, approved: false, reference: generateReferenceCode(), statusDetail: "ข้อมูลถูกส่งเรียบร้อย รอการอนุมัติภายใน 3 วัน โดยหัวหน้าฝ่ายการเงิน", approver: "นางสาวสมฤดี ใจดี", }; setReceipts([...receipts, newReceipt]); setStep("รอการอนุมัติ"); }; const handleApprove = (id) => { setReceipts(receipts.map((r) => (r.id === id ? { ...r, approved: true } : r))); }; const exportPDF = () => { const doc = new jsPDF(); doc.setFontSize(18); doc.text("ใบสำคัญรับเงิน - รายงานทั้งหมด", 105, 15, { align: "center" }); autoTable(doc, { startY: 30, head: [["รหัสอ้างอิง", "ชื่อ", "จำนวน", "วันที่", "สถานะ"]], body: receipts.map((r) => [r.reference, r.name, r.amount, r.date, r.approved ? "✔ อนุมัติ" : "⏳ รอดำเนินการ"]), }); doc.save("receipts.pdf"); }; return ( <div className="flex flex-col min-h-screen bg-gradient-to-br from-slate-50 via-purple-100 to-indigo-100 font-sans"> <div className="flex flex-1 overflow-hidden"> <div ref={sidebarRef} className={`bg-gradient-to-b from-indigo-900 to-purple-700 text-white transition-all duration-300 ${sidebarOpen ? "w-72" : "w-16"} flex flex-col shadow-2xl rounded-tr-3xl rounded-br-3xl`} > <div className="flex items-center justify-between p-4"> <span className="text-xl font-extrabold tracking-wider"> {sidebarOpen ? "✨ ReceiptPro Ultra" : "✨"} </span> </div> <nav className="flex flex-col space-y-3 px-3 mt-4 text-sm"> <button className="hover:bg-purple-600 rounded-xl p-3 text-left font-medium"> {sidebarOpen ? "📝 กรอกข้อมูล" : "📝"} </button> <button className="hover:bg-purple-600 rounded-xl p-3 text-left font-medium"> {sidebarOpen ? "📂 ประวัติรับเงิน" : "📂"} </button> <button onClick={exportPDF} className="hover:bg-purple-600 rounded-xl p-3 text-left font-medium" > {sidebarOpen ? "📄 ดาวน์โหลด PDF" : "📄"} </button> </nav> </div> <div className="flex-1 overflow-y-auto p-8"> <div className="bg-white p-10 rounded-3xl shadow-2xl border border-purple-200"> <h1 className="text-4xl font-extrabold text-purple-700 mb-2 text-center tracking-tight"> 🚀 ระบบใบสำคัญรับเงิน </h1> <p className="text-center text-indigo-600 font-medium mb-6">🔄 ขั้นตอนล่าสุด: {step}</p> <form onSubmit={handleSubmit} className="grid gap-5 grid-cols-1 md:grid-cols-3"> <input type="text" name="name" value={formData.name} onChange={handleChange} placeholder="ชื่อผู้รับเงิน" className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required /> <input type="email" name="email" value={formData.email} onChange={handleChange} placeholder="อีเมล" className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required /> <input type="tel" name="phone" value={formData.phone} onChange={handleChange} placeholder="เบอร์โทรศัพท์" className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required /> <input type="number" name="amount" value={formData.amount} onChange={handleChange} placeholder="จำนวนเงิน (บาท)" className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required /> <input type="date" name="date" value={formData.date} onChange={handleChange} className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required /> <input type="file" name="idCard" accept="image/*,.pdf" onChange={handleChange} className="p-3 border rounded-xl" required /> <button type="submit" className="col-span-full bg-purple-600 hover:bg-purple-700 text-white font-semibold py-3 rounded-xl shadow-lg transition">💾 บันทึกข้อมูล</button> </form> <div className="mt-12"> <h2 className="text-2xl font-bold text-indigo-700 mb-5">📜 ประวัติการรับเงิน</h2> <ul className="space-y-4"> {receipts.map((item) => ( <div className="grid grid-cols-1 md:grid-cols-5 gap-x-4 gap-y-2 text-sm"> <p><strong>รหัส:</strong> {item.reference}</p> <p><strong>ชื่อ:</strong> {item.name}</p> <p><strong>จำนวน:</strong> {item.amount} บาท</p> <p><strong>สถานะ:</strong> {item.approved ? "✔ อนุมัติแล้ว" : "⏳ รออนุมัติ"}</p> </div> <div className="text-xs text-gray-600 mt-2"> <p>{item.statusDetail}</p> <p>กำหนดอนุมัติ: {item.approveDate} โดย {item.approver}</p> </div> {!item.approved && ( <button onClick={() => handleApprove(item.id)} className="mt-3 bg-emerald-500 hover:bg-emerald-600 text-white px-4 py-2 rounded-xl shadow"> ✅ ร้องขออนุมัติ </button> )} </li> ))} {receipts.length === 0 && <p className="text-gray-500 text-center">ไม่มีข้อมูลในระบบ</p>} </ul> </div> </div> </div> </div> <footer className="bg-white text-center py-5 text-sm text-gray-600 border-t mt-8"> <div>จำนวนผู้เข้าใช้งาน: {visits}</div> </footer> </div> ); }
Standard input is empty
import React, { useState, useEffect, useRef } from "react";
import jsPDF from "jspdf";
import autoTable from "jspdf-autotable";
export default function ReceiptApp() {
const sidebarRef = useRef(null);
const [sidebarOpen, setSidebarOpen] = useState(false);
const [formData, setFormData] = useState({
name: "",
amount: "",
date: "",
idCard: null,
email: "",
phone: "",
});
const [receipts, setReceipts] = useState([]);
const [visits, setVisits] = useState(0);
const [step, setStep] = useState("กรอกข้อมูล");
useEffect(() => {
const stored = localStorage.getItem("visits") || 0;
const next = parseInt(stored) + 1;
setVisits(next);
localStorage.setItem("visits", next);
const handleMouseMove = (e) => {
if (sidebarRef.current && e.clientX < 50) {
setSidebarOpen(true);
} else if (sidebarRef.current && e.clientX > 300) {
setSidebarOpen(false);
}
};
window.addEventListener("mousemove", handleMouseMove);
return () => window.removeEventListener("mousemove", handleMouseMove);
}, []);
const handleChange = (e) => {
const { name, value, files } = e.target;
if (name === "idCard") {
setFormData({ ...formData, idCard: files[0] });
} else {
setFormData({ ...formData, [name]: value });
}
};
const generateReferenceCode = () => {
return "REF-" + Math.random().toString(36).substring(2, 8).toUpperCase();
};
const handleSubmit = (e) => {
e.preventDefault();
const { name, amount, date, idCard, email, phone } = formData;
if (!name || !amount || !date || !idCard || !email || !phone) {
alert("⚠️ กรุณากรอกข้อมูลให้ครบทุกช่องก่อนส่ง");
return;
}
if (!confirm("คุณต้องการยืนยันการบันทึกข้อมูลใช่หรือไม่?")) return;
const newReceipt = {
...formData,
id: Date.now(),
approved: false,
reference: generateReferenceCode(),
statusDetail: "ข้อมูลถูกส่งเรียบร้อย รอการอนุมัติภายใน 3 วัน โดยหัวหน้าฝ่ายการเงิน",
approver: "นางสาวสมฤดี ใจดี",
approveDate: new Date(Date.now() + 3 * 86400000).toLocaleDateString(),
};
setReceipts([...receipts, newReceipt]);
setFormData({ name: "", amount: "", date: "", idCard: null, email: "", phone: "" });
setStep("รอการอนุมัติ");
};
const handleApprove = (id) => {
setReceipts(receipts.map((r) => (r.id === id ? { ...r, approved: true } : r)));
};
const exportPDF = () => {
const doc = new jsPDF();
doc.setFontSize(18);
doc.text("ใบสำคัญรับเงิน - รายงานทั้งหมด", 105, 15, { align: "center" });
autoTable(doc, {
startY: 30,
head: [["รหัสอ้างอิง", "ชื่อ", "จำนวน", "วันที่", "สถานะ"]],
body: receipts.map((r) => [r.reference, r.name, r.amount, r.date, r.approved ? "✔ อนุมัติ" : "⏳ รอดำเนินการ"]),
});
doc.save("receipts.pdf");
};
return (
<div className="flex flex-col min-h-screen bg-gradient-to-br from-slate-50 via-purple-100 to-indigo-100 font-sans">
<div className="flex flex-1 overflow-hidden">
<div
ref={sidebarRef}
className={`bg-gradient-to-b from-indigo-900 to-purple-700 text-white transition-all duration-300 ${sidebarOpen ? "w-72" : "w-16"} flex flex-col shadow-2xl rounded-tr-3xl rounded-br-3xl`}
>
<div className="flex items-center justify-between p-4">
<span className="text-xl font-extrabold tracking-wider">
{sidebarOpen ? "✨ ReceiptPro Ultra" : "✨"}
</span>
</div>
<nav className="flex flex-col space-y-3 px-3 mt-4 text-sm">
<button className="hover:bg-purple-600 rounded-xl p-3 text-left font-medium">
{sidebarOpen ? "📝 กรอกข้อมูล" : "📝"}
</button>
<button className="hover:bg-purple-600 rounded-xl p-3 text-left font-medium">
{sidebarOpen ? "📂 ประวัติรับเงิน" : "📂"}
</button>
<button
onClick={exportPDF}
className="hover:bg-purple-600 rounded-xl p-3 text-left font-medium"
>
{sidebarOpen ? "📄 ดาวน์โหลด PDF" : "📄"}
</button>
</nav>
</div>
<div className="flex-1 overflow-y-auto p-8">
<div className="bg-white p-10 rounded-3xl shadow-2xl border border-purple-200">
<h1 className="text-4xl font-extrabold text-purple-700 mb-2 text-center tracking-tight">
🚀 ระบบใบสำคัญรับเงิน
</h1>
<p className="text-center text-indigo-600 font-medium mb-6">🔄 ขั้นตอนล่าสุด: {step}</p>
<form onSubmit={handleSubmit} className="grid gap-5 grid-cols-1 md:grid-cols-3">
<input type="text" name="name" value={formData.name} onChange={handleChange} placeholder="ชื่อผู้รับเงิน" className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required />
<input type="email" name="email" value={formData.email} onChange={handleChange} placeholder="อีเมล" className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required />
<input type="tel" name="phone" value={formData.phone} onChange={handleChange} placeholder="เบอร์โทรศัพท์" className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required />
<input type="number" name="amount" value={formData.amount} onChange={handleChange} placeholder="จำนวนเงิน (บาท)" className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required />
<input type="date" name="date" value={formData.date} onChange={handleChange} className="p-3 border rounded-xl shadow-inner focus:outline-none focus:ring-2 focus:ring-purple-400" required />
<input type="file" name="idCard" accept="image/*,.pdf" onChange={handleChange} className="p-3 border rounded-xl" required />
<button type="submit" className="col-span-full bg-purple-600 hover:bg-purple-700 text-white font-semibold py-3 rounded-xl shadow-lg transition">💾 บันทึกข้อมูล</button>
</form>
<div className="mt-12">
<h2 className="text-2xl font-bold text-indigo-700 mb-5">📜 ประวัติการรับเงิน</h2>
<ul className="space-y-4">
{receipts.map((item) => (
<li key={item.id} className="bg-white border border-purple-200 rounded-xl p-4 shadow-md">
<div className="grid grid-cols-1 md:grid-cols-5 gap-x-4 gap-y-2 text-sm">
<p><strong>รหัส:</strong> {item.reference}</p>
<p><strong>ชื่อ:</strong> {item.name}</p>
<p><strong>จำนวน:</strong> {item.amount} บาท</p>
<p><strong>วันที่:</strong> {item.date}</p>
<p><strong>สถานะ:</strong> {item.approved ? "✔ อนุมัติแล้ว" : "⏳ รออนุมัติ"}</p>
</div>
<div className="text-xs text-gray-600 mt-2">
<p>{item.statusDetail}</p>
<p>กำหนดอนุมัติ: {item.approveDate} โดย {item.approver}</p>
</div>
{!item.approved && (
<button onClick={() => handleApprove(item.id)} className="mt-3 bg-emerald-500 hover:bg-emerald-600 text-white px-4 py-2 rounded-xl shadow">
✅ ร้องขออนุมัติ
</button>
)}
</li>
))}
{receipts.length === 0 && <p className="text-gray-500 text-center">ไม่มีข้อมูลในระบบ</p>}
</ul>
</div>
</div>
</div>
</div>
<footer className="bg-white text-center py-5 text-sm text-gray-600 border-t mt-8">
<div>© {new Date().getFullYear()} พัฒนาโดย ReceiptPro Ultra Team</div>
<div>จำนวนผู้เข้าใช้งาน: {visits}</div>
<div>วันที่: {new Date().toLocaleDateString()} เวลา: {new Date().toLocaleTimeString()}</div>
</footer>
</div>
);
}