feat: bổ sung phần profile của user có thể drag

This commit is contained in:
2026-07-22 19:43:04 +07:00
parent 0155abd0da
commit f3d48e8837
3 changed files with 93 additions and 16 deletions
+41 -8
View File
@@ -2743,6 +2743,8 @@ const ProfileModal = ({
const [msg, setMsg] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const [dragOfs, setDragOfs] = useState({ x: 0, y: 0 });
const dragRef = useRef({ active: false, startX: 0, startY: 0, ofsX: 0, ofsY: 0 });
// Projects list state
const [projectsList, setProjectsList] = useState([]);
@@ -2755,6 +2757,26 @@ const ProfileModal = ({
// Confirmation modal state
const [confirmModal, setConfirmModal] = useState(null);
const handleDragStart = (e) => {
const r = dragRef.current;
r.active = true;
r.startX = e.clientX;
r.startY = e.clientY;
r.ofsX = dragOfs.x;
r.ofsY = dragOfs.y;
const onMove = (ev) => {
if (!r.active) return;
setDragOfs({ x: r.ofsX + ev.clientX - r.startX, y: r.ofsY + ev.clientY - r.startY });
};
const onUp = () => {
r.active = false;
document.removeEventListener('mousemove', onMove);
document.removeEventListener('mouseup', onUp);
};
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
};
useEffect(() => {
if (isOpen) {
fetchProfile();
@@ -2890,10 +2912,18 @@ const ProfileModal = ({
}
};
return /*#__PURE__*/React.createElement("div", {
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm relative"
}, confirmModal && /*#__PURE__*/React.createElement("div", {
className: "absolute inset-0 z-[60] flex items-center justify-center bg-black/50"
const modalStyle = {
left: `calc(50% + ${dragOfs.x}px)`,
top: `calc(50% + ${dragOfs.y}px)`,
transform: 'translate(-50%, -50%)'
};
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
key: "backdrop",
className: "fixed inset-0 z-40 bg-black/70 backdrop-blur-sm",
onClick: onClose
}), confirmModal && /*#__PURE__*/React.createElement("div", {
key: "confirm-overlay",
className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/50"
}, /*#__PURE__*/React.createElement("div", {
className: "bg-[#262626] border border-[#383838] rounded-lg shadow-2xl p-5 max-w-sm w-full text-slate-200"
}, /*#__PURE__*/React.createElement("h4", {
@@ -2909,9 +2939,12 @@ const ProfileModal = ({
onClick: () => { const fn = confirmModal.onConfirm; setConfirmModal(null); fn(); },
className: "px-3 py-1.5 bg-rose-700 hover:bg-rose-600 text-white rounded text-xs font-semibold"
}, "Xác nhận xóa")))), /*#__PURE__*/React.createElement("div", {
className: "bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200 flex flex-col max-h-[85vh]"
key: "dialog",
className: "fixed z-50 bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200 flex flex-col max-h-[85vh]",
style: modalStyle
}, /*#__PURE__*/React.createElement("div", {
className: "flex justify-between items-center pb-3 border-b border-[#383838] shrink-0"
className: "flex justify-between items-center pb-3 border-b border-[#383838] shrink-0 cursor-grab active:cursor-grabbing select-none",
onMouseDown: handleDragStart
}, /*#__PURE__*/React.createElement("h3", {
className: "text-md font-bold text-teal-400 flex items-center gap-1.5"
}, "👤 Hồ Sơ Cá Nhân & Quản Lý Dự Án"), /*#__PURE__*/React.createElement("button", {
@@ -8514,7 +8547,7 @@ const App = () => {
}, [showAIPanel, showExportPanel, showSelectionPanel, showPythonToolsPanel,
showMediaExplorer, showFxRack, showMidiEvents, panelPositions,
rightSidebarWidth, mediaExplorerHeight, selectedProviderId, currentUser]);
return /*#__PURE__*/React.createElement("div", {
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
className: "h-full w-full flex flex-col bg-[#1e1e1e]"
}, /*#__PURE__*/React.createElement("header", {
className: "h-9 bg-[#2e2e2e] border-b border-[#181818] flex items-center px-1 shrink-0 select-none"
@@ -10982,7 +11015,7 @@ const App = () => {
setToastMessage(null);
},
className: "ml-2 px-2 py-0.5 bg-purple-700 hover:bg-purple-600 text-white rounded text-[10px] uppercase font-bold"
}, toastMessage.actionText || 'Tải về')), /*#__PURE__*/React.createElement(AuthModal, {
}, toastMessage.actionText || 'Tải về'))), /*#__PURE__*/React.createElement(AuthModal, {
isOpen: authModalOpen,
mode: authMode,
forceMandatory: isMandatoryLogin,
+52 -8
View File
@@ -2780,6 +2780,17 @@ const ProfileModal = ({
const [msg, setMsg] = useState('');
const [error, setError] = useState('');
const [loading, setLoading] = useState(false);
const [dragOfs, setDragOfs] = useState({
x: 0,
y: 0
});
const dragRef = useRef({
active: false,
startX: 0,
startY: 0,
ofsX: 0,
ofsY: 0
});
// Projects list state
const [projectsList, setProjectsList] = useState([]);
@@ -2791,6 +2802,28 @@ const ProfileModal = ({
// Confirmation modal state
const [confirmModal, setConfirmModal] = useState(null);
const handleDragStart = e => {
const r = dragRef.current;
r.active = true;
r.startX = e.clientX;
r.startY = e.clientY;
r.ofsX = dragOfs.x;
r.ofsY = dragOfs.y;
const onMove = ev => {
if (!r.active) return;
setDragOfs({
x: r.ofsX + ev.clientX - r.startX,
y: r.ofsY + ev.clientY - r.startY
});
};
const onUp = () => {
r.active = false;
document.removeEventListener('mousemove', onMove);
document.removeEventListener('mouseup', onUp);
};
document.addEventListener('mousemove', onMove);
document.addEventListener('mouseup', onUp);
};
useEffect(() => {
if (isOpen) {
fetchProfile();
@@ -2917,10 +2950,18 @@ const ProfileModal = ({
setLoading(false);
}
};
return /*#__PURE__*/React.createElement("div", {
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm relative"
}, confirmModal && /*#__PURE__*/React.createElement("div", {
className: "absolute inset-0 z-[60] flex items-center justify-center bg-black/50"
const modalStyle = {
left: `calc(50% + ${dragOfs.x}px)`,
top: `calc(50% + ${dragOfs.y}px)`,
transform: 'translate(-50%, -50%)'
};
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
key: "backdrop",
className: "fixed inset-0 z-40 bg-black/70 backdrop-blur-sm",
onClick: onClose
}), confirmModal && /*#__PURE__*/React.createElement("div", {
key: "confirm-overlay",
className: "fixed inset-0 z-[60] flex items-center justify-center bg-black/50"
}, /*#__PURE__*/React.createElement("div", {
className: "bg-[#262626] border border-[#383838] rounded-lg shadow-2xl p-5 max-w-sm w-full text-slate-200"
}, /*#__PURE__*/React.createElement("h4", {
@@ -2940,9 +2981,12 @@ const ProfileModal = ({
},
className: "px-3 py-1.5 bg-rose-700 hover:bg-rose-600 text-white rounded text-xs font-semibold"
}, "Xác nhận xóa")))), /*#__PURE__*/React.createElement("div", {
className: "bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200 flex flex-col max-h-[85vh]"
key: "dialog",
className: "fixed z-50 bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200 flex flex-col max-h-[85vh]",
style: modalStyle
}, /*#__PURE__*/React.createElement("div", {
className: "flex justify-between items-center pb-3 border-b border-[#383838] shrink-0"
className: "flex justify-between items-center pb-3 border-b border-[#383838] shrink-0 cursor-grab active:cursor-grabbing select-none",
onMouseDown: handleDragStart
}, /*#__PURE__*/React.createElement("h3", {
className: "text-md font-bold text-teal-400 flex items-center gap-1.5"
}, "👤 Hồ Sơ Cá Nhân & Quản Lý Dự Án"), /*#__PURE__*/React.createElement("button", {
@@ -8994,7 +9038,7 @@ const App = () => {
}, 2000);
return () => clearTimeout(timer);
}, [showAIPanel, showExportPanel, showSelectionPanel, showPythonToolsPanel, showMediaExplorer, showFxRack, showMidiEvents, panelPositions, rightSidebarWidth, mediaExplorerHeight, selectedProviderId, currentUser]);
return /*#__PURE__*/React.createElement("div", {
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
className: "h-full w-full flex flex-col bg-[#1e1e1e]"
}, /*#__PURE__*/React.createElement("header", {
className: "h-9 bg-[#2e2e2e] border-b border-[#181818] flex items-center px-1 shrink-0 select-none"
@@ -11530,7 +11574,7 @@ const App = () => {
setToastMessage(null);
},
className: "ml-2 px-2 py-0.5 bg-purple-700 hover:bg-purple-600 text-white rounded text-[10px] uppercase font-bold"
}, toastMessage.actionText || 'Tải về')), /*#__PURE__*/React.createElement(AuthModal, {
}, toastMessage.actionText || 'Tải về'))), /*#__PURE__*/React.createElement(AuthModal, {
isOpen: authModalOpen,
mode: authMode,
forceMandatory: isMandatoryLogin,