feat: bổ sung phần profile của user

This commit is contained in:
2026-07-22 18:55:25 +07:00
parent c4302da931
commit 0155abd0da
3 changed files with 103 additions and 24 deletions
+27
View File
@@ -6,6 +6,7 @@ from fastapi import APIRouter, UploadFile, File, HTTPException, Query, Depends
from fastapi.responses import FileResponse
from pydantic import BaseModel
from typing import Optional, List
import json
from app.config import settings
from app.api.v1.auth import get_current_user
from app.api.v1.projects import get_optional_user
@@ -68,6 +69,15 @@ async def upload_audio(file: UploadFile = File(...), current_user: Optional[dict
content = await file.read()
f.write(content)
# Save original filename as sidecar metadata
import json
meta_path = os.path.join(settings.UPLOADS_DIR, file_id + ".meta")
try:
with open(meta_path, "w") as mf:
json.dump({"original_name": file.filename}, mf)
except Exception:
pass
# Trigger celery task
from app.tasks.worker import analyze_audio_task
task = analyze_audio_task.delay(file_id)
@@ -357,8 +367,18 @@ async def list_user_files(req: MyFilesRequest, current_user: dict = Depends(get_
if filename in files_map:
files_map[filename]["size_mb"] = round(files_map[filename]["size_mb"] + stat.st_size / (1024 * 1024), 2)
else:
original_name = filename
meta_path = os.path.join(directory, filename + ".meta")
if os.path.isfile(meta_path):
try:
with open(meta_path, "r") as mf:
meta = json.load(mf)
original_name = meta.get("original_name", filename)
except Exception:
pass
files_map[filename] = {
"file_id": filename,
"original_name": original_name,
"size_mb": round(stat.st_size / (1024 * 1024), 2),
"created_at": stat.st_mtime,
"type": type_label,
@@ -390,6 +410,13 @@ async def delete_user_file(file_id: str, current_user: dict = Depends(get_curren
deleted = True
except Exception:
pass
# Clean up sidecar metadata file
meta_path = os.path.join(directory, file_id + ".meta")
if os.path.isfile(meta_path):
try:
os.remove(meta_path)
except Exception:
pass
if not deleted:
raise HTTPException(status_code=404, detail="Không tìm thấy tệp trên server")
+27 -3
View File
@@ -2752,6 +2752,9 @@ const ProfileModal = ({
const [filesList, setFilesList] = useState([]);
const [loadingFiles, setLoadingFiles] = useState(false);
// Confirmation modal state
const [confirmModal, setConfirmModal] = useState(null);
useEffect(() => {
if (isOpen) {
fetchProfile();
@@ -2821,7 +2824,10 @@ const ProfileModal = ({
const handleDeleteProject = async (projectId, e) => {
e.stopPropagation();
if (!confirm("Bạn có chắc chắn muốn xóa dự án này khỏi Cloud?")) return;
setConfirmModal({
title: "Xóa dự án Cloud",
message: "Bạn có chắc chắn muốn xóa dự án này khỏi Cloud? Hành động này không thể hoàn tác.",
onConfirm: async () => {
try {
await window.SonicAPI.deleteCloudProject(projectId);
showToast("Đã xóa dự án thành công!", "success");
@@ -2830,6 +2836,8 @@ const ProfileModal = ({
} catch (err) {
showToast(err.message || "Lỗi khi xóa dự án", "error");
}
}
});
};
const handleDeleteFile = async (fileId) => {
@@ -2883,8 +2891,24 @@ const ProfileModal = ({
};
return /*#__PURE__*/React.createElement("div", {
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"
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"
}, /*#__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", {
className: "text-sm font-bold text-rose-400 mb-2"
}, confirmModal.title), /*#__PURE__*/React.createElement("p", {
className: "text-xs text-slate-300 mb-4"
}, confirmModal.message), /*#__PURE__*/React.createElement("div", {
className: "flex justify-end gap-2"
}, /*#__PURE__*/React.createElement("button", {
onClick: () => setConfirmModal(null),
className: "px-3 py-1.5 bg-zinc-700 hover:bg-zinc-600 text-slate-300 rounded text-xs font-semibold"
}, "Hủy"), /*#__PURE__*/React.createElement("button", {
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]"
}, /*#__PURE__*/React.createElement("div", {
className: "flex justify-between items-center pb-3 border-b border-[#383838] shrink-0"
@@ -3024,7 +3048,7 @@ const ProfileModal = ({
className: "flex items-center justify-between p-3 bg-[#1e1e1e] rounded border border-zinc-800 text-xs"
}, [
/*#__PURE__*/React.createElement("div", { key: "meta", className: "max-w-[70%]" }, [
/*#__PURE__*/React.createElement("div", { className: "font-mono font-semibold text-slate-300 truncate" }, file.file_id.replace(/^user_[^_]+_/, '')),
/*#__PURE__*/React.createElement("div", { className: "font-semibold text-slate-300 truncate" }, file.original_name || file.file_id),
/*#__PURE__*/React.createElement("div", { className: "text-[10px] text-zinc-500 mt-0.5" }, `Loại: ${file.type} | Dung lượng: ${file.size_mb} MB | Tạo lúc: ${new Date(file.created_at * 1000).toLocaleString()}`)
]),
/*#__PURE__*/React.createElement("div", { key: "actions", className: "flex items-center gap-2" }, [
+32 -4
View File
@@ -2788,6 +2788,9 @@ const ProfileModal = ({
// Files list state
const [filesList, setFilesList] = useState([]);
const [loadingFiles, setLoadingFiles] = useState(false);
// Confirmation modal state
const [confirmModal, setConfirmModal] = useState(null);
useEffect(() => {
if (isOpen) {
fetchProfile();
@@ -2852,7 +2855,10 @@ const ProfileModal = ({
};
const handleDeleteProject = async (projectId, e) => {
e.stopPropagation();
if (!confirm("Bạn có chắc chắn muốn xóa dự án này khỏi Cloud?")) return;
setConfirmModal({
title: "Xóa dự án Cloud",
message: "Bạn có chắc chắn muốn xóa dự án này khỏi Cloud? Hành động này không thể hoàn tác.",
onConfirm: async () => {
try {
await window.SonicAPI.deleteCloudProject(projectId);
showToast("Đã xóa dự án thành công!", "success");
@@ -2861,6 +2867,8 @@ const ProfileModal = ({
} catch (err) {
showToast(err.message || "Lỗi khi xóa dự án", "error");
}
}
});
};
const handleDeleteFile = async fileId => {
if (!confirm(`Bạn có chắc chắn muốn xóa tệp tin ${fileId}?`)) return;
@@ -2910,8 +2918,28 @@ const ProfileModal = ({
}
};
return /*#__PURE__*/React.createElement("div", {
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"
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"
}, /*#__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", {
className: "text-sm font-bold text-rose-400 mb-2"
}, confirmModal.title), /*#__PURE__*/React.createElement("p", {
className: "text-xs text-slate-300 mb-4"
}, confirmModal.message), /*#__PURE__*/React.createElement("div", {
className: "flex justify-end gap-2"
}, /*#__PURE__*/React.createElement("button", {
onClick: () => setConfirmModal(null),
className: "px-3 py-1.5 bg-zinc-700 hover:bg-zinc-600 text-slate-300 rounded text-xs font-semibold"
}, "Hủy"), /*#__PURE__*/React.createElement("button", {
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]"
}, /*#__PURE__*/React.createElement("div", {
className: "flex justify-between items-center pb-3 border-b border-[#383838] shrink-0"
@@ -3067,8 +3095,8 @@ const ProfileModal = ({
key: "meta",
className: "max-w-[70%]"
}, [/*#__PURE__*/React.createElement("div", {
className: "font-mono font-semibold text-slate-300 truncate"
}, file.file_id.replace(/^user_[^_]+_/, '')), /*#__PURE__*/React.createElement("div", {
className: "font-semibold text-slate-300 truncate"
}, file.original_name || file.file_id), /*#__PURE__*/React.createElement("div", {
className: "text-[10px] text-zinc-500 mt-0.5"
}, `Loại: ${file.type} | Dung lượng: ${file.size_mb} MB | Tạo lúc: ${new Date(file.created_at * 1000).toLocaleString()}`)]), /*#__PURE__*/React.createElement("div", {
key: "actions",