const rootPopupMasterElement = document.getElementById("root_popup_master"); const rootMaster = ReactDOM.createRoot(rootPopupMasterElement); //alert(_token_encode); const PopupMasterComponent=()=>{ return( ) } rootMaster.render(, rootPopupMasterElement); const PopupMaster=()=>{ const [show, setShow] = useState(false) const [actionForm, setActionForm] = useState() window.addEventListener('message', (event) => { const targetOrigin = event.origin; if (window.location.origin.startsWith(targetOrigin)) { //setUserInfo(event.data) let data_received =event.data if(data_received.action=="campaign"){ setActionForm(data_received.action) setShow(true) } } }); if (actionForm==null){ return( <> ) }else return( <> { actionForm=='campaign' && } ) } const MasterInfo=()=>{ const {ButtonGroup,Dropdown,Badge ,DropdownButton, Alert } = ReactBootstrap let config = null const user_lang = commonFunc.getCookies('user_lang') || 'vi' try { config = { token: _token_encode } }catch (e) { config = { token: '' } } const [userInfo, setUserInfo] = useState() const [loading, setLoading] = useState(false) const [showPopUpChangePassword, setShowPopUpChangePassword] = useState(false) const [showPopUpUserInfo, setShowPopUpUserInfo] = useState(false) const [viewCount, setViewCount] = useState(0) const dropdownStyle = { backgroundColor: 'transparent', border: 'none', color:'red', }; const [actionMessages, setActionMessage] = useState([]) const fetchUserInfo = async () => { setLoading(true); try { const url = '/api/get-user-by-token'; const data = { token:config?.token }; // Thêm số trang và kích thước trang vào dữ liệu const resultObj = await commonApi.APIPOSTByURL(url, data, config); setLoading(false); if (resultObj.status === 200) { setUserInfo(resultObj.data); var logo=resultObj?.data?.user_company?.logo // Cập nhật icon logo bằng logo (base64) const link = document.querySelector("link[rel*='icon']"); if (link && logo) { link.href = `${logo}`; // Thay đổi kiểu nếu cần } // Cập nhật title công ty const companyName = resultObj.data.user_company.name; const titleLink = document.getElementById("title_company"); if (titleLink && companyName && titleLink.textContent=='') { titleLink.textContent = companyName; // Cập nhật nội dung của thẻ title } const titleCompany = document.getElementById("_short_name_company"); if (titleCompany && companyName) { titleCompany.textContent = companyName; // Cập nhật nội dung của thẻ title } const logoCompany = document.getElementById("_logo_company"); if (logoCompany && logo) { logoCompany.src = `${logo}`; // Thay đổi kiểu nếu cần } const copyRight = document.getElementById("_copy_right"); if (copyRight) { const legalName = resultObj.data.user_company.legal_name; if(legalName) copyRight.textContent = legalName; } } else { console.log("Unexpected response status:", resultObj.status); } } catch (e) { setLoading(false); console.log("ERROR get-user-by-token", e); } }; const fetchMessages = async () => { if (config?.token=='') return; setLoading(true); try { const url = '/api/get-messages'; const data = { token:config?.token }; // Thêm số trang và kích thước trang vào dữ liệu const resultObj = await commonApi.APIPOSTByURL(url, data, config); setLoading(false); if (resultObj.status === 200) { setActionMessage(resultObj.data); } else { console.log("Unexpected response status:", resultObj.status); } } catch (e) { setLoading(false); console.log("ERROR get-message", e); } }; const updateMessages = async (id, path) => { setLoading(true); try { const url = '/api/update-message'; const data = { message_id:id }; // Thêm số trang và kích thước trang vào dữ liệu const resultObj = await commonApi.APIPUTByURL(url, data, config); setLoading(false); if (resultObj.status === 201) { console.log("Unexpected response status:", resultObj.status); window.location.href = `${path}/&goto_message=${id}`; } else { console.log("Unexpected response status:", resultObj.status); } } catch (e) { setLoading(false); console.log("ERROR update-message", e); } }; useEffect(()=>{ fetchUserInfo() // Set up an interval to fetch messages every 30 seconds const intervalId = setInterval(() => { fetchMessages(); }, 50000); // 30 seconds in milliseconds // Cleanup function to clear the interval on component unmount return () => clearInterval(intervalId); },[]) useEffect(()=>{ if (!userInfo || actionMessages.length==0) return; const count = actionMessages.reduce((acc, curr) => { const hasSuperAdmin = curr.users_viewed.some(u => u.username === userInfo?.username); return hasSuperAdmin ? acc : acc + 1; }, 0); setViewCount(count) if (userInfo?.internal_user==true){ let elm = document.getElementById('menuButton') if (elm){ //elm.style.display = ''; } } },[userInfo, actionMessages]) const showFormChangePassword=()=>{ setShowPopUpChangePassword(true) } const showFormUserInfo=()=>{ setShowPopUpUserInfo(true) } if (config?.token==''){ return( <> ) } const gotoMessage=(path, id)=>{ if (path && id) { updateMessages(id, path); } else { console.error("Path or ID is missing"); } } const handleChangeLanguage=(lang)=>{ document.cookie = `user_lang=${lang}; path=/`; window.location.reload(); // Tải lại trang để áp dụng ngôn ngữ mới } const handleManageOrder=()=>{ const isCashier = userInfo?.internal_user || false if (isCashier){ window.location.href = '/mdc/transactions?type=internal'; }else{ window.location.href = '/mdc/transactions?type=external'; } } return ( <> {/* Scoped styles for base navbar components */} {actionMessages?.length > 0 && ( {viewCount > 0 && ( {viewCount} )}
{user_lang === 'en' ? 'NOTIFICATIONS' : 'THÔNG BÁO'}
{actionMessages.map((alert, index) => ( gotoMessage(alert?.path, alert?.id)} className="p-0 mb-1 border-0 bg-transparent"> {alert.message} ))}
)} {/* User Account Dropdown */} {userInfo ? ( userInfo.avatar ? ( user-avatar ) : ( ) ) : ( )} {window.innerWidth > 768 && ( {userInfo?.name || (user_lang === 'en' ? 'Guest' : 'Khách')} )} {(userInfo != null && userInfo?.username !== 'guest') ? ( <> {user_lang === 'en' ? "Edit Profile" : "Sửa thông tin"} {user_lang === 'en' ? "Change Password" : "Đổi mật khẩu"}
handleChangeLanguage(user_lang === 'vi' ? 'en' : 'vi')} className="base-dropdown-item">
{user_lang === 'en' ? "Language: English" : "Ngôn ngữ: Tiếng Việt"} flag
{user_lang === 'en' ? "Orders" : "Đơn hàng"}
{user_lang === 'en' ? "Logout" : "Đăng xuất"} ) : ( <> handleChangeLanguage(user_lang === 'vi' ? 'en' : 'vi')} className="base-dropdown-item"> {user_lang === 'en' ? "Switch to Vietnamese" : "Chuyển sang Tiếng Anh"}
{user_lang === 'en' ? "Login" : "Đăng nhập"} )} {/* Shopping Basket (Hidden by default) */}
0
{/* Popups */} ); } const PopUpChangeUserPassword=(props)=>{ const {show, setShow} = props const user_lang = commonFunc.getCookies('user_lang') || 'vi' return( <> ) } const ChangeUserPassword=(props)=>{ const { Form, Alert } = ReactBootstrap const [currentPassword, setCurrentPassword] = useState(''); const [newPassword, setNewPassword] = useState(''); const [confirmPassword, setConfirmPassword] = useState(''); const [error, setError] = useState(''); const [success, setSuccess] = useState(''); const config = { token: _token_encode } const [loading, setLoading] = useState(false) const user_lang = commonFunc.getCookies('user_lang') || 'vi' const handleSubmit = (e) => { e.preventDefault(); setError(''); setSuccess(''); if (newPassword !== confirmPassword) { setError('Mật khẩu mới và xác nhận mật khẩu không khớp.'); return; } handleChangePassword() // Xử lý đổi mật khẩu ở đây (gọi API, v.v.) }; const handleChangePassword=async()=>{ try { setLoading(true); const data = { "current_password": currentPassword, "new_password":newPassword, } const changePasswordAPI = await commonApi.APIPUTByURL('/api/change-password', data, config); if (changePasswordAPI) { if (changePasswordAPI?.status==201) { const data = changePasswordAPI.data if (data.status=='success') { setSuccess(data.message); }else{ setError(data.message); } } else { setError('Không có phản hồi từ server.') } }else{ setError('Không có phản hồi từ server.'); } } catch (e) { console.error("Error: " + e.message); setError(e.message || 'Đã xảy ra lỗi không xác định.'); } finally { setLoading(false); } } return (
{error && {error}} {success && {success}} {user_lang=='en'?"Current Password":"Mật khẩu hiện tại" } setCurrentPassword(e.target.value)} className="base-form-control" required /> {user_lang=='en'?"New Password":"Mật khẩu mới" } setNewPassword(e.target.value)} className="base-form-control" required /> {user_lang=='en'?"Confirm New Password":"Nhập lại mật khẩu mới" } setConfirmPassword(e.target.value)} className="base-form-control" required />
); }; const PopUpChangeUserInfo= (props)=>{ const {show, setShow, userInfo} = props const company=userInfo?.company_id const user_lang = commonFunc.getCookies('user_lang') || 'vi' // AuthUserForm load from /static/components/admin/permission/user.jsx const [components, setComponents] = useState(null); useEffect(() => { // Chỉ nạp khi Popup được mở if (show && !components) { async function startApp() { const fcomponents = await LoadMultipleComponents([ `/static/components/admin/permission/user.${_extension}?v=${typeof _version !== 'undefined' ? _version + '_v3' : Date.now()}` ]); // Vì file trả về { CMSUsers, AuthUserForm } // Hàm loader của bạn sẽ trả về { user: { CMSUsers, AuthUserForm } } if (fcomponents) { setComponents(fcomponents); } } startApp(); } }, [show]); // Chạy lại khi trạng thái show thay đổi if (components?.user?.AuthUserForm==null){ return(<>) } return( <> ) } class ErrorBoundary extends React.Component { constructor(props) { super(props); this.state = { hasError: false, error: null, // Thêm state để lưu đối tượng lỗi errorInfo: null // Thêm state để lưu thông tin lỗi }; } // 1. Phương thức này được gọi khi lỗi xảy ra static getDerivedStateFromError(error) { // Cập nhật state để lần render tiếp theo sẽ hiển thị fallback UI. // LƯU Ý: Không thể truy cập 'error' ở đây, chỉ có thể trả về 'hasError: true'. return { hasError: true }; } // 2. Phương thức này được gọi sau khi lỗi xảy ra componentDidCatch(error, errorInfo) { // Ghi lại thông tin lỗi vào console console.error("ErrorBoundary caught an error:", error, errorInfo); // Cập nhật state để lưu chi tiết lỗi và errorInfo this.setState({ error: error, errorInfo: errorInfo }); // Ví dụ: logErrorToMyService(error, errorInfo); } render() { if (this.state.hasError) { // Khi có lỗi, hiển thị chi tiết lỗi và stack trace return (

⚠️ Đã xảy ra lỗi không mong muốn!

Xin lỗi, component này đã gặp sự cố. Chi tiết kỹ thuật:

{/* Hiển thị thông báo lỗi chính */}
{this.state.error && this.state.error.toString()} {/* Hiển thị stack trace của component bị lỗi */} {this.state.errorInfo && (
                {this.state.errorInfo.componentStack}
              
)}

Vui lòng liên hệ bộ phận hỗ trợ nếu vấn đề này vẫn tiếp diễn.

); } // Nếu không có lỗi, hiển thị các component con bình thường return this.props.children; } }