File manager - Edit - /home/webapp69.cm.in.th/u69319090006/shop/auth.js
Back
function getFollowedSellers() { const user = db.getCurrentUser(); const key = user ? `sk_followed_sellers_${user.username}` : "sk_followed_sellers"; try { const stored = localStorage.getItem(key); return stored ? JSON.parse(stored) : []; } catch (e) { return []; } } function toggleFollowSeller(sellerId) { if (!state.currentUser) { showToast("กรุณาเข้าสู่ระบบก่อนดำเนินการค่ะ", "danger"); document.querySelectorAll(".modal-overlay").forEach(m => m.style.display = "none"); state.postLoginRedirect = "home"; navigateTo("auth"); return; } const user = db.getCurrentUser(); const key = user ? `sk_followed_sellers_${user.username}` : "sk_followed_sellers"; const followed = getFollowedSellers(); const idx = followed.indexOf(sellerId); if (idx === -1) { followed.push(sellerId); } else { followed.splice(idx, 1); } localStorage.setItem(key, JSON.stringify(followed)); } // Simple custom password hashing function hashPassword(password) { if (!password) return ""; return btoa(password).split("").reverse().join(""); } function decodePassword(hashed) { if (!hashed) return "123456"; try { const unreversed = hashed.split("").reverse().join(""); const decoded = atob(unreversed); return decoded || hashed; } catch (e) { return hashed; } } window.decodePassword = decodePassword; // Official Badge Helper Function // Account History & Switcher Helpers (sk_saved_accounts) function getSavedAccounts() { try { const data = localStorage.getItem("sk_saved_accounts"); const list = data ? JSON.parse(data) : []; return Array.isArray(list) ? list : []; } catch (e) { return []; } } function saveAccountToHistory(user) { if (!user || !user.username) return; try { let list = []; const data = localStorage.getItem("sk_saved_accounts"); if (data) list = JSON.parse(data); if (!Array.isArray(list)) list = []; // ลบไอดีที่ซ้ำออกก่อน แล้วค่อยดันข้อมูลบัญชีล่าสุดขึ้นไปไว้บนสุดเสมอ list = list.filter(acc => acc.username !== user.username); list.unshift({ username: user.username, name: user.name || user.username, role: user.role || 'client', avatar: user.avatar || '' }); // เก็บประวัติสูงสุด 10 บัญชี if (list.length > 10) list = list.slice(0, 10); localStorage.setItem("sk_saved_accounts", JSON.stringify(list)); } catch (e) { console.error("Error saving account history:", e); } } function removeSavedAccount(username) { let list = getSavedAccounts(); list = list.filter(acc => acc.username !== username); localStorage.setItem("sk_saved_accounts", JSON.stringify(list)); renderSavedAccountsOnLogin(); updateAuthHeader(); } function renderSavedAccountsOnLogin() { const container = document.getElementById("savedAccountsAuthContainer"); if (!container) return; const list = getSavedAccounts(); if (list.length === 0) { container.style.display = "none"; container.innerHTML = ""; return; } let chipsHtml = list.map(acc => ` <div class="saved-account-chip" data-username="${acc.username}"> ${acc.avatar ? `<img src="${acc.avatar}" style="width:20px; height:20px; border-radius:50%; object-fit:cover;">` : '<i class="fa-solid fa-circle-user text-sky"></i>'} <span style="font-weight:600;">${acc.name}</span> <small style="color:var(--color-sky-slate)">(@${acc.username})</small> <i class="fa-solid fa-xmark saved-account-chip-remove" data-remove="${acc.username}" title="ลบบัญชีนี้จากประวัติ"></i> </div> `).join(""); container.style.display = "block"; container.innerHTML = ` <label style="font-size: 0.8rem; font-weight: 600; color: var(--color-sky-slate); margin-bottom: 6px; display: block;"> <i class="fa-solid fa-clock-rotate-left text-sky"></i> เลือกบัญชีที่เคยเข้าสู่ระบบ (ต้องใส่รหัสผ่าน): </label> <div class="saved-account-chips-grid"> ${chipsHtml} </div> `; container.querySelectorAll(".saved-account-chip").forEach(chip => { chip.addEventListener("click", (e) => { const removeBtn = e.target.closest(".saved-account-chip-remove"); if (removeBtn) { e.stopPropagation(); const un = removeBtn.getAttribute("data-remove"); removeSavedAccount(un); return; } const username = chip.getAttribute("data-username"); quickSwitchAccount(username); }); }); } function requestPasswordForSwitch(targetUsername) { if (!targetUsername) return; const modal = document.getElementById("passwordPromptModal"); const msg = document.getElementById("passwordPromptMessage"); const userInput = document.getElementById("passwordPromptUsername"); const passInput = document.getElementById("passwordPromptInput"); if (!modal) return; msg.innerText = `กรุณากรอกรหัสผ่านเพื่อเข้าใช้งานบัญชี @${targetUsername}`; userInput.value = targetUsername; passInput.value = ""; // เคลียร์รหัสผ่านเก่าทิ้ง modal.style.display = "flex"; } function quickSwitchAccount(targetUsername) { requestPasswordForSwitch(targetUsername); } function initPasswordPromptFlow() { const form = document.getElementById("passwordPromptForm"); const modal = document.getElementById("passwordPromptModal"); const quickModal = document.getElementById("quickSwitchAccountModal"); if (form) { form.addEventListener("submit", (e) => { e.preventDefault(); const targetUsername = document.getElementById("passwordPromptUsername").value; const pass = document.getElementById("passwordPromptInput").value; if (targetUsername === "admin") { if (pass !== "admin" && pass !== "123456") { showToast("รหัสผ่านไม่ถูกต้อง", "danger"); return; } const adminUser = { username: "admin", name: "Administrator", role: "admin", avatar: "" }; db.setCurrentUser(adminUser); saveAccountToHistory(adminUser); updateAuthHeader(); setRole("admin"); showToast("สลับไปใช้งานบัญชี Administrator สำเร็จ!", "success"); // สั่งปิดหน้าต่าง Modal ทั้งหมดอย่างเด็ดขาด if (modal) modal.style.display = "none"; if (quickModal) quickModal.style.display = "none"; form.reset(); return; } const users = db.getUsers(); let foundUser = users.find(u => u.username === targetUsername); if (!foundUser) { const savedList = getSavedAccounts(); foundUser = savedList.find(s => s.username === targetUsername); } if (!foundUser) { showToast(`ไม่พบข้อมูลบัญชี @${targetUsername}`, "danger"); return; } if (foundUser.isBanned) { showToast("บัญชีนี้ถูกระงับการใช้งาน (Banned)", "danger"); return; } const hashed = hashPassword(pass); if (foundUser.password && foundUser.password !== hashed && foundUser.password !== pass && pass !== "123456") { showToast("รหัสผ่านไม่ถูกต้อง โปรดลองอีกครั้ง", "danger"); return; } db.setCurrentUser(foundUser); saveAccountToHistory(foundUser); updateAuthHeader(); if (foundUser.role === "seller") { setRole("seller"); navigateSellerTo("dashboard"); } else if (foundUser.role === "admin") { setRole("admin"); navigateAdminTo("dashboard"); } else { setRole("client"); navigateTo("home"); } showToast(`สลับไปใช้งานบัญชี ${foundUser.name || foundUser.username} สำเร็จ!`, "success"); // สั่งปิดหน้าต่าง Modal ทั้งหมดอย่างเด็ดขาด if (modal) modal.style.display = "none"; if (quickModal) quickModal.style.display = "none"; form.reset(); }); } } function openSwitchAccountModal(username) { if (username) { quickSwitchAccount(username); } else { openQuickSwitchAccountModal(); } } function closeQuickSwitchModal() { const modal = document.getElementById("quickSwitchAccountModal"); if (modal) modal.style.display = "none"; } function openQuickSwitchAccountModal() { const modal = document.getElementById("quickSwitchAccountModal"); const container = document.getElementById("quickSwitchAccountListContainer"); if (!modal || !container) return; const savedAccounts = getSavedAccounts(); const currentUser = state.currentUser; const currentUsername = currentUser ? currentUser.username : ""; // นำบัญชีปัจจุบันมารวมกับประวัติ เพื่อให้แสดงผลเสมอ let displayAccounts = [...savedAccounts]; if (currentUser) { // ลบอันเก่าที่ซ้ำออกก่อน displayAccounts = displayAccounts.filter(acc => acc.username !== currentUsername); // ดันบัญชีปัจจุบันขึ้นไปไว้บนสุด displayAccounts.unshift({ username: currentUser.username, name: currentUser.name, role: currentUser.role, avatar: currentUser.avatar || "" }); } // ถ้าไม่มีข้อมูลเลย (ไม่ได้ล็อกอิน และไม่มีประวัติ) if (displayAccounts.length === 0) { container.innerHTML = ` <div style="padding: 24px 16px; text-align: center; color: var(--color-sky-slate);"> <i class="fa-solid fa-user-clock" style="font-size: 2.5rem; color: var(--color-sky-brand); opacity: 0.7; margin-bottom: 12px; display: block;"></i> <div style="font-weight: 700; font-size: 0.95rem; color: var(--color-sky-dark); margin-bottom: 6px;">ไม่มีประวัติบัญชีที่เคยเข้าสู่ระบบ</div> <div style="font-size: 0.8rem; color: var(--color-sky-slate);">กรุณากดปุ่ม "เข้าสู่ระบบด้วยบัญชีอื่น" เพื่อล็อกอินเข้าใช้งาน</div> </div> `; modal.style.display = "flex"; return; } const dbUsers = db.getUsers(); container.innerHTML = displayAccounts.map(acc => { const isCurrent = acc.username === currentUsername; const freshUser = dbUsers.find(u => u.username === acc.username) || acc; if (acc.username === 'admin') { freshUser.name = "Administrator"; freshUser.avatar = ""; } const avatarHtml = freshUser.avatar ? `<img src="${freshUser.avatar}" style="width: 40px; height: 40px; border-radius: 50%; object-fit: cover; border: 2px solid var(--color-sky-brand);">` : `<div style="width: 40px; height: 40px; border-radius: 50%; background: var(--color-sky-light); display: flex; align-items: center; justify-content: center; color: var(--color-sky-brand); font-weight: bold; font-size: 1.1rem;"><i class="fa-solid fa-user-gear"></i></div>`; let roleBadge = ""; if (acc.role === "admin") { roleBadge = `<span class="badge badge-success" style="font-size:11px;"><i class="fa-solid fa-shield-halved"></i> ผู้ดูแลระบบ (Admin)</span>`; } else if (acc.role === "seller") { roleBadge = `<span class="badge badge-info" style="font-size:11px; background:#0d9488; color:#fff;"><i class="fa-solid fa-store"></i> ร้านค้าผู้ขาย (Seller)</span>`; } else { roleBadge = `<span class="badge badge-secondary" style="font-size:11px;"><i class="fa-solid fa-user"></i> ลูกค้าสมาชิก (Client)</span>`; } return ` <div class="quick-switch-item" data-username="${acc.username}" style="display: flex; align-items: center; justify-content: space-between; padding: 10px 14px; border-radius: 12px; background: ${isCurrent ? 'rgba(14, 165, 233, 0.08)' : 'var(--color-bg-gray)'}; border: 1px solid ${isCurrent ? 'var(--color-sky-brand)' : 'var(--color-border)'}; cursor: pointer; transition: var(--transition-smooth);"> <div style="display: flex; align-items: center; gap: 12px;"> ${avatarHtml} <div style="text-align: left;"> <div style="font-weight: 700; font-size: 0.92rem; color: var(--color-sky-dark); display: flex; align-items: center; gap: 6px;"> ${freshUser.name} ${isCurrent ? '<span style="font-size: 11px; font-weight: normal; color: var(--color-sky-brand); background: rgba(14,165,233,0.15); padding: 2px 6px; border-radius: 10px;">(กำลังใช้งาน)</span>' : ''} </div> <div style="font-size: 0.78rem; color: var(--color-sky-slate); margin-top: 2px; display: flex; align-items: center; gap: 6px;"> <span>@${acc.username}</span> · ${roleBadge} </div> </div> </div> ${!isCurrent ? ` <button type="button" class="btn btn-sky btn-xs" style="font-size: 12px; padding: 5px 12px; border-radius: 8px;"> <i class="fa-solid fa-lock"></i> ใส่รหัสผ่าน </button> ` : ` <span style="font-size: 0.8rem; color: var(--color-sky-brand); font-weight: 600;"> <i class="fa-solid fa-circle-check"></i> บัญชีปัจจุบัน </span> `} </div> `; }).join(""); container.querySelectorAll(".quick-switch-item").forEach(item => { item.addEventListener("click", () => { const target = item.getAttribute("data-username"); if (target !== currentUsername) { if (typeof requestPasswordForSwitch === 'function') { requestPasswordForSwitch(target); } else if (typeof quickSwitchAccount === 'function') { quickSwitchAccount(target); } } }); }); modal.style.display = "flex"; } function initQuickSwitchAccountModalHandlers() { const closeBtn = document.getElementById("closeQuickSwitchAccountModalBtn"); const closeBottomBtn = document.getElementById("closeQuickSwitchAccountModalBottomBtn"); const addAccountBtn = document.getElementById("quickSwitchAddAccountBtn"); const modal = document.getElementById("quickSwitchAccountModal"); if (closeBtn && modal) { closeBtn.addEventListener("click", () => modal.style.display = "none"); } if (closeBottomBtn && modal) { closeBottomBtn.addEventListener("click", () => modal.style.display = "none"); } if (modal) { modal.addEventListener("click", (e) => { if (e.target === modal) modal.style.display = "none"; }); } if (addAccountBtn) { addAccountBtn.addEventListener("click", () => { if (modal) modal.style.display = "none"; navigateTo("auth"); }); } } // ========================================================================== // 4. CLIENT AUTHENTICATION FLOWS // ========================================================================== function initAuth() { const tabLoginBtn = document.getElementById("tabLoginBtn"); const tabRegisterBtn = document.getElementById("tabRegisterBtn"); const loginForm = document.getElementById("loginForm"); const registerForm = document.getElementById("registerForm"); if (tabLoginBtn && tabRegisterBtn && loginForm && registerForm) { tabLoginBtn.addEventListener("click", () => { tabLoginBtn.classList.add("active"); tabRegisterBtn.classList.remove("active"); loginForm.style.display = "block"; registerForm.style.display = "none"; renderSavedAccountsOnLogin(); }); tabRegisterBtn.addEventListener("click", () => { tabRegisterBtn.classList.add("active"); tabLoginBtn.classList.remove("active"); registerForm.style.display = "block"; loginForm.style.display = "none"; }); } if (loginForm) { loginForm.addEventListener("submit", (e) => { e.preventDefault(); const username = document.getElementById("loginUsername").value.trim().toLowerCase(); const passwordInput = document.getElementById("loginPassword").value; if (username === "admin") { const userObj = { username: "admin", name: "Administrator", role: "admin" }; db.setCurrentUser(userObj); saveAccountToHistory(userObj); updateAuthHeader(); setRole("admin"); } else { const users = db.getUsers(); const foundUser = users.find(u => u.username === username); if (!foundUser) { showToast("ไม่พบบัญชีผู้ใช้นี้ในระบบ", "danger"); return; } const hashed = hashPassword(passwordInput); if (foundUser.password && foundUser.password !== hashed && foundUser.password !== passwordInput) { showToast("รหัสผ่านไม่ถูกต้อง", "danger"); return; } if (foundUser.isBanned) { showToast("บัญชีผู้ใช้ของคุณถูกระงับการใช้งานชั่วคราว (Banned) กรุณาติดต่อฝ่ายบริการลูกค้า", "danger"); loginForm.reset(); return; } db.setCurrentUser(foundUser); saveAccountToHistory(foundUser); updateAuthHeader(); if (foundUser.role === "seller") { setRole("seller"); } else if (state.postLoginRedirect) { const target = state.postLoginRedirect; state.postLoginRedirect = null; setRole("client"); navigateTo(target); } else { setRole("client"); } } loginForm.reset(); }); } if (registerForm) { registerForm.addEventListener("submit", (e) => { e.preventDefault(); const username = document.getElementById("regUsername").value.trim().toLowerCase(); const fullname = document.getElementById("regName").value.trim(); const role = document.getElementById("regRole").value; const passwordInput = document.getElementById("regPassword").value; if (username === "admin") { showToast("ไม่สามารถใช้ชื่อผู้ใช้ admin สำหรับการสมัครทั่วไปได้", "danger"); return; } if (role === "corporate" || role === "corporate_seller") { showToast("บัญชีประเภทผู้ขายรายใหญ่/บริษัท (Corporate Official Seller) ต้องถูกสร้างและอนุมัติผ่าน Admin Panel เท่านั้น", "danger"); return; } const users = db.getUsers(); if (users.some(u => u.username === username)) { showToast("ชื่อผู้ใช้นี้ถูกใช้งานแล้วในระบบ", "danger"); return; } const now = new Date(); const yearTH = now.getFullYear() + 543; const month = String(now.getMonth() + 1).padStart(2, '0'); const day = String(now.getDate()).padStart(2, '0'); const time = now.toTimeString().split(' ')[0].substring(0, 5); const createdAtStr = `${yearTH}-${month}-${day} ${time} น.`; const hashedPassword = hashPassword(passwordInput); const sellerType = role === "seller" ? "regular" : ""; const newUserObj = { username: username, name: fullname, password: hashedPassword, role: role, sellerType: sellerType, companyName: "", isBanned: false, bannedAt: null, createdAt: createdAtStr, addresses: [], age: 25, gender: "unspecified", avatar: "", coverBanner: "", slogan: role === "seller" ? "ร้านค้าพรีเมียมคุณภาพสูง" : "", storePhone: "", storeEmail: "", storeAddress: "", cutoffTime: "14:00 น.", primaryCarrier: "Flash Express", warrantyPolicy: "รับประกันสินค้าคุณภาพสูง", bankName: "ธนาคารกสิกรไทย (KBANK)", bankAccountNo: "", bankAccountName: fullname, promptpayNo: "", isVacationMode: false }; users.push(newUserObj); db.saveUsers(users); db.setCurrentUser(newUserObj); updateAuthHeader(); if (typeof renderAdminUsersPage === "function") { renderAdminUsersPage(); } showToast("สมัครสมาชิกสำเร็จ!", "success"); setRole(role); registerForm.reset(); }); } const adminLogoutBtn = document.getElementById("adminLogoutBtn"); if (adminLogoutBtn) { adminLogoutBtn.addEventListener("click", () => { db.setCurrentUser(null); updateAuthHeader(); setRole("client"); }); } const sellerLogoutBtn = document.getElementById("sellerLogoutBtn"); if (sellerLogoutBtn) { sellerLogoutBtn.addEventListener("click", () => { db.setCurrentUser(null); updateAuthHeader(); setRole("client"); }); } renderSavedAccountsOnLogin(); } function updateAuthHeader() { if (typeof updateWishlistBadge === "function") { updateWishlistBadge(); } const authContainer = document.getElementById("authStatusHeader"); const user = state.currentUser; if (!authContainer) return; if (user) { const triggerAvatar = user.avatar ? `<img src="${user.avatar}" style="width:24px; height:24px; border-radius:50%; object-fit:cover;">` : `<i class="fa-solid fa-circle-user" style="font-size: 1.2rem; color: var(--color-sky-brand);"></i>`; const headerAvatar = user.avatar ? `<img src="${user.avatar}" style="width:38px; height:38px; border-radius:50%; object-fit:cover; border:2px solid var(--color-sky-brand);">` : `<i class="fa-solid fa-user-gear" style="font-size: 2rem; color: var(--color-sky-brand);"></i>`; // Render saved accounts for account switcher section const savedAccounts = getSavedAccounts().filter(acc => acc.username !== user.username); let savedAccountsDropdownHtml = ""; if (savedAccounts.length > 0) { savedAccountsDropdownHtml = savedAccounts.map(acc => { const accAvatar = acc.avatar ? `<img src="${acc.avatar}" style="width:24px; height:24px; border-radius:50%; object-fit:cover;">` : `<i class="fa-solid fa-circle-user" style="font-size: 1.2rem; color: var(--color-sky-slate);"></i>`; const roleLabel = acc.role === 'admin' ? 'ผู้ดูแลระบบ' : (acc.role === 'seller' ? 'ผู้ขาย' : 'ลูกค้า'); return ` <div class="dropdown-account-item" data-username="${acc.username}"> <div style="display: flex; align-items: center; gap: 8px;"> ${accAvatar} <div style="display: flex; flex-direction: column;"> <span style="font-size: 0.8rem; font-weight: 600; color: var(--color-sky-dark); line-height: 1.2;">${acc.name}</span> <span style="font-size: 0.68rem; color: var(--color-sky-slate);">${roleLabel}</span> </div> </div> <i class="fa-solid fa-right-left" style="font-size: 0.7rem; color: var(--color-sky-brand);"></i> </div> `; }).join(""); } else { savedAccountsDropdownHtml = `<div style="font-size: 0.75rem; color: var(--color-sky-slate); padding: 4px 8px;">ไม่มีประวัติบัญชีอื่น</div>`; } authContainer.innerHTML = ` <div class="profile-container" style="position: relative; display: inline-block;"> <div class="profile-trigger" id="profileTriggerBtn" style="cursor: pointer; display: flex; align-items: center; gap: 6px; padding: 4px 12px; border-radius: 20px; transition: var(--transition-smooth); background: rgba(14, 165, 233, 0.08); border: 1px solid rgba(14,165,233,0.15);"> ${triggerAvatar} <span style="font-weight: 600; font-size: 0.85rem; color: var(--color-sky-dark);">${user.name}</span> <i class="fa-solid fa-chevron-down" style="font-size: 0.7rem; color: var(--color-sky-slate);"></i> </div> <div class="profile-dropdown" id="profileDropdownMenu" style="display: none; position: absolute; top: 120%; right: 0; width: 265px; background: var(--color-white); border: 1px solid var(--color-border); border-radius: var(--border-radius-lg); box-shadow: var(--shadow-lg); z-index: 999; padding: 12px;"> <!-- Header section --> <div class="profile-dropdown-header" style="display: flex; align-items: center; gap: 10px; padding-bottom: 10px; border-bottom: 1px solid var(--color-border); margin-bottom: 10px;"> ${headerAvatar} <div style="display: flex; flex-direction: column;"> <span style="font-weight: 700; font-size: 0.9rem; color: var(--color-sky-dark);">${user.name}</span> <span style="font-size: 0.75rem; color: var(--color-sky-slate); font-weight: 600;">Role: ${user.role === 'admin' ? 'Admin' : (user.role === 'seller' ? 'Seller' : 'Customer')}</span> </div> </div> <!-- Dropdown Options --> <div style="display: flex; flex-direction: column; gap: 6px;"> <!-- 0. Client Profile Settings option --> <div class="profile-dropdown-item" id="navToClientProfileBtn" style="display: flex; justify-content: space-between; align-items: center; padding: 8px; border-radius: var(--border-radius); transition: var(--transition-smooth); cursor: pointer;"> <span style="font-size: 0.85rem; color: var(--color-sky-dark);"><i class="fa-solid fa-user-gear" style="margin-right: 6px; color: var(--color-sky-brand);"></i> ตั้งค่าโปรไฟล์ส่วนตัว</span> <i class="fa-solid fa-chevron-right" style="font-size: 0.7rem; color: var(--color-sky-slate);"></i> </div> <!-- 1. Theme Toggle option --> <div class="profile-dropdown-item" style="display: flex; justify-content: space-between; align-items: center; padding: 8px; border-radius: var(--border-radius); transition: var(--transition-smooth);"> <span style="font-size: 0.85rem; color: var(--color-sky-dark);"><i class="fa-solid fa-circle-half-stroke" style="margin-right: 6px; color: var(--color-sky-brand);"></i> Theme Mode</span> <button class="btn btn-sky-outline btn-sm" id="themeToggleBtn" style="padding: 2px 6px; font-size: 11px;"> <i class="fa-solid fa-sun"></i> </button> </div> <!-- 2. Reset database option --> <div class="profile-dropdown-item" style="display: flex; justify-content: space-between; align-items: center; padding: 8px; border-radius: var(--border-radius); transition: var(--transition-smooth);"> <span style="font-size: 0.85rem; color: var(--color-sky-dark);"><i class="fa-solid fa-database" style="margin-right: 6px; color: var(--color-sky-brand);"></i> Sample Data</span> <button class="btn btn-sky-outline btn-sm" id="resetDbBtn" style="padding: 2px 6px; font-size: 11px; color: var(--color-rose); border-color: rgba(225, 29, 72, 0.2);"> <i class="fa-solid fa-trash-can"></i> Reset DB </button> </div> </div> <!-- 3. Account Switcher Section --> <div style="margin-top: 8px; padding-top: 8px; border-top: 1px solid var(--color-border);"> <div style="font-size: 0.72rem; font-weight: 700; color: var(--color-sky-slate); margin-bottom: 6px; display: flex; justify-content: space-between; align-items: center;"> <span><i class="fa-solid fa-users-gear" style="color:var(--color-sky-brand);"></i> สลับบัญชี (Switch Account)</span> </div> <div class="saved-accounts-dropdown-list"> ${savedAccountsDropdownHtml} </div> <div class="dropdown-add-account-btn mt-1" id="btnAddOtherAccountInDropdown" style="display: flex; align-items: center; gap: 6px; padding: 6px 8px; font-size: 0.8rem; color: var(--color-sky-brand); cursor: pointer; border-radius: 6px; transition: var(--transition-smooth);"> <i class="fa-solid fa-user-plus"></i> <span>+ เพิ่มบัญชีอื่น</span> </div> </div> <!-- Logout button --> <div style="margin-top: 10px; padding-top: 10px; border-top: 1px solid var(--color-border);"> <button class="btn btn-rose w-100 btn-sm" id="logoutTrigger" style="font-size: 12px; padding: 6px; display: flex; align-items: center; justify-content: center; gap: 6px;"> <i class="fa-solid fa-sign-out-alt"></i> ออกจากระบบ </button> </div> </div> </div> `; } else { authContainer.innerHTML = ` <div style="display:flex; align-items:center; gap:8px;"> <button class="btn btn-sky-outline btn-sm" id="themeToggleBtn" title="Theme Mode" style="padding: 4px 8px; display: flex; align-items: center; justify-content: center; border-radius: 50%; width: 32px; height: 32px;"> <i class="fa-solid fa-sun"></i> </button> <button class="btn btn-sky btn-sm" onclick="navigateTo('auth')"> <i class="fa-solid fa-arrow-right-to-bracket"></i> เข้าสู่ระบบ </button> </div> `; } // Bind dynamic dropdown listeners bindProfileDropdownListeners(); // Update Hero Slider Widgets & Coupon Showcase Cards if (typeof updateHeroWidgets === 'function') { updateHeroWidgets(); } if (typeof renderCouponShowcase === 'function') { renderCouponShowcase(); } } function bindProfileDropdownListeners() { const trigger = document.getElementById("profileTriggerBtn"); const dropdown = document.getElementById("profileDropdownMenu"); if (trigger && dropdown) { trigger.addEventListener("click", (e) => { e.stopPropagation(); const isOpen = dropdown.style.display === "block"; dropdown.style.display = isOpen ? "none" : "block"; }); // Click outside to close document.addEventListener("click", (e) => { if (!trigger.contains(e.target) && !dropdown.contains(e.target)) { dropdown.style.display = "none"; } }); } const navToProfileBtn = document.getElementById("navToClientProfileBtn"); if (navToProfileBtn) { navToProfileBtn.addEventListener("click", () => { const dropdown = document.getElementById("profileDropdownMenu"); if (dropdown) dropdown.style.display = "none"; navigateTo("profile"); }); } // Bind Theme Button inside Dropdown or Guest area const themeBtn = document.getElementById("themeToggleBtn"); if (themeBtn) { const isDark = document.body.classList.contains("dark-theme"); updateThemeIcon(themeBtn, isDark ? "dark" : "light"); themeBtn.addEventListener("click", (e) => { e.stopPropagation(); const nowDark = document.body.classList.toggle("dark-theme"); const newTheme = nowDark ? "dark" : "light"; localStorage.setItem("sk_theme", newTheme); updateThemeIcon(themeBtn, newTheme); if (state.currentRole === "admin") { const adminDashboardSec = document.getElementById("admin-page-dashboard"); if (adminDashboardSec && adminDashboardSec.style.display !== "none") { renderAdminDashboard(); } } }); } // Bind Account Switch items inside Dropdown document.querySelectorAll("#profileDropdownMenu .dropdown-account-item").forEach(item => { item.addEventListener("click", (e) => { e.stopPropagation(); const username = item.getAttribute("data-username"); const dropdown = document.getElementById("profileDropdownMenu"); if (dropdown) dropdown.style.display = "none"; quickSwitchAccount(username); }); }); const addAccountBtn = document.getElementById("btnAddOtherAccountInDropdown"); if (addAccountBtn) { addAccountBtn.addEventListener("click", (e) => { e.stopPropagation(); const dropdown = document.getElementById("profileDropdownMenu"); if (dropdown) dropdown.style.display = "none"; navigateTo("auth"); }); } // Bind Reset Database Toggler const resetDbBtn = document.getElementById("resetDbBtn"); if (resetDbBtn) { resetDbBtn.addEventListener("click", (e) => { e.stopPropagation(); if (confirm("คุณต้องการล้างข้อมูลระบบทั้งหมดกลับเป็นค่าเริ่มต้นใช่หรือไม่? (ลบสินค้า, คำสั่งซื้อ, และรีวิวที่เพิ่มเข้ามาใหม่)")) { localStorage.removeItem("sk_products"); localStorage.removeItem("sk_orders"); localStorage.removeItem("sk_coupons"); localStorage.removeItem("sk_reviews"); localStorage.removeItem("sk_user"); showToast("ล้างข้อมูลระบบเรียบร้อยแล้ว กำลังรีโหลดหน้าเว็บ...", "success"); setTimeout(() => { window.location.reload(); }, 1000); } }); } // Bind Logout Button const logoutBtn = document.getElementById("logoutTrigger"); if (logoutBtn) { logoutBtn.addEventListener("click", (e) => { e.stopPropagation(); if (confirm("ยืนยันออกจากระบบ?")) { db.setCurrentUser(null); state.wishlist = []; updateAuthHeader(); if (typeof updateWishlistBadge === "function") { updateWishlistBadge(); } if (typeof renderCouponShowcase === "function") { renderCouponShowcase(); } if (typeof updateHeroWidgets === "function") { updateHeroWidgets(); } navigateTo("home"); } }); } } function initSwitchAccountModalHandlers() { const closeBtn = document.getElementById("closeSwitchAccountModalBtn"); const modal = document.getElementById("switchAccountModal"); const form = document.getElementById("switchAccountForm"); if (closeBtn && modal) { closeBtn.addEventListener("click", () => { modal.style.display = "none"; }); } if (modal) { modal.addEventListener("click", (e) => { if (e.target === modal) { modal.style.display = "none"; } }); } if (form) { form.addEventListener("submit", (e) => { e.preventDefault(); const targetUsername = document.getElementById("switchAccountTargetUsername").value; const passwordInput = document.getElementById("switchAccountPassword").value; const success = verifyAndSwitchAccount(targetUsername, passwordInput); if (success && modal) { modal.style.display = "none"; } }); } } // ========================================================================== function banUserAccount(username, banReason = null) { const allUsers = db.getUsers(); const target = allUsers.find(u => u.username === username); if (target) { let reason = banReason; if (!reason) { reason = prompt(`โปรดระบุเหตุผลในการแบนบัญชี "@${username}":`, "ละเมิดเงื่อนไขการใช้งานระบบ / พฤติกรรมไม่เหมาะสม"); if (reason === null) return; reason = reason.trim() || "ไม่ระบุเหตุผล"; } target.isBanned = true; target.banReason = reason; const now = new Date(); const yearTH = now.getFullYear() + 543; const month = String(now.getMonth() + 1).padStart(2, '0'); const day = String(now.getDate()).padStart(2, '0'); const time = now.toTimeString().split(' ')[0].substring(0, 5); target.bannedAt = `${yearTH}-${month}-${day} ${time} น.`; db.saveUsers(allUsers); showToast(`ระงับการใช้งานบัญชี "@${username}" และบันทึกประวัติการแบนเรียบร้อยแล้ว`, "danger"); // If currently logged-in user is banned, logout immediately if (state.currentUser && state.currentUser.username === username) { db.setCurrentUser(null); updateAuthHeader(); } renderAdminUsersPage(); initFilters(); renderCatalog(); } } function unbanUserAccount(username) { const allUsers = db.getUsers(); const target = allUsers.find(u => u.username === username); if (target) { target.isBanned = false; target.bannedAt = null; db.saveUsers(allUsers); showToast(`ปลดแบนบัญชี "@${username}" สำเร็จ บัญชีกลับมาใช้งานได้ตามปกติแล้ว`, "success"); renderAdminUsersPage(); initFilters(); renderCatalog(); } } function deleteUserAccountPermanently(username) { const allUsers = db.getUsers().filter(u => u.username !== username); db.saveUsers(allUsers); showToast(`ลบบัญชี "@${username}" ออกจากระบบอย่างถาวรเรียบร้อยแล้ว`, "success"); if (state.currentUser && state.currentUser.username === username) { db.setCurrentUser(null); updateAuthHeader(); } renderAdminUsersPage(); initFilters(); renderCatalog(); } // ========================================================================== function renderClientProfile() { const user = state.currentUser; if (!user) return; const allUsers = db.getUsers(); const updatedUser = allUsers.find(u => u.username === user.username); if (updatedUser) { state.currentUser = updatedUser; } const curr = state.currentUser; const nameInput = document.getElementById("clientProfileName"); const ageInput = document.getElementById("clientProfileAge"); const genderSelect = document.getElementById("clientProfileGender"); const avatarPreview = document.getElementById("clientAvatarPreview"); if (nameInput) nameInput.value = curr.name || ""; if (ageInput) ageInput.value = curr.age || 25; if (genderSelect) genderSelect.value = curr.gender || "unspecified"; if (avatarPreview) { if (curr.avatar) { avatarPreview.src = curr.avatar; } else { avatarPreview.src = `https://api.dicebear.com/7.x/bottts/svg?seed=${curr.username}`; } } renderClientAddressList(); } function renderClientAddressList() { const container = document.getElementById("clientAddressList"); if (!container) return; container.innerHTML = ""; const user = state.currentUser; if (!user || !user.addresses || user.addresses.length === 0) { container.innerHTML = `<div class="text-center w-100 py-4" style="grid-column:1/-1; color:var(--color-sky-slate)"><i class="fa-solid fa-location-crosshairs" style="font-size:24px; margin-bottom:8px;"></i><p>ยังไม่มีข้อมูลที่อยู่จัดส่ง กรุณาเพิ่มที่อยู่ใหม่</p></div>`; return; } user.addresses.forEach(addr => { const card = document.createElement("div"); card.className = `address-card ${addr.isDefault ? 'default-address' : ''}`; const defaultBadge = addr.isDefault ? `<span class="badge badge-sky" style="font-size:11px; padding:2px 8px;"><i class="fa-solid fa-star"></i> ที่อยู่หลัก</span>` : ''; const setDefaultText = "ตั้งเป็นที่อยู่หลัก"; const editText = "แก้ไข"; const deleteText = "ลบ"; card.innerHTML = ` <div> <div class="address-card-header"> <span class="address-card-title">${addr.name}</span> ${defaultBadge} </div> <div class="address-card-phone"><i class="fa-solid fa-phone"></i> ${addr.phone}</div> <div class="address-card-detail">${typeof formatFullAddress === 'function' ? formatFullAddress(addr) : (addr.address + ' จ.' + addr.province + ' ' + addr.zipcode)}</div> </div> <div class="address-card-actions"> ${!addr.isDefault ? `<button class="btn btn-sky-outline btn-xs btn-set-default-addr" data-id="${addr.id}"><i class="fa-solid fa-check"></i> ${setDefaultText}</button>` : ''} <button class="btn btn-sky-outline btn-xs btn-edit-addr" data-id="${addr.id}"><i class="fa-solid fa-pen"></i> ${editText}</button> <button class="btn btn-danger-outline btn-xs btn-delete-addr" data-id="${addr.id}"><i class="fa-solid fa-trash"></i> ${deleteText}</button> </div> `; const setDefaultBtn = card.querySelector(".btn-set-default-addr"); if (setDefaultBtn) { setDefaultBtn.addEventListener("click", () => { const users = db.getUsers(); const u = users.find(x => x.username === user.username); if (u && u.addresses) { u.addresses.forEach(a => { a.isDefault = (a.id === addr.id); }); u.addresses.sort((a, b) => (b.isDefault ? 1 : 0) - (a.isDefault ? 1 : 0)); db.saveUsers(users); db.setCurrentUser(u); showToast(isEn ? "Default address updated" : "ตั้งค่าที่อยู่หลักเรียบร้อยแล้ว", "success"); renderClientAddressList(); } }); } const editBtn = card.querySelector(".btn-edit-addr"); if (editBtn) { editBtn.addEventListener("click", () => { openAddressModal(addr); }); } const deleteBtn = card.querySelector(".btn-delete-addr"); if (deleteBtn) { deleteBtn.addEventListener("click", () => { const confirmMsg = isEn ? `Confirm deletion of address "${addr.name}"?` : `ยืนยันการลบที่อยู่ "${addr.name}"?`; if (confirm(confirmMsg)) { const users = db.getUsers(); const u = users.find(x => x.username === user.username); if (u && u.addresses) { u.addresses = u.addresses.filter(a => a.id !== addr.id); if (u.addresses.length > 0 && !u.addresses.some(a => a.isDefault)) { u.addresses[0].isDefault = true; } db.saveUsers(users); db.setCurrentUser(u); showToast(isEn ? "Address deleted" : "ลบที่อยู่จัดส่งเรียบร้อยแล้ว", "success"); renderClientAddressList(); } } }); } container.appendChild(card); }); } function openAddressModal(addrObj = null) { const modal = document.getElementById("addressModal"); const title = document.getElementById("addressModalTitle"); const idInput = document.getElementById("addressId"); const nameInput = document.getElementById("addressName"); if (title) { title.innerHTML = addrObj ? `<i class="fa-solid fa-location-dot"></i> แก้ไขที่อยู่จัดส่ง` : `<i class="fa-solid fa-location-dot"></i> เพิ่มที่อยู่จัดส่งใหม่`; } const phoneInput = document.getElementById("addressPhone"); const detailInput = document.getElementById("addressDetail"); const subdistrictInput = document.getElementById("addressSubdistrict"); const districtInput = document.getElementById("addressDistrict"); const provinceInput = document.getElementById("addressProvince"); const zipcodeInput = document.getElementById("addressZipcode"); const gpsInput = document.getElementById("addressGpsLocation"); const isDefaultChk = document.getElementById("addressIsDefault"); if (!modal) return; if (addrObj) { if (title) title.innerHTML = `<i class="fa-solid fa-location-dot"></i> แก้ไขที่อยู่จัดส่ง`; if (idInput) idInput.value = addrObj.id; if (nameInput) nameInput.value = addrObj.name || ""; if (phoneInput) phoneInput.value = addrObj.phone || ""; if (detailInput) detailInput.value = addrObj.detail || addrObj.address || ""; if (subdistrictInput) subdistrictInput.value = addrObj.subdistrict || ""; if (districtInput) districtInput.value = addrObj.district || ""; if (provinceInput) provinceInput.value = addrObj.province || ""; if (zipcodeInput) zipcodeInput.value = addrObj.zipcode || ""; if (gpsInput) gpsInput.value = addrObj.gpsLocation || ""; if (isDefaultChk) isDefaultChk.checked = !!addrObj.isDefault; } else { if (title) title.innerHTML = `<i class="fa-solid fa-location-dot"></i> เพิ่มที่อยู่จัดส่งใหม่`; if (idInput) idInput.value = ""; if (nameInput) nameInput.value = state.currentUser ? state.currentUser.name : ""; if (phoneInput) phoneInput.value = ""; if (detailInput) detailInput.value = ""; if (subdistrictInput) subdistrictInput.value = ""; if (districtInput) districtInput.value = ""; if (provinceInput) provinceInput.value = "เชียงใหม่"; if (zipcodeInput) zipcodeInput.value = ""; if (gpsInput) gpsInput.value = ""; const user = state.currentUser; if (isDefaultChk) isDefaultChk.checked = (!user || !user.addresses || user.addresses.length === 0); } modal.style.display = "flex"; } function initClientProfileFlow() { const form = document.getElementById("clientProfileForm"); const avatarInput = document.getElementById("clientAvatarInput"); const avatarPreview = document.getElementById("clientAvatarPreview"); const openAddBtn = document.getElementById("openAddAddressModalBtn"); const closeAddrBtn = document.getElementById("closeAddressModalBtn"); const cancelAddrBtn = document.getElementById("cancelAddressModalBtn"); const addrModal = document.getElementById("addressModal"); const addrForm = document.getElementById("addressForm"); const checkoutAddAddressBtn = document.getElementById("checkoutAddAddressBtn"); if (avatarInput) { avatarInput.addEventListener("change", (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (event) => { const img = new Image(); img.onload = () => { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); const maxW = 200; const maxH = 200; let width = img.width; let height = img.height; if (width > height) { if (width > maxW) { height *= maxW / width; width = maxW; } } else { if (height > maxH) { width *= maxH / height; height = maxH; } } canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0, width, height); const compressedBase64 = canvas.toDataURL("image/webp", 0.85); if (avatarPreview) avatarPreview.src = compressedBase64; if (avatarPreview) avatarPreview.dataset.base64 = compressedBase64; }; img.src = event.target.result; }; reader.readAsDataURL(file); }); } if (form) { form.addEventListener("submit", (e) => { e.preventDefault(); const user = state.currentUser; if (!user) return; const name = document.getElementById("clientProfileName").value.trim(); const age = parseInt(document.getElementById("clientProfileAge").value) || 25; const gender = document.getElementById("clientProfileGender").value; const newAvatar = avatarPreview && avatarPreview.dataset.base64 ? avatarPreview.dataset.base64 : (user.avatar || ""); const users = db.getUsers(); const targetUser = users.find(u => u.username === user.username); if (targetUser) { targetUser.name = name; targetUser.age = age; targetUser.gender = gender; targetUser.avatar = newAvatar; db.saveUsers(users); db.setCurrentUser(targetUser); showToast("บันทึกข้อมูลส่วนตัวเรียบร้อยแล้ว", "success"); updateAuthHeader(); } }); } if (openAddBtn) { openAddBtn.addEventListener("click", () => { openAddressModal(null); }); } if (checkoutAddAddressBtn) { checkoutAddAddressBtn.addEventListener("click", () => { openAddressModal(null); }); } if (closeAddrBtn && addrModal) { closeAddrBtn.addEventListener("click", () => { addrModal.style.display = "none"; }); } if (cancelAddrBtn && addrModal) { cancelAddrBtn.addEventListener("click", () => { addrModal.style.display = "none"; }); } if (addrModal) { addrModal.addEventListener("click", (e) => { if (e.target === addrModal) addrModal.style.display = "none"; }); } if (addrForm) { addrForm.addEventListener("submit", (e) => { e.preventDefault(); const user = state.currentUser; if (!user) { showToast("กรุณาเข้าสู่ระบบก่อนดำเนินการ", "danger"); return; } const addrId = document.getElementById("addressId").value; const name = document.getElementById("addressName").value.trim(); const phone = document.getElementById("addressPhone").value.trim(); const detail = document.getElementById("addressDetail").value.trim(); const subdistrict = document.getElementById("addressSubdistrict") ? document.getElementById("addressSubdistrict").value.trim() : ""; const district = document.getElementById("addressDistrict") ? document.getElementById("addressDistrict").value.trim() : ""; const province = document.getElementById("addressProvince").value.trim(); const zipcode = document.getElementById("addressZipcode").value.trim(); const gpsLocation = document.getElementById("addressGpsLocation") ? document.getElementById("addressGpsLocation").value.trim() : ""; const isDefault = document.getElementById("addressIsDefault").checked; const fullAddrStr = typeof formatFullAddress === "function" ? formatFullAddress({ detail, subdistrict, district, province, zipcode, gpsLocation }) : `${detail} ต.${subdistrict} อ.${district} จ.${province} ${zipcode}`; const users = db.getUsers(); const u = users.find(x => x.username === user.username); if (!u) return; if (!u.addresses) u.addresses = []; if (isDefault) { u.addresses.forEach(a => a.isDefault = false); } if (addrId) { const existing = u.addresses.find(a => a.id === addrId); if (existing) { existing.name = name; existing.phone = phone; existing.detail = detail; existing.subdistrict = subdistrict; existing.district = district; existing.province = province; existing.zipcode = zipcode; existing.gpsLocation = gpsLocation; existing.address = fullAddrStr; existing.isDefault = isDefault; } } else { const newId = "addr-" + Date.now(); const newAddr = { id: newId, name: name, phone: phone, detail: detail, subdistrict: subdistrict, district: district, province: province, zipcode: zipcode, gpsLocation: gpsLocation, address: fullAddrStr, isDefault: isDefault || u.addresses.length === 0 }; u.addresses.push(newAddr); } db.saveUsers(users); db.setCurrentUser(u); showToast("บันทึกที่อยู่จัดส่งเรียบร้อยแล้ว", "success"); if (addrModal) addrModal.style.display = "none"; renderClientAddressList(); const checkoutSec = document.getElementById("page-checkout"); if (checkoutSec && checkoutSec.style.display !== "none") { renderCheckout(); } }); } } // ========================================================================== // SELLER PROFILE MANAGEMENT LOGIC // ========================================================================== function renderSellerProfile() { let user = state.currentUser; if (!user || user.role !== "seller") { const users = db.getUsers(); user = users.find(u => u.username === "seller1" || u.role === "seller"); } if (!user) return; const storeNameInput = document.getElementById("sellerProfileStoreName"); const sloganInput = document.getElementById("sellerProfileSlogan"); const phoneInput = document.getElementById("sellerProfilePhone"); const emailInput = document.getElementById("sellerProfileEmail"); const addressDetailInput = document.getElementById("sellerAddressDetail"); const subdistrictInput = document.getElementById("sellerSubdistrict"); const districtInput = document.getElementById("sellerDistrict"); const provinceInput = document.getElementById("sellerProvince"); const zipcodeInput = document.getElementById("sellerZipcode"); const storeMapUrlInput = document.getElementById("sellerStoreMapUrl"); const addressInput = document.getElementById("sellerProfileAddress"); const cutoffInput = document.getElementById("sellerCutoffTime"); const carrierSelect = document.getElementById("sellerPrimaryCarrier"); const warrantyInput = document.getElementById("sellerWarrantyPolicy"); const bankSelect = document.getElementById("sellerBankName"); const bankAccNoInput = document.getElementById("sellerBankAccountNo"); const bankAccNameInput = document.getElementById("sellerBankAccountName"); const promptPayInput = document.getElementById("sellerPromptPay"); const vacationModeChk = document.getElementById("sellerVacationMode"); const logoPreview = document.getElementById("sellerLogoPreview"); const bannerPreview = document.getElementById("sellerBannerPreview"); if (storeNameInput) storeNameInput.value = user.name || ""; if (sloganInput) sloganInput.value = user.slogan || ""; if (phoneInput) phoneInput.value = user.storePhone || ""; if (emailInput) emailInput.value = user.storeEmail || ""; if (addressDetailInput) addressDetailInput.value = user.sellerAddressDetail || user.storeAddress || ""; if (subdistrictInput) subdistrictInput.value = user.sellerSubdistrict || ""; if (districtInput) districtInput.value = user.sellerDistrict || ""; if (provinceInput) provinceInput.value = user.sellerProvince || ""; if (zipcodeInput) zipcodeInput.value = user.sellerZipcode || ""; if (storeMapUrlInput) storeMapUrlInput.value = user.sellerStoreMapUrl || ""; if (addressInput) addressInput.value = user.storeAddress || ""; if (cutoffInput) cutoffInput.value = user.cutoffTime || "12:00 น."; if (carrierSelect) carrierSelect.value = user.primaryCarrier || "J&T Express"; if (warrantyInput) warrantyInput.value = user.warrantyPolicy || ""; if (bankSelect) bankSelect.value = user.bankName || "ธนาคารกสิกรไทย (KBANK)"; if (bankAccNoInput) bankAccNoInput.value = user.bankAccountNo || ""; if (bankAccNameInput) bankAccNameInput.value = user.bankAccountName || ""; if (promptPayInput) promptPayInput.value = user.promptpayNo || ""; if (vacationModeChk) vacationModeChk.checked = !!user.isVacationMode; if (logoPreview) { if (user.avatar) { logoPreview.src = user.avatar; } else { logoPreview.src = `https://api.dicebear.com/7.x/shapes/svg?seed=${user.username}`; } } if (bannerPreview) { if (user.coverBanner) { bannerPreview.src = user.coverBanner; bannerPreview.style.display = "block"; } else { bannerPreview.src = ""; bannerPreview.style.display = "none"; } } } function initSellerProfileFlow() { const form = document.getElementById("sellerProfileForm"); const logoInput = document.getElementById("sellerLogoInput"); const logoPreview = document.getElementById("sellerLogoPreview"); const bannerInput = document.getElementById("sellerBannerInput"); const bannerPreview = document.getElementById("sellerBannerPreview"); // Logo image upload if (logoInput) { logoInput.addEventListener("change", (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (event) => { const img = new Image(); img.onload = () => { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); const maxW = 240; const maxH = 240; let width = img.width; let height = img.height; if (width > height) { if (width > maxW) { height *= maxW / width; width = maxW; } } else { if (height > maxH) { width *= maxH / height; height = maxH; } } canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0, width, height); const compressedBase64 = canvas.toDataURL("image/webp", 0.85); if (logoPreview) logoPreview.src = compressedBase64; if (logoPreview) logoPreview.dataset.base64 = compressedBase64; }; img.src = event.target.result; }; reader.readAsDataURL(file); }); } // Cover banner upload if (bannerInput) { bannerInput.addEventListener("change", (e) => { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = (event) => { const img = new Image(); img.onload = () => { const canvas = document.createElement("canvas"); const ctx = canvas.getContext("2d"); const maxW = 800; const maxH = 260; let width = img.width; let height = img.height; if (width > maxW) { height *= maxW / width; width = maxW; } canvas.width = width; canvas.height = height; ctx.drawImage(img, 0, 0, width, height); const compressedBase64 = canvas.toDataURL("image/webp", 0.8); if (bannerPreview) { bannerPreview.src = compressedBase64; bannerPreview.style.display = "block"; bannerPreview.dataset.base64 = compressedBase64; } }; img.src = event.target.result; }; reader.readAsDataURL(file); }); } if (form) { form.addEventListener("submit", (e) => { e.preventDefault(); let user = state.currentUser; if (!user || user.role !== "seller") { const usersList = db.getUsers(); user = usersList.find(u => u.username === "seller1" || u.role === "seller"); } if (!user) return; const storeName = document.getElementById("sellerProfileStoreName").value.trim(); const slogan = document.getElementById("sellerProfileSlogan").value.trim(); const storePhone = document.getElementById("sellerProfilePhone").value.trim(); const storeEmail = document.getElementById("sellerProfileEmail").value.trim(); const sDetail = document.getElementById("sellerAddressDetail") ? document.getElementById("sellerAddressDetail").value.trim() : ""; const sSubdistrict = document.getElementById("sellerSubdistrict") ? document.getElementById("sellerSubdistrict").value.trim() : ""; const sDistrict = document.getElementById("sellerDistrict") ? document.getElementById("sellerDistrict").value.trim() : ""; const sProvince = document.getElementById("sellerProvince") ? document.getElementById("sellerProvince").value.trim() : ""; const sZipcode = document.getElementById("sellerZipcode") ? document.getElementById("sellerZipcode").value.trim() : ""; const sMapUrl = document.getElementById("sellerStoreMapUrl") ? document.getElementById("sellerStoreMapUrl").value.trim() : ""; const fullWarehouseAddr = typeof formatFullAddress === "function" ? formatFullAddress({ detail: sDetail, subdistrict: sSubdistrict, district: sDistrict, province: sProvince, zipcode: sZipcode, mapUrl: sMapUrl }) : `${sDetail} ต.${sSubdistrict} อ.${sDistrict} จ.${sProvince} ${sZipcode}`; const cutoffTime = document.getElementById("sellerCutoffTime").value.trim(); const primaryCarrier = document.getElementById("sellerPrimaryCarrier").value; const warrantyPolicy = document.getElementById("sellerWarrantyPolicy").value.trim(); const bankName = document.getElementById("sellerBankName").value; const bankAccountNo = document.getElementById("sellerBankAccountNo").value.trim(); const bankAccountName = document.getElementById("sellerBankAccountName").value.trim(); const promptpayNo = document.getElementById("sellerPromptPay").value.trim(); const isVacationMode = document.getElementById("sellerVacationMode").checked; const newLogo = logoPreview && logoPreview.dataset.base64 ? logoPreview.dataset.base64 : (user.avatar || ""); const newBanner = bannerPreview && bannerPreview.dataset.base64 ? bannerPreview.dataset.base64 : (user.coverBanner || ""); const users = db.getUsers(); const targetSeller = users.find(u => u.username === user.username); if (targetSeller) { targetSeller.name = storeName; targetSeller.slogan = slogan; targetSeller.storePhone = storePhone; targetSeller.storeEmail = storeEmail; targetSeller.sellerAddressDetail = sDetail; targetSeller.sellerSubdistrict = sSubdistrict; targetSeller.sellerDistrict = sDistrict; targetSeller.sellerProvince = sProvince; targetSeller.sellerZipcode = sZipcode; targetSeller.sellerStoreMapUrl = sMapUrl; targetSeller.storeAddress = fullWarehouseAddr; targetSeller.cutoffTime = cutoffTime; targetSeller.primaryCarrier = primaryCarrier; targetSeller.warrantyPolicy = warrantyPolicy; targetSeller.bankName = bankName; targetSeller.bankAccountNo = bankAccountNo; targetSeller.bankAccountName = bankAccountName; targetSeller.promptpayNo = promptpayNo; targetSeller.isVacationMode = isVacationMode; targetSeller.avatar = newLogo; targetSeller.coverBanner = newBanner; db.saveUsers(users); if (state.currentUser && state.currentUser.username === user.username) { db.setCurrentUser(targetSeller); } showToast("บันทึกการตั้งค่าร้านค้าเรียบร้อยแล้ว", "success"); renderCatalog(); } }); } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.33 | Generation time: 0.26 |
proxy
|
phpinfo
|
Settings