import React, { useState, useEffect, useCallback } from 'react';
import {
Save, Trash2, User, Calendar, Facebook, Activity, Search,
CheckCircle2, CreditCard, ChevronDown, Lock, KeyRound, LogOut,
ShieldCheck, Eye, EyeOff, AlertTriangle, Timer, Clock, Fingerprint,
MonitorOff, Server, CameraOff, Terminal, Delete, Package, UserCog,
ArrowLeft, ActivitySquare, ShieldAlert, HardDrive, Cpu, RefreshCw, Zap,
Globe, Shield, Scan, FileText, X, FileWarning
} from 'lucide-react';
// นำเข้า Firebase
import { initializeApp } from 'firebase/app';
import { getAuth, signInWithCustomToken, signInAnonymously, onAuthStateChanged } from 'firebase/auth';
import { getFirestore, collection, onSnapshot, addDoc, updateDoc, deleteDoc, doc, setDoc } from 'firebase/firestore';
// ตั้งค่า Firebase
let app, auth, db, appId;
const isExternalEnv = typeof __firebase_config === 'undefined';
try {
if (!isExternalEnv) {
const firebaseConfig = JSON.parse(__firebase_config);
app = initializeApp(firebaseConfig);
auth = getAuth(app);
db = getFirestore(app);
appId = typeof __app_id !== 'undefined' ? __app_id : 'default-app-id';
}
} catch (error) {
console.warn("Firebase Init Failed (Using LocalStorage fallback):", error);
}
export default function App() {
// โหลด Tailwind CSS
useEffect(() => {
if (!document.getElementById('tailwind-cdn')) {
const script = document.createElement('script');
script.id = 'tailwind-cdn';
script.src = 'https://cdn.tailwindcss.com';
document.head.appendChild(script);
}
}, []);
// --- State การเข้าสู่ระบบ ---
const [isInitializing, setIsInitializing] = useState(true);
const [bootLogs, setBootLogs] = useState([]);
const [isLoggedIn, setIsLoggedIn] = useState(false);
const [loginStep, setLoginStep] = useState(1);
const [loginData, setLoginData] = useState({ username: '', password: '', otp: '' });
const [loginError, setLoginError] = useState('');
const [failedAttempts, setFailedAttempts] = useState(0);
const [isLocked, setIsLocked] = useState(false);
const [lockoutTime, setLockoutTime] = useState(0);
const [showPassword, setShowPassword] = useState(false);
const [padKeys, setPadKeys] = useState(['1','2','3','4','5','6','7','8','9','0']); // สำหรับ Dynamic Keypad
const [isPrivacyMode, setIsPrivacyMode] = useState(true);
const [sessionTimeLeft, setSessionTimeLeft] = useState(300);
const [currentTime, setCurrentTime] = useState(new Date());
const [isWindowFocused, setIsWindowFocused] = useState(true);
const [screenshotWarning, setScreenshotWarning] = useState(false);
const [clientIp, setClientIp] = useState('171.97.xxx.xxx');
const [sessionId, setSessionId] = useState('');
const [securityViolation, setSecurityViolation] = useState(null);
const [currentPage, setCurrentPage] = useState('dashboard');
const [hashKey, setHashKey] = useState('0x...');
const [adminFormData, setAdminFormData] = useState({
firstName: '', lastName: '', nickname: '', age: '',
startDate: new Date().toISOString().split('T')[0], role: 'Super Admin'
});
const [viewRecordData, setViewRecordData] = useState(null); // State สำหรับแสดงข้อมูลรายบุคคล
const [firebaseUser, setFirebaseUser] = useState(null);
const [records, setRecords] = useState([]);
const [auditLogs, setAuditLogs] = useState([]);
const [isSyncing, setIsSyncing] = useState(false);
// --- Secure Boot Sequence ---
useEffect(() => {
if (!isInitializing) return;
const logs = [
"INITIALIZING ZENSHOP CORE PROTOCOLS...",
"ESTABLISHING AES-256-GCM ENCRYPTED TUNNEL...",
"VERIFYING TLS/SSL CERTIFICATES...",
"BLOCKING UNTRUSTED ROUTING...",
"CONNECTING TO SECURE NODE (TH-BKK-01)...",
"ENVIRONMENT SECURED."
];
let i = 0;
const interval = setInterval(() => {
setBootLogs(prev => [...prev, logs[i]]);
i++;
if (i >= logs.length) {
clearInterval(interval);
setTimeout(() => setIsInitializing(false), 1200);
}
}, 400);
return () => clearInterval(interval);
}, [isInitializing]);
// สร้าง IP, Session ID
useEffect(() => {
setClientIp(`171.97.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`);
setSessionId(`SEC-${Math.random().toString(36).substring(2, 10).toUpperCase()}`);
const hashInterval = setInterval(() => setHashKey(`0x${Math.random().toString(16).substring(2, 10).toUpperCase()}`), 2000);
return () => clearInterval(hashInterval);
}, []);
// Auth Init
useEffect(() => {
if (!auth) {
setFirebaseUser({ uid: 'local-dev-user' });
return;
}
const initAuth = async () => {
try {
if (typeof __initial_auth_token !== 'undefined' && __initial_auth_token) await signInWithCustomToken(auth, __initial_auth_token);
else await signInAnonymously(auth);
} catch (error) { console.error("Auth error:", error); }
};
initAuth();
const unsubscribe = onAuthStateChanged(auth, setFirebaseUser);
return () => unsubscribe();
}, []);
// Data Fetching
useEffect(() => {
if (!firebaseUser) return;
setIsSyncing(true);
let unsubRecords, unsubProfile, unsubLogs;
if (db) {
unsubRecords = onSnapshot(collection(db, 'artifacts', appId, 'users', firebaseUser.uid, 'crm_records'), (snapshot) => {
setRecords(snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })).sort((a, b) => b.createdAt - a.createdAt));
setIsSyncing(false);
});
unsubProfile = onSnapshot(doc(db, 'artifacts', appId, 'users', firebaseUser.uid, 'admin_profile', 'main'), (docSnap) => {
if (docSnap.exists()) setAdminFormData(docSnap.data());
});
unsubLogs = onSnapshot(collection(db, 'artifacts', appId, 'users', firebaseUser.uid, 'audit_logs'), (snapshot) => {
setAuditLogs(snapshot.docs.map(doc => ({ id: doc.id, ...doc.data() })).sort((a, b) => b.timestamp - a.timestamp));
});
} else {
const localRecords = localStorage.getItem('crm_records');
if (localRecords) setRecords(JSON.parse(localRecords).sort((a, b) => b.createdAt - a.createdAt));
const localProfile = localStorage.getItem('admin_profile');
if (localProfile) setAdminFormData(JSON.parse(localProfile));
const localLogs = localStorage.getItem('audit_logs');
if (localLogs) setAuditLogs(JSON.parse(localLogs).sort((a, b) => b.timestamp - a.timestamp));
setIsSyncing(false);
}
return () => { if (unsubRecords) unsubRecords(); if (unsubProfile) unsubProfile(); if (unsubLogs) unsubLogs(); };
}, [firebaseUser]);
// Audit Logging
const addAuditLog = async (eventText, statusStr, iconStr) => {
if (!firebaseUser) return;
const newLog = { event: eventText, status: statusStr, icon: iconStr, timestamp: Date.now() };
if (db) {
try { await addDoc(collection(db, 'artifacts', appId, 'users', firebaseUser.uid, 'audit_logs'), newLog); } catch (e) {}
} else {
newLog.id = Date.now().toString() + Math.random().toString(36).substr(2, 5);
setAuditLogs(prev => {
const updated = [newLog, ...prev].sort((a, b) => b.timestamp - a.timestamp);
localStorage.setItem('audit_logs', JSON.stringify(updated));
return updated;
});
}
};
const [showModal, setShowModal] = useState(false);
const [modalConfig, setModalConfig] = useState({ title: '', message: '', onConfirm: () => {}, onCancel: () => {}, isAlert: false });
// Security & Tracking
useEffect(() => {
let interval;
if (isLoggedIn && !securityViolation) {
interval = setInterval(() => {
setSessionTimeLeft((prev) => {
if (prev <= 1) { handleLogout(true); return 0; }
return prev - 1;
});
}, 1000);
const resetTimer = () => setSessionTimeLeft(300);
window.addEventListener('mousemove', resetTimer);
window.addEventListener('keydown', resetTimer);
return () => { clearInterval(interval); window.removeEventListener('mousemove', resetTimer); window.removeEventListener('keydown', resetTimer); };
}
}, [isLoggedIn, securityViolation]);
useEffect(() => {
const handleFocus = () => setIsWindowFocused(true);
const handleBlur = () => setIsWindowFocused(false);
const handleMouseLeave = (e) => { if (e.clientY <= 0 || e.clientX <= 0 || e.clientX >= window.innerWidth || e.clientY >= window.innerHeight) setIsWindowFocused(false); };
const handleMouseEnter = () => setIsWindowFocused(true);
window.addEventListener('focus', handleFocus); window.addEventListener('blur', handleBlur);
document.addEventListener('mouseleave', handleMouseLeave); document.addEventListener('mouseenter', handleMouseEnter);
// Prevent Dragging
document.ondragstart = () => false;
return () => {
window.removeEventListener('focus', handleFocus); window.removeEventListener('blur', handleBlur);
document.removeEventListener('mouseleave', handleMouseLeave); document.removeEventListener('mouseenter', handleMouseEnter);
document.ondragstart = null;
};
}, []);
useEffect(() => {
const handleKeyDown = (e) => {
// Extensive Block List
if (
e.key === 'F12' ||
(e.ctrlKey && e.shiftKey && ['I', 'J', 'C'].includes(e.key.toUpperCase())) ||
(e.ctrlKey && ['U', 'S'].includes(e.key.toUpperCase()))
) {
e.preventDefault(); setSecurityViolation('DEVTOOLS_ATTEMPT'); addAuditLog('พยายามเข้าถึงแกนระบบ (System Core)', 'Blocked', 'Alert'); setIsLoggedIn(false); return;
}
if (e.key === 'PrintScreen' || (e.metaKey && e.shiftKey && ['s', 'S', '3', '4', '5'].includes(e.key))) {
e.preventDefault(); setScreenshotWarning(true); addAuditLog('พยายามบันทึกภาพหน้าจอ', 'Blocked', 'Alert'); try { navigator.clipboard.writeText('⚠️ [SECURITY ALERT: CONFIDENTIAL DATA]'); } catch (err) {} setTimeout(() => setScreenshotWarning(false), 5000);
}
if (e.ctrlKey && ['c', 'x', 'p'].includes(e.key.toLowerCase())) { e.preventDefault(); addAuditLog(`พยายามคัดลอก/พิมพ์ข้อมูล`, 'Blocked', 'Alert'); }
};
const handleKeyUp = (e) => { if (e.key === 'PrintScreen') { e.preventDefault(); setScreenshotWarning(true); addAuditLog('พยายามบันทึกภาพหน้าจอ', 'Blocked', 'Alert'); try { navigator.clipboard.writeText('⚠️ [SECURITY ALERT]'); } catch (err) {} } };
window.addEventListener('keydown', handleKeyDown); window.addEventListener('keyup', handleKeyUp);
return () => { window.removeEventListener('keydown', handleKeyDown); window.removeEventListener('keyup', handleKeyUp); };
}, []);
useEffect(() => { const timer = setInterval(() => setCurrentTime(new Date()), 1000); return () => clearInterval(timer); }, []);
useEffect(() => {
let timer;
if (isLocked && lockoutTime > 0) timer = setInterval(() => setLockoutTime(p => { if (p <= 1) { setIsLocked(false); setFailedAttempts(0); return 0; } return p - 1; }), 1000);
return () => clearInterval(timer);
}, [isLocked, lockoutTime]);
// Handlers
const handleLoginChange = (e) => { setLoginData({ ...loginData, [e.target.name]: e.target.value }); setLoginError(''); };
// Dynamic Keypad Shuffle
const shuffleKeypad = () => {
let arr = [...padKeys];
for (let i = arr.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[arr[i], arr[j]] = [arr[j], arr[i]];
}
setPadKeys(arr);
};
useEffect(() => {
if (loginStep === 2) shuffleKeypad();
}, [loginStep]);
const handleOTPKeyPress = (val) => {
if (loginData.otp.length < 6) {
setLoginData(prev => ({ ...prev, otp: prev.otp + val }));
setLoginError('');
shuffleKeypad(); // Shuffle after every click
}
};
const handleOTPDelete = () => {
setLoginData(prev => ({ ...prev, otp: prev.otp.slice(0, -1) }));
shuffleKeypad();
};
const handleLoginSubmit = (e) => {
e.preventDefault();
if (isLocked) return;
if (loginStep === 1) {
if (loginData.username === 'ZenshopTHA' && loginData.password === 'ZenshopTHA123') { setLoginStep(2); setLoginError(''); setFailedAttempts(0); }
else {
const newAttempts = failedAttempts + 1; setFailedAttempts(newAttempts);
if (newAttempts >= 5) {
// SELF DESTRUCT PROTOCOL
localStorage.clear();
setSecurityViolation('BRUTE_FORCE_DETECTED');
} else if (newAttempts >= 3) {
setIsLocked(true); setLockoutTime(30); setLoginError('ตรวจพบความเสี่ยง: ระงับการใช้งานชั่วคราว');
}
else setLoginError(`การยืนยันล้มเหลว (เหลือโอกาส ${5 - newAttempts} ครั้งก่อนทำลายข้อมูล)`);
}
} else if (loginStep === 2) {
if (loginData.otp === '377821') { setIsLoggedIn(true); setSessionTimeLeft(300); setLoginError(''); setCurrentPage('dashboard'); addAuditLog('ระบบยืนยันตัวตนสำเร็จ (2FA)', 'Passed', 'User'); }
else { setLoginError('รหัส 2FA ไม่ถูกต้อง ระบบได้บันทึก IP ของคุณแล้ว'); setLoginData(prev => ({ ...prev, otp: '' })); shuffleKeypad(); }
}
};
const handleLogout = (isAuto = false) => {
if (isAuto) {
setIsLoggedIn(false); setLoginStep(1); setLoginData({ username: '', password: '', otp: '' });
setModalConfig({ title: 'สิ้นสุดการเชื่อมต่อ', message: 'เซสชันหมดอายุ ข้อมูลของคุณถูกเข้ารหัสและปิดผนึกเพื่อความปลอดภัย', onConfirm: () => setShowModal(false), isAlert: true });
setShowModal(true);
} else {
setModalConfig({
title: 'ยืนยันการตัดการเชื่อมต่อ', message: 'คุณต้องการสิ้นสุดช่องทางสื่อสารที่เข้ารหัสและออกจากระบบใช่หรือไม่?',
onConfirm: () => { setIsLoggedIn(false); setLoginStep(1); setLoginData({ username: '', password: '', otp: '' }); setShowModal(false); },
onCancel: () => setShowModal(false), isAlert: false
});
setShowModal(true);
}
};
const [formData, setFormData] = useState({ name: '', code: '', orderDate: new Date().toISOString().split('T')[0], orderNumber: '', product: '', facebookName: '', actionStatus: 'ชำระเงินแล้ว', amount: '' });
const [searchTerm, setSearchTerm] = useState('');
const handleChange = (e) => setFormData(prev => ({ ...prev, [e.target.name]: e.target.value }));
const handleSubmit = async (e) => {
e.preventDefault();
if (!formData.name || !formData.orderNumber || !firebaseUser) return;
try {
const newRecord = { ...formData, amount: parseFloat(formData.amount) || 0, createdAt: Date.now() };
if (db) await addDoc(collection(db, 'artifacts', appId, 'users', firebaseUser.uid, 'crm_records'), newRecord);
else {
newRecord.id = Date.now().toString() + Math.random().toString(36).substr(2, 5);
setRecords(prev => { const updated = [newRecord, ...prev]; localStorage.setItem('crm_records', JSON.stringify(updated)); return updated.sort((a, b) => b.createdAt - a.createdAt); });
}
await addAuditLog(`บันทึกข้อมูลเข้ารหัสสำเร็จ: ${formData.name}`, 'Passed', 'Save');
setFormData({ name: '', code: '', orderDate: new Date().toISOString().split('T')[0], orderNumber: '', product: '', facebookName: '', actionStatus: 'ชำระเงินแล้ว', amount: '' });
} catch (error) {}
};
const handleDelete = (id) => {
setModalConfig({
title: 'ลบข้อมูลขั้นเด็ดขาด (Critical Action)', message: 'โปรดยืนยันการทำลายข้อมูลนี้อย่างถาวร (การกระทำนี้จะถูกส่งคำสั่งไปยังเซิร์ฟเวอร์หลักทันที)',
onConfirm: async () => {
try {
if (firebaseUser) {
if (db) await deleteDoc(doc(db, 'artifacts', appId, 'users', firebaseUser.uid, 'crm_records', id));
else setRecords(prev => { const updated = prev.filter(r => r.id !== id); localStorage.setItem('crm_records', JSON.stringify(updated)); return updated; });
await addAuditLog(`ทำลายข้อมูลลูกค้ารหัส: ${id.substring(0, 6)}...`, 'Passed', 'Trash');
}
} catch (error) {}
setShowModal(false);
},
onCancel: () => setShowModal(false), isAlert: false
});
setShowModal(true);
};
const handleStatusChange = async (id, newStatus) => {
try {
if (firebaseUser) {
if (db) await updateDoc(doc(db, 'artifacts', appId, 'users', firebaseUser.uid, 'crm_records', id), { actionStatus: newStatus });
else setRecords(prev => { const updated = prev.map(r => r.id === id ? { ...r, actionStatus: newStatus } : r); localStorage.setItem('crm_records', JSON.stringify(updated)); return updated; });
await addAuditLog(`ปรับปรุงโปรโตคอลสถานะเป็น: ${newStatus}`, 'Passed', 'Update');
}
} catch (error) {}
};
const handleAdminChange = (e) => setAdminFormData(prev => ({ ...prev, [e.target.name]: e.target.value }));
const handleAdminSubmit = async (e) => {
e.preventDefault();
if (!firebaseUser) return;
try {
if (db) await setDoc(doc(db, 'artifacts', appId, 'users', firebaseUser.uid, 'admin_profile', 'main'), adminFormData);
else localStorage.setItem('admin_profile', JSON.stringify(adminFormData));
await addAuditLog(`อัปเดตสิทธิ์ระดับสูง: ${adminFormData.firstName || 'ไม่ระบุชื่อ'}`, 'Passed', 'User');
setModalConfig({ title: 'บันทึกข้อมูลสำเร็จ', message: 'มาตรการและระดับสิทธิ์ถูกซิงค์เข้ากับเซิร์ฟเวอร์เรียบร้อยแล้ว', onConfirm: () => setShowModal(false), isAlert: true });
setShowModal(true);
} catch (error) {}
};
// UI Helpers
const getStatusStyle = (status) => {
switch (status) {
case 'ชำระเงินแล้ว': return 'bg-indigo-50 text-indigo-700 border-indigo-200 focus:ring-indigo-500/20';
case 'กำลังดำเนินการ': return 'bg-amber-50 text-amber-700 border-amber-200 focus:ring-amber-500/20';
case 'สำเร็จ': return 'bg-emerald-50 text-emerald-700 border-emerald-200 focus:ring-emerald-500/20';
default: return 'bg-slate-50 text-slate-700 border-slate-200';
}
};
const getStatusIcon = (status) => {
switch (status) {
case 'ชำระเงินแล้ว': return
{modalConfig.message}
ตรวจพบการโจมตี (Brute Force/Tampering)
ระบบความปลอดภัยขั้นสูงสุด (Self-Destruct Protocol) ได้ทำงานแล้ว
ข้อมูลใน Local Storage ทั้งหมดถูกลบทิ้งเพื่อป้องกันการเข้าถึง ข้อมูลเครือข่าย [{clientIp}] ของคุณถูกบันทึกลง Blacklist
หน้าจอถูกซ่อนอัตโนมัติเนื่องจากคุณสลับไปใช้งานโปรแกรมอื่น
คลิกที่หน้าต่างเพื่อปลดล็อก
การพยายามบันทึกภาพหน้าจอถือเป็นการละเมิดนโยบายความปลอดภัย
ข้อมูลเหตุการณ์นี้ได้ถูกบันทึกลงระบบแล้ว
| เลขที่เอกสาร / วันที่ | ข้อมูลลูกค้า | สถานะดำเนินการ | จำนวนเงิน {isPrivacyMode && | จัดการ |
|---|---|---|---|---|
|
{record.orderNumber}
|
{maskData(record.name, 'name')}{record.code && {record.code}}
|
{getStatusIcon(record.actionStatus)}
|
{isPrivacyMode ? maskData(record.amount, 'amount') : Number(record.amount).toLocaleString('th-TH', { minimumFractionDigits: 2 })} |
|
|
ไม่พบข้อมูลในระบบ กรุณากรอกข้อมูลด้านซ้ายเพื่อเพิ่มรายการใหม่ หรือลองเปลี่ยนคำค้นหา |
||||
| เวลา | เหตุการณ์ | สถานะ |
|---|---|---|
| {getRelativeTime(log.timestamp)} | {renderLogIcon(log.icon)} {log.event} | {log.status} |
ยังไม่มีประวัติการใช้งาน | ||
ชื่อลูกค้า / บริษัท
{viewRecordData.name}
รหัสอ้างอิง
{viewRecordData.code || '-'}
วันที่ทำรายการ
เลขที่เอกสาร
{viewRecordData.orderNumber}
ช่องทางติดต่อ (Facebook)
สถานะดำเนินการ
{viewRecordData.actionStatus}ยอดเงินสุทธิ (THB)
฿{Number(viewRecordData.amount).toLocaleString('th-TH', { minimumFractionDigits: 2 })}
หน้าจอถูกซ่อนอัตโนมัติเนื่องจากคุณสลับไปใช้งานโปรแกรมอื่น
คลิกที่หน้าต่างเพื่อปลดล็อก
การพยายามบันทึกภาพหน้าจอถือเป็นการละเมิดนโยบายความปลอดภัย
ข้อมูลเหตุการณ์นี้ได้ถูกบันทึกลงระบบแล้ว