diff --git a/src/components/user-profile/ApplicationList.tsx b/src/components/user-profile/ApplicationList.tsx
index bd414f5..cdac3bd 100644
--- a/src/components/user-profile/ApplicationList.tsx
+++ b/src/components/user-profile/ApplicationList.tsx
@@ -3,30 +3,125 @@
import { setSelectedApplication } from "@/store/features/userSlice";
import { useRouter } from "next/navigation";
import { useDispatch } from "react-redux";
+import { URL_MEDIA } from "../../../api";
-export default function ApplicationList({ applications }: { applications: any[] }) {
+const formatFullDateTime = (dateString: string) => {
+ const date = new Date(dateString);
+ const time = date.toLocaleTimeString("vi-VN", { hour: "2-digit", minute: "2-digit" });
+ const day = date.toLocaleDateString("vi-VN", { day: "2-digit", month: "2-digit", year: "numeric" });
+ return `${time} ${day}`;
+};
+
+const processMedia = (mediaArray: any[]) => {
+ if (!mediaArray || mediaArray.length === 0) return { type: "empty" };
+ const imageFiles = mediaArray.filter((file) => {
+ const isImageMime = file.mime_type?.startsWith("image/");
+ const isImageExt = /\.(jpg|jpeg|png|webp|gif)$/i.test(file.storage_key);
+ return isImageMime || isImageExt;
+ });
+ const docFiles = mediaArray.filter((file) => {
+ const isImage = file.mime_type?.startsWith("image/") || /\.(jpg|jpeg|png|webp|gif)$/i.test(file.storage_key);
+ return !isImage;
+ });
+ if (imageFiles.length > 0) return { type: "image", src: `${URL_MEDIA}${imageFiles[0].storage_key}` };
+ if (docFiles.length > 0) {
+ const extensions = docFiles.map((file) => file.mime_type ? file.mime_type.split("/")[1] : file.storage_key.split(".").pop() || "file");
+ return { type: "documents", extensions };
+ }
+ return { type: "empty" };
+};
+
+export default function ApplicationSquareCardList({ applications }: { applications: any[] }) {
const router = useRouter();
const dispatch = useDispatch();
- const handleViewDetail = (app: any) => {
+ const handleViewDetail = (app: any) => {
dispatch(setSelectedApplication(app));
router.push(`/profile/applications`);
-};
+ };
return (
-
- {applications.map((app) => (
-
handleViewDetail(app)}
- className="p-4 border rounded-lg cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 transition"
- >
-
- Loại: {app.verify_type}
- Xem chi tiết →
-
-
- ))}
+
+
+ Applications CV
+
+
+
+ {applications?.map((app) => {
+ const mediaState = processMedia(app.media);
+ return (
+
handleViewDetail(app)}
+ className="group relative h-40 aspect-square border dark:border-zinc-800 rounded-xl cursor-pointer overflow-hidden transition-all duration-300 hover:ring-2 hover:ring-blue-500/50"
+ >
+
+ {mediaState.type === "image" ? (
+

+ ) : (
+
+ {mediaState.type === "documents" ? (
+
+ {mediaState.extensions?.slice(0, 3).map((ext, i) => (
+
+ .{ext}
+
+ ))}
+
+ ) : (
+
+ )}
+
+ )}
+
+
+
+
+
+
+
+
+
+ {app.media?.length > 0 && (
+
+ {app.media.length} FILE
+
+ )}
+
+
+
+
+
+ {app.verify_type || "VERIFY"}
+
+ {app?.reviewer?.display_name && (
+
+ By: {app.reviewer.display_name}
+
+ )}
+
+
+
+
+ {formatFullDateTime(app.created_at)}
+
+
+
+
+
+ );
+ })}
+
);
}
\ No newline at end of file
diff --git a/src/components/user-profile/UserMetaCard.tsx b/src/components/user-profile/UserMetaCard.tsx
index 9916f16..e7ff851 100644
--- a/src/components/user-profile/UserMetaCard.tsx
+++ b/src/components/user-profile/UserMetaCard.tsx
@@ -37,7 +37,7 @@ export default function UserMetaCard({ data }: { data: UserMetaCardProps }) {
setIsUploading(true);
const uploadedMedia = await uploadMedia(file);
- console.log("Upload thành công:", uploadedMedia);
+ // console.log("Upload thành công:", uploadedMedia);
if (uploadedMedia?.url) {
diff --git a/src/service/mediaService.ts b/src/service/mediaService.ts
index d4fc921..e9229d4 100644
--- a/src/service/mediaService.ts
+++ b/src/service/mediaService.ts
@@ -58,14 +58,14 @@ export const uploadFileToS3 = async (
"Content-Type": file.type,
},
});
- console.log("Response from S3 upload:", res);
+ // console.log("Response from S3 upload:", res);
};
export const confirmUpload = async (token_id: string) => {
const res = await api.post("/media/presigned/complete", {
token_id,
});
- console.log("Response from confirm upload:", res);
+ // console.log("Response from confirm upload:", res);
return res.data;
};
@@ -80,12 +80,12 @@ export const uploadMedia = async (file: File) => {
},
},
);
- console.log("Presigned URL:", presigned);
+ // console.log("Presigned URL:", presigned);
await uploadFileToS3(file, presigned);
const media = await confirmUpload(presigned.token_id);
- console.log("Media sau khi upload:", media);
+ // console.log("Media sau khi upload:", media);
return media;
};
@@ -100,7 +100,7 @@ export const getPresignedUrl = async (file: File) => {
},
},
);
- console.log("Presigned URL:", presigned);
+ // console.log("Presigned URL:", presigned);
return presigned;
};
diff --git a/src/store/features/userSlice.ts b/src/store/features/userSlice.ts
index d966dfe..aed21c5 100644
--- a/src/store/features/userSlice.ts
+++ b/src/store/features/userSlice.ts
@@ -1,7 +1,6 @@
import { UserData } from '@/interface/user';
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
-// Hàm helper để đọc dữ liệu an toàn từ storage
const getStoredApplication = () => {
if (typeof window !== "undefined") {
const saved = sessionStorage.getItem('selected_application');
@@ -19,7 +18,7 @@ interface UserState {
const initialState: UserState = {
data: null,
isAuthenticated: false,
- selectedApplication: getStoredApplication(), // Khởi tạo từ storage
+ selectedApplication: getStoredApplication(),
};
const userSlice = createSlice({
@@ -32,7 +31,6 @@ const userSlice = createSlice({
},
setSelectedApplication: (state, action: PayloadAction
) => {
state.selectedApplication = action.payload;
- // Lưu vào sessionStorage để khi reload trang không bị mất
if (typeof window !== "undefined") {
sessionStorage.setItem('selected_application', JSON.stringify(action.payload));
}