Sửa lỗi UX trong dashboard và privacy của người dùng ở chế độ private
This commit is contained in:
+78
-29
@@ -366,9 +366,9 @@ async function handleRegister() {
|
||||
const data = await response.json();
|
||||
if (!response.ok) throw new Error(data.message || 'Registration failed');
|
||||
|
||||
alert('Registration successful! You can now log in.');
|
||||
showNotification('Registration successful! You can now log in.', 'success');
|
||||
} catch (error) {
|
||||
alert(error.message);
|
||||
showNotification(error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -377,7 +377,10 @@ async function handleRegister() {
|
||||
*/
|
||||
function showLogoutConfirm() {
|
||||
const modal = document.getElementById('logout-confirm-modal');
|
||||
if (modal) modal.style.display = 'flex';
|
||||
if (modal) {
|
||||
closeDashboard(); // Đảm bảo đóng dashboard nếu đang mở
|
||||
modal.style.display = 'flex';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -385,7 +388,11 @@ function showLogoutConfirm() {
|
||||
*/
|
||||
function closeLogoutConfirm() {
|
||||
const modal = document.getElementById('logout-confirm-modal');
|
||||
if (modal) modal.style.display = 'none';
|
||||
if (modal) {
|
||||
modal.style.display = 'none';
|
||||
openDashboard(); // Mở lại dashboard sau khi đóng confirm
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -421,7 +428,7 @@ function openCreateSceneModal(lat, lng) {
|
||||
returnToDashboardAfterEdit = false;
|
||||
const token = localStorage.getItem('jwt');
|
||||
if (!token) {
|
||||
alert('Please log in first to create a 3D scene.');
|
||||
showNotification('Please log in first to create a 3D scene.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -486,7 +493,7 @@ async function submitScene(e) {
|
||||
const method = sceneId ? 'PUT' : 'POST';
|
||||
|
||||
uploadWithProgress(url, method, formData, token, 'create', () => {
|
||||
alert(sceneId ? 'Scene đang được cập nhật ngầm!' : 'Scene đã được tạo! Ảnh đang được xử lý 8K...');
|
||||
showNotification(sceneId ? 'Scene đang được cập nhật ngầm!' : 'Scene đã được tạo! Ảnh đang được xử lý 8K...', 'success');
|
||||
closeModal();
|
||||
loadScenes();
|
||||
});
|
||||
@@ -524,13 +531,13 @@ function uploadWithProgress(url, method, formData, token, prefix, callback) {
|
||||
const err = JSON.parse(xhr.responseText);
|
||||
errorMsg = err.message || errorMsg;
|
||||
} catch (e) {}
|
||||
alert('Lỗi: ' + errorMsg);
|
||||
showNotification('Lỗi: ' + errorMsg, 'error');
|
||||
}
|
||||
});
|
||||
|
||||
xhr.addEventListener('error', () => {
|
||||
if (container) container.style.display = 'none';
|
||||
alert('Lỗi kết nối mạng.');
|
||||
showNotification('Lỗi kết nối mạng.', 'error');
|
||||
});
|
||||
|
||||
xhr.open(method, url);
|
||||
@@ -651,7 +658,7 @@ async function loadScenes() {
|
||||
if (isAdmin || (currentUserId && ownerId && ownerId.toString() === currentUserId.toString())) {
|
||||
handleEditDeleteScene(scene);
|
||||
} else {
|
||||
alert("Bạn không có quyền chỉnh sửa scene này.");
|
||||
showNotification("Bạn không có quyền chỉnh sửa scene này.", 'warning');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -771,7 +778,7 @@ window.confirmDeleteScene = async function() {
|
||||
loadMyScenes();
|
||||
}
|
||||
} catch (error) {
|
||||
alert("Lỗi khi xóa: " + error.message);
|
||||
showNotification("Lỗi khi xóa: " + error.message, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -858,14 +865,14 @@ async function openScene(sceneId, privacy, shareToken, force = false, initialPit
|
||||
// Kiểm tra nếu đang truy cập qua link trực tiếp (URL có sceneId) mà gặp lỗi (do xóa token hoặc token không hợp lệ)
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
if (urlParams.has('sceneId')) {
|
||||
alert("Bạn không có quyền truy cập hoặc liên kết chia sẻ đã hết hạn. Quay về bản đồ công cộng.");
|
||||
showNotification("Bạn không có quyền truy cập hoặc liên kết chia sẻ đã hết hạn. Quay về bản đồ công cộng.", 'error');
|
||||
// Xóa toàn bộ tham số URL và tải lại trang để làm mới trạng thái (về trang chủ dành cho khách)
|
||||
window.history.replaceState({}, document.title, window.location.pathname);
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
|
||||
alert(error.message);
|
||||
showNotification(error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -892,7 +899,7 @@ function restoreActiveScene() {
|
||||
window.handleHotspotCreation = async function(pitch, yaw, existingHotspot = null) {
|
||||
const token = localStorage.getItem('jwt');
|
||||
if (!token) {
|
||||
alert('Vui lòng đăng nhập để thực hiện thao tác này.');
|
||||
showNotification('Vui lòng đăng nhập để thực hiện thao tác này.', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -946,7 +953,7 @@ window.handleHotspotCreation = async function(pitch, yaw, existingHotspot = null
|
||||
if (linkType === 'upload') {
|
||||
const file = document.getElementById('hs-panorama-file').files[0];
|
||||
if (!file) {
|
||||
alert('Vui lòng chọn ảnh panorama.');
|
||||
showNotification('Vui lòng chọn ảnh panorama.', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -961,7 +968,7 @@ window.handleHotspotCreation = async function(pitch, yaw, existingHotspot = null
|
||||
lat = Number(document.getElementById('hs-lat').value);
|
||||
lng = Number(document.getElementById('hs-lng').value);
|
||||
if (!lat || !lng) {
|
||||
alert('Vui lòng chọn vị trí GPS.');
|
||||
showNotification('Vui lòng chọn vị trí GPS.', 'warning');
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -982,7 +989,7 @@ window.handleHotspotCreation = async function(pitch, yaw, existingHotspot = null
|
||||
|
||||
const finalTargetId = formData.get('targetSceneId');
|
||||
if (!finalTargetId) {
|
||||
alert('Vui lòng chọn cảnh để liên kết.');
|
||||
showNotification('Vui lòng chọn cảnh để liên kết.', 'warning');
|
||||
return;
|
||||
}
|
||||
await saveHotspotToDB(pitch, yaw, formData.get('title'), formData.get('description'), finalTargetId, existingHotspot?._id);
|
||||
@@ -1105,13 +1112,13 @@ async function saveHotspotToDB(pitch, yaw, title, description, targetSceneId, ho
|
||||
const data = await response.json();
|
||||
if (!response.ok) throw new Error(data.message || 'Lỗi khi lưu hotspot');
|
||||
|
||||
alert('Lưu điểm điều hướng thành công!');
|
||||
showNotification('Lưu điểm điều hướng thành công!', 'success');
|
||||
// Buộc nạp lại để cập nhật danh sách hotspot mới
|
||||
openScene(currentSceneId, localStorage.getItem('activeScenePrivacy'), localStorage.getItem('activeSceneToken'), true);
|
||||
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
alert(error.message);
|
||||
showNotification(error.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1132,13 +1139,13 @@ window.systemReset = async function() {
|
||||
|
||||
if (response.ok) {
|
||||
localStorage.clear(); // Xóa sạch token, vị trí map, active scene
|
||||
alert(data.message);
|
||||
showNotification(data.message, 'success');
|
||||
location.reload();
|
||||
} else {
|
||||
throw new Error(data.message);
|
||||
}
|
||||
} catch (e) {
|
||||
alert("Lỗi reset: " + e.message);
|
||||
showNotification("Lỗi reset: " + e.message, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1191,11 +1198,11 @@ async function deleteHotspot(hotspotId) {
|
||||
throw new Error(err.message || 'Lỗi xóa hotspot');
|
||||
}
|
||||
|
||||
alert('Đã xóa điểm điều hướng.');
|
||||
showNotification('Đã xóa điểm điều hướng.', 'success');
|
||||
// Refresh lại scene hiện tại để cập nhật viewer
|
||||
openScene(currentSceneId, null, null, true);
|
||||
} catch (e) {
|
||||
alert(e.message);
|
||||
showNotification(e.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1415,22 +1422,24 @@ window.confirmDeleteAsset = async function() {
|
||||
}
|
||||
|
||||
closeDeleteAssetModal();
|
||||
showSuccessModal(data.message || "Đã xóa thành công");
|
||||
showNotification(data.message || "Đã xóa thành công", 'success');
|
||||
loadMyAssets(); // Nạp lại kho ảnh
|
||||
loadScenes(); // Nạp lại bản đồ nếu có scene bị xóa kèm theo
|
||||
} catch (e) {
|
||||
alert("Lỗi khi xóa: " + e.message);
|
||||
showNotification("Lỗi khi xóa: " + e.message, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Hiển thị Modal thông báo thành công
|
||||
*/
|
||||
window.showSuccessModal = function(message) {
|
||||
window.showSuccessModal = function(message, icon = '✓') {
|
||||
const modal = document.getElementById('success-modal');
|
||||
const msgElem = document.getElementById('success-modal-message');
|
||||
if (modal && msgElem) {
|
||||
const iconElem = document.getElementById('success-modal-icon');
|
||||
if (modal && msgElem && iconElem) {
|
||||
msgElem.innerText = message;
|
||||
iconElem.innerText = icon;
|
||||
modal.style.display = 'flex';
|
||||
// Tự động ẩn sau 3 giây
|
||||
setTimeout(() => closeSuccessModal(), 3000);
|
||||
@@ -1448,9 +1457,49 @@ window.closeSuccessModal = function(e) {
|
||||
modal.style.display = 'none';
|
||||
};
|
||||
|
||||
/**
|
||||
* Hiển thị Modal thông báo lỗi hoặc cảnh báo
|
||||
*/
|
||||
window.showErrorModal = function(message, title = "Thông báo", icon = '⚠️') {
|
||||
const modal = document.getElementById('error-modal');
|
||||
const msgElem = document.getElementById('error-modal-message');
|
||||
const titleElem = document.getElementById('error-modal-title');
|
||||
const iconElem = document.getElementById('error-modal-icon');
|
||||
if (modal && msgElem && iconElem) {
|
||||
msgElem.innerText = message;
|
||||
iconElem.innerText = icon;
|
||||
if (titleElem) titleElem.innerText = title;
|
||||
modal.style.display = 'flex';
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Đóng Modal lỗi (hỗ trợ click ra ngoài)
|
||||
*/
|
||||
window.closeErrorModal = function(e) {
|
||||
const modal = document.getElementById('error-modal');
|
||||
if (!modal) return;
|
||||
// Nếu nhấn từ code (không có e) hoặc click trúng overlay thì đóng
|
||||
if (e && e.target !== modal) return;
|
||||
modal.style.display = 'none';
|
||||
};
|
||||
|
||||
/**
|
||||
* Hàm thông báo dùng chung thay thế alert()
|
||||
*/
|
||||
window.showNotification = function(message, type = 'success') {
|
||||
if (type === 'success') {
|
||||
showSuccessModal(message, '✓');
|
||||
} else if (type === 'warning') {
|
||||
showErrorModal(message, 'Cảnh báo', '⚠️');
|
||||
} else {
|
||||
showErrorModal(message, 'Lỗi', '❌');
|
||||
}
|
||||
};
|
||||
|
||||
window.openEditFromMedia = function(scene, isChild = false) {
|
||||
if (!scene || !scene._id) {
|
||||
alert("Không thể chỉnh sửa: Ảnh này không được gắn với một Scene hợp lệ.");
|
||||
showNotification("Không thể chỉnh sửa: Ảnh này không được gắn với một Scene hợp lệ.", 'error');
|
||||
return;
|
||||
}
|
||||
dashboardReturnTab = 'media-library';
|
||||
@@ -1679,11 +1728,11 @@ async function submitEditScene(e) {
|
||||
const data = await res.json();
|
||||
if (!res.ok) throw new Error(data.message);
|
||||
|
||||
showSuccessModal("Đã cập nhật thông tin cảnh thành công!");
|
||||
showNotification("Đã cập nhật thông tin cảnh thành công!", 'success');
|
||||
closeEditMetadataModal();
|
||||
loadScenes();
|
||||
} catch (err) {
|
||||
alert("Lỗi cập nhật: " + err.message);
|
||||
showNotification("Lỗi cập nhật: " + err.message, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user