import React, { useState, useEffect } from 'react';
import {
BookOpen,
User,
Phone,
Building,
MapPin,
Calendar as CalendarIcon,
Search,
CheckCircle2,
Clock,
Settings,
Mail,
Globe,
ArrowLeft,
Save,
Lock,
Unlock,
X,
FileText,
Download,
Printer,
AlertCircle,
KeyRound
} from 'lucide-react';
/**
* Aplikasi Buku Tamu Digital Desa
* Fitur: Form pendaftaran, Panel Admin dengan PIN (Dapat Diubah), Pengaturan Profil, dan Laporan Cetak.
*/
export default function App() {
// --- State Admin & Profil ---
const [currentView, setCurrentView] = useState('guestbook'); // 'guestbook' | 'admin'
const [adminTab, setAdminTab] = useState('profile'); // 'profile' | 'reports' | 'security'
const [isPinModalOpen, setIsPinModalOpen] = useState(false);
const [pinInput, setPinInput] = useState('');
const [pinError, setPinError] = useState(false);
// State untuk PIN Admin (Default: 123456)
const [adminPin, setAdminPin] = useState('123456');
// State untuk Ubah PIN
const [securityForm, setSecurityForm] = useState({
currentPin: '',
newPin: '',
confirmNewPin: ''
});
const [securityMessage, setSecurityMessage] = useState({ type: '', text: '' });
const [villageProfile, setVillageProfile] = useState({
name: 'Pemerintah Desa Nusantara, Kec. Makmur',
address: 'Jl. Raya Pemuda No. 1, Nusantara',
email: 'admin@desanusantara.go.id',
whatsapp: '081234567890',
website: 'www.desanusantara.go.id'
});
const [editProfile, setEditProfile] = useState(villageProfile);
const [showProfileSuccess, setShowProfileSuccess] = useState(false);
// --- State Filter Laporan ---
const [reportFilter, setReportFilter] = useState({
month: new Date().getMonth() + 1,
year: new Date().getFullYear()
});
// --- State Formulir ---
const [formData, setFormData] = useState({
name: '',
whatsapp: '',
agency: '',
address: '',
date: new Date().toISOString().split('T')[0]
});
// --- State Daftar Tamu ---
const [guests, setGuests] = useState([
{
id: 1,
name: 'Budi Santoso',
whatsapp: '081234567890',
agency: 'Dinas Pertanian Kabupaten',
address: 'Jl. Merdeka No. 45, Kota',
date: '2026-05-07',
timestamp: new Date().toISOString()
},
{
id: 2,
name: 'Siti Aminah',
whatsapp: '085678901234',
agency: 'Puskesmas Kecamatan',
address: 'Desa Sebelah RT 02/01',
date: '2026-05-06',
timestamp: new Date(Date.now() - 86400000).toISOString()
}
]);
// --- State Feedback UI ---
const [isSubmitting, setIsSubmitting] = useState(false);
const [showSuccess, setShowSuccess] = useState(false);
const [searchQuery, setSearchQuery] = useState('');
// --- Handlers ---
const handleInputChange = (e) => {
const { name, value } = e.target;
setFormData(prev => ({ ...prev, [name]: value }));
};
const handleSubmit = (e) => {
e.preventDefault();
if (!formData.name || !formData.whatsapp || !formData.agency || !formData.address || !formData.date) return;
setIsSubmitting(true);
setTimeout(() => {
const newGuest = {
id: Date.now(),
...formData,
timestamp: new Date().toISOString()
};
setGuests(prev => [newGuest, ...prev]);
setFormData({
name: '',
whatsapp: '',
agency: '',
address: '',
date: new Date().toISOString().split('T')[0]
});
setIsSubmitting(false);
setShowSuccess(true);
setTimeout(() => setShowSuccess(false), 3000);
}, 600);
};
const handleAdminAccess = () => {
if (currentView === 'admin') {
setCurrentView('guestbook');
} else {
setIsPinModalOpen(true);
}
};
const handlePinSubmit = (e) => {
e.preventDefault();
if (pinInput === adminPin) {
setPinError(false);
setPinInput('');
setIsPinModalOpen(false);
setEditProfile(villageProfile);
setCurrentView('admin');
} else {
setPinError(true);
setPinInput('');
}
};
const handleSaveProfile = (e) => {
e.preventDefault();
setVillageProfile(editProfile);
setShowProfileSuccess(true);
setTimeout(() => setShowProfileSuccess(false), 3000);
};
const handleUpdatePin = (e) => {
e.preventDefault();
setSecurityMessage({ type: '', text: '' });
if (securityForm.currentPin !== adminPin) {
setSecurityMessage({ type: 'error', text: 'PIN lama tidak sesuai!' });
return;
}
if (securityForm.newPin.length !== 6) {
setSecurityMessage({ type: 'error', text: 'PIN baru harus 6 digit angka!' });
return;
}
if (securityForm.newPin !== securityForm.confirmNewPin) {
setSecurityMessage({ type: 'error', text: 'Konfirmasi PIN baru tidak cocok!' });
return;
}
setAdminPin(securityForm.newPin);
setSecurityForm({ currentPin: '', newPin: '', confirmNewPin: '' });
setSecurityMessage({ type: 'success', text: 'PIN berhasil diperbarui!' });
};
// --- Logika Filter ---
const filteredGuests = guests.filter(guest =>
guest.name.toLowerCase().includes(searchQuery.toLowerCase()) ||
guest.agency.toLowerCase().includes(searchQuery.toLowerCase())
);
const reportData = guests.filter(guest => {
const guestDate = new Date(guest.date);
return (guestDate.getMonth() + 1) === parseInt(reportFilter.month) &&
guestDate.getFullYear() === parseInt(reportFilter.year);
});
const getMonthName = (monthNum) => {
return new Date(2000, monthNum - 1).toLocaleDateString('id-ID', { month: 'long' });
};
return (
{/* Header */}
Buku Tamu Digital
{villageProfile.name}
{/* Main Content */}
{currentView === 'admin' ? (
{adminTab === 'profile' && (
)}
{adminTab === 'reports' && (
Laporan Kunjungan
| Tanggal |
Nama |
Instansi |
{reportData.length > 0 ? reportData.map((guest) => (
| {guest.date} |
{guest.name} |
{guest.agency} |
)) : (
| Tidak ada data. |
)}
)}
{adminTab === 'security' && (
)}
) : (
/* --- TAMPILAN GUESTBOOK --- */
| Tamu |
Instansi |
Tanggal |
{filteredGuests.length > 0 ? filteredGuests.map((guest) => (
{guest.name} {guest.whatsapp} |
{guest.agency} |
{guest.date} |
)) : (
| Data tidak ditemukan. |
)}
)}
{/* Print View */}
{villageProfile.name}
{villageProfile.address}
LAPORAN KUNJUNGAN TAMU
Periode: {getMonthName(reportFilter.month)} {reportFilter.year}
| No |
Tanggal |
Nama |
Instansi |
WhatsApp |
{reportData.map((guest, idx) => (
| {idx + 1} |
{guest.date} |
{guest.name} |
{guest.agency} |
{guest.whatsapp} |
))}
{/* Pin Modal */}
{isPinModalOpen && (
)}
);
}