Commit 4a0686d2 authored by Lê Bảo Hồng Đức's avatar Lê Bảo Hồng Đức

[tag]0.1-vcci

parents c01bc430 0a8e85f9
Pipeline #52801 passed with stages
in 4 minutes and 45 seconds
...@@ -26,6 +26,7 @@ import logo from "@/assets/VCCI-HCM-logo-VN-2025.png"; ...@@ -26,6 +26,7 @@ import logo from "@/assets/VCCI-HCM-logo-VN-2025.png";
import links, { resolveUploadUrl } from "@/links"; import links, { resolveUploadUrl } from "@/links";
import { loginAdmin } from "@/lib/auth/admin-auth"; import { loginAdmin } from "@/lib/auth/admin-auth";
import useAuthStore from "@/store/useAuthStore"; import useAuthStore from "@/store/useAuthStore";
import { fetchCmsFileById, resolveCmsFileUrl } from "@/lib/api/files";
type AuthMode = "login" | "forgot"; type AuthMode = "login" | "forgot";
...@@ -120,6 +121,19 @@ function AuthShell({ ...@@ -120,6 +121,19 @@ function AuthShell({
} }
); );
// Resolve logo URL: prefer logo_url, otherwise fetch file by file_id.
const { data: logoFile } = useQuery({
queryKey: ["cms-file", logoData?.file_id],
queryFn: () => fetchCmsFileById(logoData!.file_id),
enabled: !!logoData?.file_id && !logoData?.logo_url,
});
const logoSrc = logoData?.logo_url
? resolveUploadUrl(logoData.logo_url)
: logoFile
? resolveCmsFileUrl(logoFile.path)
: logo;
const title = const title =
mode === "login" mode === "login"
? "Đăng nhập quản trị" ? "Đăng nhập quản trị"
...@@ -141,7 +155,7 @@ function AuthShell({ ...@@ -141,7 +155,7 @@ function AuthShell({
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="flex h-16 w-16 items-center justify-center rounded-2xl border border-[#063e8e]/10 bg-white shadow-sm"> <div className="flex h-16 w-16 items-center justify-center rounded-2xl border border-[#063e8e]/10 bg-white shadow-sm">
<Image <Image
src={logoData?.logo_url ? resolveUploadUrl(logoData.logo_url) : logo} src={logoSrc}
alt={logoData?.logo_name || "VCCI HCM"} alt={logoData?.logo_name || "VCCI HCM"}
width={48} width={48}
height={48} height={48}
...@@ -195,7 +209,7 @@ function AuthShell({ ...@@ -195,7 +209,7 @@ function AuthShell({
<div className="mb-8 flex items-center gap-3 lg:hidden"> <div className="mb-8 flex items-center gap-3 lg:hidden">
<div className="flex h-12 w-12 items-center justify-center rounded-2xl border border-[#063e8e]/10 bg-[#f8fbff]"> <div className="flex h-12 w-12 items-center justify-center rounded-2xl border border-[#063e8e]/10 bg-[#f8fbff]">
<Image <Image
src={logoData?.logo_url ? resolveUploadUrl(logoData.logo_url) : logo} src={logoSrc}
alt={logoData?.logo_name || "VCCI HCM"} alt={logoData?.logo_name || "VCCI HCM"}
width={36} width={36}
height={36} height={36}
......
...@@ -182,11 +182,10 @@ interface PostHistoryViewerProps { ...@@ -182,11 +182,10 @@ interface PostHistoryViewerProps {
export function PostHistoryViewer({ postId }: PostHistoryViewerProps) { export function PostHistoryViewer({ postId }: PostHistoryViewerProps) {
const [isOpen, setIsOpen] = React.useState(false); const [isOpen, setIsOpen] = React.useState(false);
const { data, isLoading, isError, error } = useGetApiV10PostIdHistory(postId, { // Always fetch history so the count is correct even before the user opens
query: { // the panel. Previously `enabled: isOpen` caused the count to show "0 thay
enabled: isOpen, // đổi" until the panel was opened.
}, const { data, isLoading, isError, error } = useGetApiV10PostIdHistory(postId);
});
const historyItems = React.useMemo(() => { const historyItems = React.useMemo(() => {
// useQuery's `data` IS the API response body: { responseData: [...], ... } // useQuery's `data` IS the API response body: { responseData: [...], ... }
......
...@@ -333,12 +333,31 @@ export function AdminRichTextEditor({ ...@@ -333,12 +333,31 @@ export function AdminRichTextEditor({
format: "json", format: "json",
buildData: (data: FormData) => { buildData: (data: FormData) => {
const next = new FormData(); const next = new FormData();
let firstFileAppended = false;
data.forEach((value, key) => { data.forEach((value, key) => {
// Jodit sends files as files[0], files[1], ... — multer expects
// a single field named "file". Only keep the first file and drop
// the rest (backend uses multer.single("file")).
if (/^files\[\d+\]$/.test(key) && value instanceof File) {
if (!firstFileAppended) {
next.append("file", value);
firstFileAppended = true;
}
return;
}
// Also handle legacy "files[]" pattern just in case.
if (key === "files[]" && value instanceof File) { if (key === "files[]" && value instanceof File) {
next.append("file", value); if (!firstFileAppended) {
} else { next.append("file", value);
next.append(key, value); firstFileAppended = true;
}
return;
}
// Drop Jodit-internal fields the backend doesn't use.
if (key === "source" || key === "extension" || key === "mimetype") {
return;
} }
next.append(key, value);
}); });
return next; return next;
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment