diff --git a/src/components/user-profile/Media.tsx b/src/components/user-profile/Media.tsx index b9a1a3b..98f169d 100644 --- a/src/components/user-profile/Media.tsx +++ b/src/components/user-profile/Media.tsx @@ -17,7 +17,7 @@ export default function MediaCard({ data }: { data: MediaDto }) { title: item.original_name, description: `Size: ${(item.size / 1024).toFixed(2)} KB - Type: ${item.mime_type}`, })); - + // console.log("slides", listMedia); return (

Media Assets

diff --git a/src/components/user-profile/UserMetaCard.tsx b/src/components/user-profile/UserMetaCard.tsx index 52c8825..3bca2fc 100644 --- a/src/components/user-profile/UserMetaCard.tsx +++ b/src/components/user-profile/UserMetaCard.tsx @@ -1,28 +1,90 @@ "use client"; -// import React from "react"; -// import { useModal } from "../../hooks/useModal"; -// import { Modal } from "../ui/modal"; -// import Button from "../ui/button/Button"; -// import Input from "../form/input/InputField"; -// import Label from "../form/Label"; + +import { useState, useRef } from "react"; import Image from "next/image"; import { UserMetaCardProps } from "@/interface/user"; +import { uploadMedia } from "@/service/mediaService"; export default function UserMetaCard({ data }: { data: UserMetaCardProps }) { - // const { isOpen, openModal, closeModal } = useModal(); + const [previewImage, setPreviewImage] = useState( + data.data?.profile?.avatar_url || "/images/no-images.jpg" + ); + const [isUploading, setIsUploading] = useState(false); + const fileInputRef = useRef(null); + + const handleAvatarClick = () => { + if (!isUploading) { + fileInputRef.current?.click(); + } + }; + + const handleFileChange = async (event: React.ChangeEvent) => { + const file = event.target.files?.[0]; + if (!file) return; + + try { + setIsUploading(true); + console.log("Selected file:", file); + + const objectUrl = URL.createObjectURL(file); + setPreviewImage(objectUrl); + + const uploadedMedia = await uploadMedia(file); + console.log("Upload thành công:", uploadedMedia); + + } catch (error) { + console.error("Lỗi khi upload avatar:", error); + setPreviewImage(data.data?.profile?.avatar_url || "/images/no-images.jpg"); + alert("Không thể tải ảnh lên. Vui lòng thử lại!"); + } finally { + setIsUploading(false); + if (fileInputRef.current) { + fileInputRef.current.value = ""; + } + } + }; + return ( <>
-
+ +
avatar + +
+ {isUploading ? ( + + + + + ) : ( + + + + + )} +
+ +
+

{data.data?.profile?.display_name || "Full Name"} @@ -42,192 +104,9 @@ export default function UserMetaCard({ data }: { data: UserMetaCardProps }) {

- {/* */}
- {/* */}
- {/* -
-
-

- Edit Personal Information -

-

- Update your details to keep your profile up-to-date. -

-
-
-
-
-
- Social Links -
- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
-
- Personal Information -
- -
-
- - -
- -
- - -
- -
- - -
- -
- - -
- -
- - -
-
-
-
-
- - -
-
-
-
*/} ); -} +} \ No newline at end of file diff --git a/src/service/mediaService.ts b/src/service/mediaService.ts index 3cde746..d6ccb61 100644 --- a/src/service/mediaService.ts +++ b/src/service/mediaService.ts @@ -1,10 +1,87 @@ import api from "@/config/config"; import { API } from "../../api"; import { payloadPresignedMedia } from "@/interface/media"; +import axios from "axios"; -export const apiGetCurrentUserMedia = async (payload: payloadPresignedMedia) => { +export const apiGetCurrentUserMedia = async ( + payload: payloadPresignedMedia, +) => { const response = await api.get(API.Media.PRESIGNED, { params: payload, }); return response?.data; -}; \ No newline at end of file +}; + +export type FileType = + | "image" + | "video" + | "audio" + | "pdf" + | "docx" + | "text" + | "other"; + +export const getFileType = (mime: string): FileType => { + if (!mime) return "other"; + + if (mime.startsWith("image/")) return "image"; + if (mime.startsWith("video/")) return "video"; + if (mime.startsWith("audio/")) return "audio"; + + if (mime === "application/pdf") return "pdf"; + + if ( + mime === + "application/vnd.openxmlformats-officedocument.wordprocessingml.document" + ) + return "docx"; + + if (mime.startsWith("text/")) return "text"; + + return "other"; +}; + +type PreSignedResponse = { + token_id: string; + upload_url: string; + storage_key: string; + signed_headers: Record; +}; + +export const uploadFileToS3 = async ( + file: File, + presigned: PreSignedResponse, +) => { + await axios.put(presigned.upload_url, file, { + headers: { + ...presigned.signed_headers, + "Content-Type": file.type, + }, + }); +}; + +export const confirmUpload = async (token_id: string) => { + const res = await api.post("/media/presigned/complete", { + token_id, + }); + + return res.data; +}; +export const uploadMedia = async (file: File) => { + const { data: presigned } = await api.get( + "/media/presigned", + { + params: { + fileName: file.name, + contentType: file.type, + size: file.size, + }, + }, + ); + + await uploadFileToS3(file, presigned); + + const media = await confirmUpload(presigned.token_id); + + return media; +};