feat:magazine edit
This commit is contained in:
parent
d64ce7fc14
commit
471539804c
|
|
@ -33,7 +33,7 @@ import {
|
||||||
PptIcon,
|
PptIcon,
|
||||||
WordIcon,
|
WordIcon,
|
||||||
} from "@/components/icons/globals";
|
} from "@/components/icons/globals";
|
||||||
import { createMagazine } from "@/service/magazine";
|
import { createMagazine, uploadMagazineFile } from "@/service/magazine";
|
||||||
|
|
||||||
// const CustomEditor = dynamic(
|
// const CustomEditor = dynamic(
|
||||||
// () => {
|
// () => {
|
||||||
|
|
@ -85,11 +85,6 @@ export default function NewCreateMagazineForm() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const editor = useRef(null);
|
const editor = useRef(null);
|
||||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||||
const [useAi, setUseAI] = useState(false);
|
|
||||||
const [listCategory, setListCategory] = useState<CategoryType[]>([]);
|
|
||||||
const [tag, setTag] = useState("");
|
|
||||||
const [thumbnailImg, setThumbnailImg] = useState<File[]>([]);
|
|
||||||
const [selectedMainImage, setSelectedMainImage] = useState<number>();
|
|
||||||
|
|
||||||
const { getRootProps, getInputProps } = useDropzone({
|
const { getRootProps, getInputProps } = useDropzone({
|
||||||
onDrop: (acceptedFiles) => {
|
onDrop: (acceptedFiles) => {
|
||||||
|
|
@ -160,28 +155,23 @@ export default function NewCreateMagazineForm() {
|
||||||
// rows: values.rows,
|
// rows: values.rows,
|
||||||
};
|
};
|
||||||
console.log("formd", formData);
|
console.log("formd", formData);
|
||||||
// const response = await createMagazine(formData);
|
const response = await createMagazine(formData);
|
||||||
|
|
||||||
// if (response?.error) {
|
if (response?.error) {
|
||||||
// error(response.message);
|
error(response.message);
|
||||||
// return false;
|
return false;
|
||||||
// }
|
}
|
||||||
// const magazineId = response?.data?.data?.id;
|
const magazineId = response?.data?.data?.id;
|
||||||
// if (files?.length > 0) {
|
if (files?.length > 0) {
|
||||||
// const formFiles = new FormData();
|
const formFiles = new FormData();
|
||||||
|
|
||||||
// for (const element of files) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
// formFiles.append("file", element);
|
formFiles.append("files", files[i]);
|
||||||
// const resFile = await uploadArticleFile(magazineId, formFiles);
|
formFiles.append("title", values.rows[i].title);
|
||||||
// }
|
formFiles.append("file", values.rows[i].description);
|
||||||
// }
|
const resFile = await uploadMagazineFile(magazineId, formFiles);
|
||||||
|
}
|
||||||
// if (thumbnailImg?.length > 0) {
|
}
|
||||||
// const formFiles = new FormData();
|
|
||||||
|
|
||||||
// formFiles.append("file", thumbnailImg[0]);
|
|
||||||
// const resFile = await uploadArticleThumbnail(magazineId, formFiles);
|
|
||||||
// }
|
|
||||||
|
|
||||||
close();
|
close();
|
||||||
successSubmit("/admin/magazine");
|
successSubmit("/admin/magazine");
|
||||||
|
|
@ -310,6 +300,7 @@ export default function NewCreateMagazineForm() {
|
||||||
<Button
|
<Button
|
||||||
className=" border-none rounded-full"
|
className=" border-none rounded-full"
|
||||||
variant="bordered"
|
variant="bordered"
|
||||||
|
color="danger"
|
||||||
onClick={() => handleRemoveFile(file)}
|
onClick={() => handleRemoveFile(file)}
|
||||||
>
|
>
|
||||||
<TimesIcon />
|
<TimesIcon />
|
||||||
|
|
|
||||||
|
|
@ -29,12 +29,14 @@ import Link from "next/link";
|
||||||
import {
|
import {
|
||||||
CsvIcon,
|
CsvIcon,
|
||||||
ExcelIcon,
|
ExcelIcon,
|
||||||
|
FileIcon,
|
||||||
PdfIcon,
|
PdfIcon,
|
||||||
PptIcon,
|
PptIcon,
|
||||||
WordIcon,
|
WordIcon,
|
||||||
} from "@/components/icons/globals";
|
} from "@/components/icons/globals";
|
||||||
import {
|
import {
|
||||||
createMagazine,
|
createMagazine,
|
||||||
|
deleteMagazineFiles,
|
||||||
getMagazineById,
|
getMagazineById,
|
||||||
updateMagazine,
|
updateMagazine,
|
||||||
uploadMagazineFile,
|
uploadMagazineFile,
|
||||||
|
|
@ -93,6 +95,7 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const editor = useRef(null);
|
const editor = useRef(null);
|
||||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||||
|
const [detailfiles, setDetailFiles] = useState<any>([]);
|
||||||
|
|
||||||
const { getRootProps, getInputProps } = useDropzone({
|
const { getRootProps, getInputProps } = useDropzone({
|
||||||
onDrop: (acceptedFiles) => {
|
onDrop: (acceptedFiles) => {
|
||||||
|
|
@ -144,6 +147,8 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
||||||
const data = res?.data?.data;
|
const data = res?.data?.data;
|
||||||
setValue("title", data?.title);
|
setValue("title", data?.title);
|
||||||
setValue("description", data?.description);
|
setValue("description", data?.description);
|
||||||
|
setDetailFiles(data?.files);
|
||||||
|
|
||||||
console.log("datasss", data);
|
console.log("datasss", data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -222,31 +227,38 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
||||||
setValue("slug", generateSlug(watchTitle));
|
setValue("slug", generateSlug(watchTitle));
|
||||||
}, [watchTitle]);
|
}, [watchTitle]);
|
||||||
|
|
||||||
const renderPreview = (file: File) => {
|
const renderPreview = (file: File, fileName?: string) => {
|
||||||
if (file.type === "application/pdf") {
|
const fileType = fileName?.split(".")[fileName?.split(".").length - 1];
|
||||||
|
if (file.type === "application/pdf" || fileType == "pdf") {
|
||||||
return <PdfIcon size={60} />;
|
return <PdfIcon size={60} />;
|
||||||
} else if (file.type === "text/csv") {
|
} else if (file.type === "text/csv" || fileType == "csv") {
|
||||||
return <CsvIcon size={60} />;
|
return <CsvIcon size={60} />;
|
||||||
} else if (
|
} else if (
|
||||||
file.type ===
|
file.type ===
|
||||||
"application/vnd.openxmlformats-officedocument.wordprocessingml.document" ||
|
"application/vnd.openxmlformats-officedocument.wordprocessingml.document" ||
|
||||||
file.type === "application/msword"
|
file.type === "application/msword" ||
|
||||||
|
fileType == "doc" ||
|
||||||
|
fileType == "docx"
|
||||||
) {
|
) {
|
||||||
return <WordIcon size={60} />;
|
return <WordIcon size={60} />;
|
||||||
} else if (
|
} else if (
|
||||||
file.type ===
|
file.type ===
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ||
|
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" ||
|
||||||
file.type === "application/vnd.ms-excel"
|
file.type === "application/vnd.ms-excel" ||
|
||||||
|
fileType == "xls" ||
|
||||||
|
fileType == "xlsx"
|
||||||
) {
|
) {
|
||||||
return <ExcelIcon size={60} />;
|
return <ExcelIcon size={60} />;
|
||||||
} else if (
|
} else if (
|
||||||
file.type ===
|
file.type ===
|
||||||
"application/vnd.openxmlformats-officedocument.presentationml.presentation" ||
|
"application/vnd.openxmlformats-officedocument.presentationml.presentation" ||
|
||||||
file.type === "application/vnd.ms-powerpoint"
|
file.type === "application/vnd.ms-powerpoint" ||
|
||||||
|
fileType == "ppt" ||
|
||||||
|
fileType == "pptx"
|
||||||
) {
|
) {
|
||||||
return <PptIcon size={60} />;
|
return <PptIcon size={60} />;
|
||||||
} else {
|
} else {
|
||||||
return "unknown";
|
return <FileIcon size={60} />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -319,6 +331,7 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
||||||
<Button
|
<Button
|
||||||
className=" border-none rounded-full"
|
className=" border-none rounded-full"
|
||||||
variant="bordered"
|
variant="bordered"
|
||||||
|
color="danger"
|
||||||
onClick={() => handleRemoveFile(file)}
|
onClick={() => handleRemoveFile(file)}
|
||||||
>
|
>
|
||||||
<TimesIcon />
|
<TimesIcon />
|
||||||
|
|
@ -326,6 +339,43 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
||||||
</div>
|
</div>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
const handleDeleteFile = (id: number) => {
|
||||||
|
MySwal.fire({
|
||||||
|
title: "Hapus File",
|
||||||
|
text: "",
|
||||||
|
icon: "warning",
|
||||||
|
showCancelButton: true,
|
||||||
|
cancelButtonColor: "#d33",
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
confirmButtonText: "Hapus",
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
deleteFile(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteFile = async (id: number) => {
|
||||||
|
loading();
|
||||||
|
const res = await deleteMagazineFiles(id);
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
error(res.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
close();
|
||||||
|
initFetch();
|
||||||
|
MySwal.fire({
|
||||||
|
title: "Sukses",
|
||||||
|
icon: "success",
|
||||||
|
confirmButtonColor: "#3085d6",
|
||||||
|
confirmButtonText: "OK",
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form
|
<form
|
||||||
className="flex flex-row gap-8 text-black"
|
className="flex flex-row gap-8 text-black"
|
||||||
|
|
@ -411,8 +461,8 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
<p className="text-sm mt-3">File Media</p>
|
<p className="text-sm mt-3">File Media</p>
|
||||||
<Fragment>
|
{!isDetail && (
|
||||||
{!isDetail && (
|
<Fragment>
|
||||||
<div {...getRootProps({ className: "dropzone" })} className="mb-2">
|
<div {...getRootProps({ className: "dropzone" })} className="mb-2">
|
||||||
<input {...getInputProps()} />
|
<input {...getInputProps()} />
|
||||||
<div className=" w-full text-center border-dashed border border-default-200 dark:border-default-300 rounded-md py-[52px] flex items-center flex-col">
|
<div className=" w-full text-center border-dashed border border-default-200 dark:border-default-300 rounded-md py-[52px] flex items-center flex-col">
|
||||||
|
|
@ -426,21 +476,190 @@ export default function EditMagazineForm(props: { isDetail: boolean }) {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div className="grid grid-cols-2 gap-2">
|
||||||
|
{files.length ? (
|
||||||
|
<Fragment>
|
||||||
|
{fileList}
|
||||||
|
|
||||||
{files.length ? (
|
{/* {files.length > 1 && (
|
||||||
<Fragment>
|
<div className=" flex justify-between gap-2">
|
||||||
<div className="grid grid-cols-2 gap-2">{fileList}</div>
|
<Button onPress={() => setFiles([])} size="sm">
|
||||||
{files.length > 1 && (
|
Hapus Semua
|
||||||
<div className=" flex justify-between gap-2">
|
</Button>
|
||||||
<Button onPress={() => setFiles([])} size="sm">
|
</div>
|
||||||
Hapus Semua
|
)} */}
|
||||||
|
</Fragment>
|
||||||
|
) : null}
|
||||||
|
{detailfiles?.map((file: any, index: number) => (
|
||||||
|
<div
|
||||||
|
key={file.fileName + index}
|
||||||
|
className=" flex justify-between border p-3 rounded-md"
|
||||||
|
>
|
||||||
|
<div className="flex gap-3 grow">
|
||||||
|
<div className="file-preview">
|
||||||
|
{renderPreview(file, file.fileName)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-1 grow">
|
||||||
|
<p className="text-sm font-semibold">Nama File</p>
|
||||||
|
<div className="flex flex-row gap-2 items-center">
|
||||||
|
<p className=" text-sm text-card-foreground">
|
||||||
|
{file.fileName}
|
||||||
|
</p>
|
||||||
|
<p className=" text-xs font-light text-muted-foreground">
|
||||||
|
{Math.round(file.size / 100) / 10 > 1000 ? (
|
||||||
|
<>
|
||||||
|
{(Math.round(file.size / 100) / 10000).toFixed(1)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>{(Math.round(file.size / 100) / 10).toFixed(1)}</>
|
||||||
|
)}
|
||||||
|
{" kb"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm font-semibold">Judul</p>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
id="title"
|
||||||
|
placeholder=""
|
||||||
|
label=""
|
||||||
|
isReadOnly
|
||||||
|
value={file.title}
|
||||||
|
onValueChange={(e) =>
|
||||||
|
setValue(`rows.${index}.title`, e)
|
||||||
|
}
|
||||||
|
labelPlacement="outside"
|
||||||
|
className="w-full "
|
||||||
|
classNames={{
|
||||||
|
inputWrapper: [
|
||||||
|
"border-1 rounded-lg",
|
||||||
|
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
variant="bordered"
|
||||||
|
/>
|
||||||
|
<p className="text-sm font-semibold">Deskripsi</p>
|
||||||
|
<Textarea
|
||||||
|
type="text"
|
||||||
|
id="title"
|
||||||
|
placeholder=""
|
||||||
|
label=""
|
||||||
|
value={file.description}
|
||||||
|
onValueChange={(e) =>
|
||||||
|
setValue(`rows.${index}.description`, e)
|
||||||
|
}
|
||||||
|
isReadOnly
|
||||||
|
labelPlacement="outside"
|
||||||
|
className="w-full "
|
||||||
|
classNames={{
|
||||||
|
inputWrapper: [
|
||||||
|
"border-1 rounded-lg",
|
||||||
|
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
variant="bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
className=" border-none rounded-full"
|
||||||
|
variant="bordered"
|
||||||
|
color="danger"
|
||||||
|
onClick={() => handleDeleteFile(file?.id)}
|
||||||
|
>
|
||||||
|
<TimesIcon />
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
))}
|
||||||
</Fragment>
|
</div>
|
||||||
) : null}
|
</Fragment>
|
||||||
</Fragment>
|
)}
|
||||||
|
{isDetail && (
|
||||||
|
<div className="grid grid-cols-2 gap-2">
|
||||||
|
{detailfiles?.map((file: any, index: number) => (
|
||||||
|
<div
|
||||||
|
key={file.fileName + index}
|
||||||
|
className=" flex justify-between border p-3 rounded-md"
|
||||||
|
>
|
||||||
|
<div className="flex gap-3 grow">
|
||||||
|
<div className="file-preview">
|
||||||
|
{renderPreview(file, file.fileName)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="flex flex-col gap-1 grow">
|
||||||
|
<p className="text-sm font-semibold">Nama File</p>
|
||||||
|
<div className="flex flex-row gap-2 items-center">
|
||||||
|
<p className=" text-sm text-card-foreground">
|
||||||
|
{file.fileName}
|
||||||
|
</p>
|
||||||
|
<p className=" text-xs font-light text-muted-foreground">
|
||||||
|
{Math.round(file.size / 100) / 10 > 1000 ? (
|
||||||
|
<>
|
||||||
|
{(Math.round(file.size / 100) / 10000).toFixed(1)}
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>{(Math.round(file.size / 100) / 10).toFixed(1)}</>
|
||||||
|
)}
|
||||||
|
{" kb"}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p className="text-sm font-semibold">Judul</p>
|
||||||
|
<Input
|
||||||
|
type="text"
|
||||||
|
id="title"
|
||||||
|
placeholder=""
|
||||||
|
label=""
|
||||||
|
isReadOnly
|
||||||
|
value={file.title}
|
||||||
|
onValueChange={(e) => setValue(`rows.${index}.title`, e)}
|
||||||
|
labelPlacement="outside"
|
||||||
|
className="w-full "
|
||||||
|
classNames={{
|
||||||
|
inputWrapper: [
|
||||||
|
"border-1 rounded-lg",
|
||||||
|
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
variant="bordered"
|
||||||
|
/>
|
||||||
|
<p className="text-sm font-semibold">Deskripsi</p>
|
||||||
|
<Textarea
|
||||||
|
type="text"
|
||||||
|
id="title"
|
||||||
|
placeholder=""
|
||||||
|
label=""
|
||||||
|
value={file.description}
|
||||||
|
onValueChange={(e) =>
|
||||||
|
setValue(`rows.${index}.description`, e)
|
||||||
|
}
|
||||||
|
isReadOnly
|
||||||
|
labelPlacement="outside"
|
||||||
|
className="w-full "
|
||||||
|
classNames={{
|
||||||
|
inputWrapper: [
|
||||||
|
"border-1 rounded-lg",
|
||||||
|
"dark:group-data-[focused=false]:bg-transparent !border-1 dark:!border-gray-400",
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
variant="bordered"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* <Button
|
||||||
|
className=" border-none rounded-full"
|
||||||
|
variant="bordered"
|
||||||
|
color="danger"
|
||||||
|
onClick={() => handleRemoveFile(file)}
|
||||||
|
>
|
||||||
|
<TimesIcon />
|
||||||
|
</Button> */}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex flex-row gap-3 mt-3">
|
<div className="flex flex-row gap-3 mt-3">
|
||||||
{!isDetail && (
|
{!isDetail && (
|
||||||
<Button color="primary" type="submit">
|
<Button color="primary" type="submit">
|
||||||
|
|
|
||||||
|
|
@ -128,3 +128,23 @@ export const PptIcon = ({
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
export const FileIcon = ({
|
||||||
|
size,
|
||||||
|
height = 24,
|
||||||
|
width = 24,
|
||||||
|
fill = "currentColor",
|
||||||
|
...props
|
||||||
|
}: IconSvgProps) => (
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={size || width}
|
||||||
|
height={size || height}
|
||||||
|
{...props}
|
||||||
|
viewBox="0 0 15 15"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="m10.5.5l.354-.354L10.707 0H10.5zm3 3h.5v-.207l-.146-.147zm-1 10.5h-10v1h10zM2 13.5v-12H1v12zM2.5 1h8V0h-8zM13 3.5v10h1v-10zM10.146.854l3 3l.708-.708l-3-3zM2.5 14a.5.5 0 0 1-.5-.5H1A1.5 1.5 0 0 0 2.5 15zm10 1a1.5 1.5 0 0 0 1.5-1.5h-1a.5.5 0 0 1-.5.5zM2 1.5a.5.5 0 0 1 .5-.5V0A1.5 1.5 0 0 0 1 1.5z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -56,3 +56,7 @@ export async function uploadMagazineFile(id: string, data: any) {
|
||||||
};
|
};
|
||||||
return await httpPost(`/magazine-files/${id}`, headers, data);
|
return await httpPost(`/magazine-files/${id}`, headers, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deleteMagazineFiles(id: number) {
|
||||||
|
return await httpDeleteInterceptor(`magazine-files/${id}`);
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue