feat:upload content, video,teks,audio, fix tags, fix responsif ckeditor spit

This commit is contained in:
Anang Yusman 2025-01-08 03:21:19 +08:00
parent 73fc0ef934
commit d76b224a72
7 changed files with 125 additions and 92 deletions

View File

@ -243,8 +243,8 @@ export default function FormAudioDetail() {
setSelectedTarget(details.categoryId); // Untuk dropdown
const filesData = details.files || [];
const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) =>
file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg"
const fileUrls = filesData.map((file: { secondaryUrl: string }) =>
file.secondaryUrl ? file.secondaryUrl : "default-image.jpg"
);
setDetailThumb(fileUrls);
}
@ -354,7 +354,7 @@ export default function FormAudioDetail() {
<div className="flex lg:flex-row gap-10">
<Card className="w-full lg:w-8/12">
<div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">Form Konten Foto</p>
<p className="text-lg font-semibold mb-3">Form Konten Audio</p>
<div className="gap-5 mb-5">
{/* Input Title */}
<div className="space-y-2 py-3">
@ -418,25 +418,39 @@ export default function FormAudioDetail() {
)}
</div>
<Label className="text-xl text-black">File Media</Label>
<div className="w-full ">
<Label className="text-xl text-black">File Mediaaa</Label>
<div className="w-full">
<Swiper
thumbs={{ swiper: thumbsSwiper }}
modules={[FreeMode, Navigation, Thumbs]}
navigation={false}
className="w-full"
>
{detailThumb?.map((data: any) => (
<SwiperSlide key={data.id}>
<img
className="object-fill h-full w-full rounded-md"
src={data}
alt={` ${data.id}`}
/>
</SwiperSlide>
))}
{detailThumb?.map((data: any) => {
const isAudio =
data.endsWith(".webm") ||
data.endsWith(".mp3") ||
data.endsWith(".ogg");
return (
<SwiperSlide key={data.id}>
{isAudio ? (
<audio
className="object-fill h-full w-full rounded-md"
src={data.secondaryUrl}
controls
/>
) : (
<img
className="object-fill h-full w-full rounded-md"
src={data.secondaryUrl}
alt={` ${data.id}`}
/>
)}
</SwiperSlide>
);
})}
</Swiper>
<div className=" mt-2 ">
<div className="mt-2">
<Swiper
onSwiper={setThumbsSwiper}
slidesPerView={6}
@ -445,17 +459,30 @@ export default function FormAudioDetail() {
clickable: true,
}}
modules={[Pagination, Thumbs]}
// className="mySwiper2"
>
{detailThumb?.map((data: any) => (
<SwiperSlide key={data.id}>
<img
className="object-cover h-[60px] w-[80px]"
src={data}
alt={` ${data.id}`}
/>
</SwiperSlide>
))}
{detailThumb?.map((data: any) => {
const isAudio =
data.endsWith(".webm") ||
data.endsWith(".mp3") ||
data.endsWith(".ogg");
return (
<SwiperSlide key={data.id}>
{isAudio ? (
<audio
className="object-cover h-[60px] w-[80px]"
src={data.secondaryUrl}
controls
/>
) : (
<img
className="object-cover h-[60px] w-[80px]"
src={data.secondaryUrl}
alt={` ${data.id}`}
/>
)}
</SwiperSlide>
);
})}
</Swiper>
</div>
</div>

View File

@ -121,7 +121,7 @@ export default function FormAudio() {
const [detailData, setDetailData] = useState<any>(null);
const [articleImages, setArticleImages] = useState<string[]>([]);
const [isSwitchOn, setIsSwitchOn] = useState<boolean>(false);
const inputRef = useRef<HTMLInputElement>(null);
const [selectedTarget, setSelectedTarget] = useState("");
const [unitSelection, setUnitSelection] = useState({
allUnit: false,
@ -347,7 +347,9 @@ export default function FormAudio() {
const newTag = e.currentTarget.value.trim();
if (!tags.includes(newTag)) {
setTags((prevTags) => [...prevTags, newTag]); // Add new tag
// setValue("tags", ""); // Clear input field
if (inputRef.current) {
inputRef.current.value = ""; // Clear input field
}
}
}
};
@ -479,12 +481,7 @@ export default function FormAudio() {
close();
// showProgress();
files.map(async (item: any, index: number) => {
await uploadResumableFile(
index,
String(id),
item,
fileTypeId == "2" || fileTypeId == "4" ? item.duration : "0"
);
await uploadResumableFile(index, String(id), item, "0");
});
Cookies.remove("idCreate");
@ -528,7 +525,7 @@ export default function FormAudio() {
filename: file.name,
filetype: file.type,
duration,
isWatermark: "true", // hardcode
isWatermark: "false", // hardcode
},
onError: async (e: any) => {
console.log("Error upload :", e);
@ -1033,6 +1030,7 @@ export default function FormAudio() {
id="tags"
placeholder="Add a tag and press Enter"
onKeyDown={handleAddTag}
ref={inputRef}
/>
<div className="mt-3 ">
{tags.map((tag, index) => (

View File

@ -123,6 +123,7 @@ export default function FormImage() {
const [detailData, setDetailData] = useState<any>(null);
const [articleImages, setArticleImages] = useState<string[]>([]);
const [isSwitchOn, setIsSwitchOn] = useState<boolean>(false);
const inputRef = useRef<HTMLInputElement>(null);
const [content, setContent] = useState("");
@ -352,7 +353,9 @@ export default function FormImage() {
const newTag = e.currentTarget.value.trim();
if (!tags.includes(newTag)) {
setTags((prevTags) => [...prevTags, newTag]); // Add new tag
// setValue("tags", ""); // Clear input field
if (inputRef.current) {
inputRef.current.value = ""; // Clear input field
}
}
}
};
@ -1038,6 +1041,7 @@ export default function FormImage() {
id="tags"
placeholder="Add a tag and press Enter"
onKeyDown={handleAddTag}
ref={inputRef}
/>
<div className="mt-3 ">
{tags.map((tag, index) => (

View File

@ -487,19 +487,19 @@ export default function FormConvertSPIT() {
</Select>
</div>
</div>
<div>
<div className="">
<RadioGroup
onValueChange={(value) => setSelectedFileType(value)}
value={selectedFileType}
className=" grid-cols-1"
>
<div className="flex items-center space-x-2">
<div className="">
<RadioGroupItem value="original" id="original-file" />
<Label htmlFor="original-file">
Select Original File
</Label>
</div>
<div className="py-3">
<div className="py-3 ">
<Label>Deskripsi</Label>
<Controller
control={control}
@ -557,7 +557,7 @@ export default function FormConvertSPIT() {
Select File Hasil Rewrite
</Label>
</div>
<div className="py-3">
<div className="py-3 ">
<Label>File hasil Rewrite</Label>
<Controller
control={control}

View File

@ -243,8 +243,8 @@ export default function FormTeksDetail() {
setSelectedTarget(details.categoryId); // Untuk dropdown
const filesData = details.files || [];
const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) =>
file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg"
const fileUrls = filesData.map((file: { url: string }) =>
file.url ? file.url : "default-image.jpg"
);
setDetailThumb(fileUrls);
}
@ -419,9 +419,8 @@ export default function FormTeksDetail() {
</p>
)}
</div>
<Label className="text-xl text-black">File Media</Label>
<div className="w-full ">
<div className="w-full">
<Swiper
thumbs={{ swiper: thumbsSwiper }}
modules={[FreeMode, Navigation, Thumbs]}
@ -430,32 +429,56 @@ export default function FormTeksDetail() {
>
{detailThumb?.map((data: any) => (
<SwiperSlide key={data.id}>
<img
className="object-fill h-full w-full rounded-md"
src={data}
alt={` ${data.id}`}
/>
{[".jpg", ".jpeg", ".png", ".webp"].includes(
data.format
) ? (
<img
className="object-fill h-full w-full rounded-md"
src={data.url}
alt={data.fileName}
/>
) : [".pdf", ".docx", ".txt"].includes(data.format) ? (
<iframe
className="w-full h-96 rounded-md"
src={data.url}
title={data.fileName}
/>
) : (
<a
href={data}
target="_blank"
rel="noopener noreferrer"
className="block text-blue-500 underline"
>
View {data.fileName}
</a>
)}
</SwiperSlide>
))}
</Swiper>
<div className=" mt-2 ">
<div className="mt-2">
<Swiper
onSwiper={setThumbsSwiper}
slidesPerView={6}
spaceBetween={8}
pagination={{
clickable: true,
}}
pagination={{ clickable: true }}
modules={[Pagination, Thumbs]}
// className="mySwiper2"
>
{detailThumb?.map((data: any) => (
<SwiperSlide key={data.id}>
<img
className="object-cover h-[60px] w-[80px]"
src={data}
alt={` ${data.id}`}
/>
{[".jpg", ".jpeg", ".png", ".webp"].includes(
data.format
) ? (
<img
className="object-cover h-[60px] w-[80px]"
src={data.url}
alt={data.fileName}
/>
) : (
<div className="h-[60px] w-[80px] flex items-center justify-center bg-gray-200 text-sm text-center text-gray-700 rounded-md">
{data?.format?.replace(".", "").toUpperCase()}
</div>
)}
</SwiperSlide>
))}
</Swiper>

View File

@ -121,6 +121,7 @@ export default function FormTeks() {
const [detailData, setDetailData] = useState<any>(null);
const [articleImages, setArticleImages] = useState<string[]>([]);
const [isSwitchOn, setIsSwitchOn] = useState<boolean>(false);
const inputRef = useRef<HTMLInputElement>(null);
const [selectedTarget, setSelectedTarget] = useState("");
const [unitSelection, setUnitSelection] = useState({
@ -346,7 +347,9 @@ export default function FormTeks() {
const newTag = e.currentTarget.value.trim();
if (!tags.includes(newTag)) {
setTags((prevTags) => [...prevTags, newTag]); // Add new tag
// setValue("tags", ""); // Clear input field
if (inputRef.current) {
inputRef.current.value = ""; // Clear input field
}
}
}
};
@ -478,12 +481,7 @@ export default function FormTeks() {
close();
// showProgress();
files.map(async (item: any, index: number) => {
await uploadResumableFile(
index,
String(id),
item,
fileTypeId == "2" || fileTypeId == "4" ? item.duration : "0"
);
await uploadResumableFile(index, String(id), item, "0");
});
Cookies.remove("idCreate");
@ -527,7 +525,7 @@ export default function FormTeks() {
filename: file.name,
filetype: file.type,
duration,
isWatermark: "true", // hardcode
isWatermark: "false", // hardcode
},
onError: async (e: any) => {
console.log("Error upload :", e);
@ -1032,6 +1030,7 @@ export default function FormTeks() {
id="tags"
placeholder="Add a tag and press Enter"
onKeyDown={handleAddTag}
ref={inputRef}
/>
<div className="mt-3 ">
{tags.map((tag, index) => (

View File

@ -121,6 +121,7 @@ export default function FormVideo() {
const [detailData, setDetailData] = useState<any>(null);
const [articleImages, setArticleImages] = useState<string[]>([]);
const [isSwitchOn, setIsSwitchOn] = useState<boolean>(false);
const inputRef = useRef<HTMLInputElement>(null);
const [selectedTarget, setSelectedTarget] = useState("");
const [unitSelection, setUnitSelection] = useState({
@ -150,24 +151,7 @@ export default function FormVideo() {
const { getRootProps, getInputProps } = useDropzone({
onDrop: (acceptedFiles) => {
const validFiles = acceptedFiles.filter((file) => {
const isValidType = ["video/mp4", "video/mov"].includes(file.type);
const isValidSize = file.size <= 100 * 1024 * 1024; // 100MB
return isValidType && isValidSize;
});
if (!validFiles.length) {
alert("Format file harus mp4/mov dan ukuran maksimal 100MB");
return;
}
setFiles(
validFiles.map((file) =>
Object.assign(file, {
preview: URL.createObjectURL(file),
})
)
);
setFiles(acceptedFiles.map((file) => Object.assign(file)));
},
});
@ -363,7 +347,9 @@ export default function FormVideo() {
const newTag = e.currentTarget.value.trim();
if (!tags.includes(newTag)) {
setTags((prevTags) => [...prevTags, newTag]); // Add new tag
// setValue("tags", ""); // Clear input field
if (inputRef.current) {
inputRef.current.value = ""; // Clear input field
}
}
}
};
@ -495,12 +481,7 @@ export default function FormVideo() {
close();
// showProgress();
files.map(async (item: any, index: number) => {
await uploadResumableFile(
index,
String(id),
item,
"0"
);
await uploadResumableFile(index, String(id), item, "0");
});
Cookies.remove("idCreate");
@ -1062,6 +1043,7 @@ export default function FormVideo() {
id="tags"
placeholder="Add a tag and press Enter"
onKeyDown={handleAddTag}
ref={inputRef}
/>
<div className="mt-3 ">
{tags.map((tag, index) => (