fix: create content imgae
This commit is contained in:
parent
b8827ba8a8
commit
377c22e083
|
|
@ -60,13 +60,13 @@ import {
|
|||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
type StatusFilter = string[];
|
||||
|
||||
const ContentTable = () => {
|
||||
const router = useRouter();
|
||||
const searchParams = useSearchParams();
|
||||
|
||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||
const [totalData, setTotalData] = React.useState<number>(1);
|
||||
const [sorting, setSorting] = React.useState<SortingState>([]);
|
||||
|
|
@ -85,7 +85,6 @@ const ContentTable = () => {
|
|||
const [limit, setLimit] = React.useState(10);
|
||||
const userId = getCookiesDecrypt("uie");
|
||||
const userLevelId = getCookiesDecrypt("ulie");
|
||||
|
||||
const [categories, setCategories] = React.useState<string[]>();
|
||||
const [categoryFilter, setCategoryFilter] = React.useState<string[]>([]);
|
||||
const [statusFilter, setStatusFilter] = React.useState<StatusFilter>([]);
|
||||
|
|
@ -95,8 +94,8 @@ const ContentTable = () => {
|
|||
const [fileTypeFilter, setFileTypeFilter] = React.useState<string[]>([]);
|
||||
const [filterBySource, setFilterBySource] = React.useState<string>("");
|
||||
const [search, setSearch] = React.useState("");
|
||||
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
const t = useTranslations("Form");
|
||||
|
||||
const table = useReactTable({
|
||||
data: dataTable,
|
||||
|
|
@ -165,8 +164,8 @@ const ContentTable = () => {
|
|||
}
|
||||
|
||||
const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSearch(e.target.value);
|
||||
table.getColumn("judul")?.setFilterValue(e.target.value);
|
||||
setSearch(e.target.value);
|
||||
table.getColumn("judul")?.setFilterValue(e.target.value);
|
||||
};
|
||||
|
||||
return (
|
||||
|
|
@ -179,7 +178,7 @@ const ContentTable = () => {
|
|||
</InputGroupText>
|
||||
<Input
|
||||
type="text"
|
||||
placeholder="Search Judul..."
|
||||
placeholder={t("searchTitle")}
|
||||
className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white"
|
||||
value={search}
|
||||
onChange={handleSearch}
|
||||
|
|
@ -211,14 +210,14 @@ const ContentTable = () => {
|
|||
}}
|
||||
>
|
||||
<SelectTrigger className="w-full lg:w-[180px]">
|
||||
<SelectValue placeholder="Select a Filter" />
|
||||
<SelectValue placeholder={t("selectFilter")} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectGroup>
|
||||
<SelectLabel>Filter</SelectLabel>
|
||||
<SelectItem value="1">Foto</SelectItem>
|
||||
<SelectItem value="2">Audio Visual</SelectItem>
|
||||
<SelectItem value="3">Teks</SelectItem>
|
||||
<SelectItem value="1">{t("image")}</SelectItem>
|
||||
<SelectItem value="2">{t("audio-visual")}</SelectItem>
|
||||
<SelectItem value="3">{t("text")}</SelectItem>
|
||||
<SelectItem value="4">Audio</SelectItem>
|
||||
</SelectGroup>
|
||||
</SelectContent>
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ import {
|
|||
import { getCookiesDecrypt } from "@/lib/utils";
|
||||
import { useDropzone } from "react-dropzone";
|
||||
import { Icon } from "@iconify/react";
|
||||
import { CloudUpload } from "lucide-react";
|
||||
import { CloudUpload, X } from "lucide-react";
|
||||
import Image from "next/image";
|
||||
import { error, loading } from "@/config/swal";
|
||||
import { Item } from "@radix-ui/react-dropdown-menu";
|
||||
|
|
@ -95,14 +95,12 @@ export default function FormImage() {
|
|||
const scheduleType = Cookies.get("scheduleType");
|
||||
const roleId = getCookiesDecrypt("urie");
|
||||
const [selectedFileType, setSelectedFileType] = useState("original");
|
||||
|
||||
const [categories, setCategories] = useState<Category[]>([]);
|
||||
const [selectedCategory, setSelectedCategory] = useState<any>();
|
||||
const [tags, setTags] = useState<any[]>([]);
|
||||
const [thumbnail, setThumbnail] = useState<File | null>(null);
|
||||
const [preview, setPreview] = useState<string | null>(null);
|
||||
const [selectedLanguage, setSelectedLanguage] = useState("");
|
||||
|
||||
const [selectedSEO, setSelectedSEO] = useState<string>("");
|
||||
const [title, setTitle] = useState<string>("");
|
||||
const [selectedAdvConfig, setSelectedAdvConfig] = useState<string>("");
|
||||
|
|
@ -119,18 +117,14 @@ export default function FormImage() {
|
|||
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
||||
const [selectedWritingStyle, setSelectedWritingStyle] =
|
||||
useState("professional");
|
||||
const [editorContent, setEditorContent] = useState(""); // Untuk original editor
|
||||
const [editorContent, setEditorContent] = useState("");
|
||||
const [rewriteEditorContent, setRewriteEditorContent] = useState("");
|
||||
const [selectedSize, setSelectedSize] = useState("");
|
||||
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("");
|
||||
|
||||
const [isContentRewriteClicked, setIsContentRewriteClicked] = useState(false);
|
||||
|
||||
const [selectedTarget, setSelectedTarget] = useState("");
|
||||
const [unitSelection, setUnitSelection] = useState({
|
||||
allUnit: false,
|
||||
|
|
@ -147,7 +141,6 @@ export default function FormImage() {
|
|||
const [isStartUpload, setIsStartUpload] = useState(false);
|
||||
const [counterProgress, setCounterProgress] = useState(0);
|
||||
const [showRewriteEditor, setShowRewriteEditor] = useState(false);
|
||||
|
||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||
const [filesTemp, setFilesTemp] = useState<File[]>([]);
|
||||
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
||||
|
|
@ -1246,6 +1239,7 @@ export default function FormImage() {
|
|||
name="files"
|
||||
render={({ field }) => {
|
||||
const maxSize = 100 * 1024 * 1024;
|
||||
const [previews, setPreviews] = useState<string[]>([]);
|
||||
|
||||
const { getRootProps, getInputProps, fileRejections } =
|
||||
useDropzone({
|
||||
|
|
@ -1254,12 +1248,40 @@ export default function FormImage() {
|
|||
"image/png": [".png"],
|
||||
},
|
||||
maxSize,
|
||||
multiple: false,
|
||||
multiple: true, // <- Set true jika ingin lebih dari satu
|
||||
onDrop: (acceptedFiles) => {
|
||||
field.onChange(acceptedFiles);
|
||||
const currentFiles = [
|
||||
...(field.value || []),
|
||||
...acceptedFiles,
|
||||
];
|
||||
field.onChange(currentFiles);
|
||||
|
||||
const newPreviews = acceptedFiles.map((file) =>
|
||||
URL.createObjectURL(file)
|
||||
);
|
||||
setPreviews((prev) => [...prev, ...newPreviews]);
|
||||
},
|
||||
});
|
||||
|
||||
// Clean up URL on unmount
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
previews.forEach((url) => URL.revokeObjectURL(url));
|
||||
};
|
||||
}, [previews]);
|
||||
|
||||
const handleRemoveFile = (indexToRemove: number) => {
|
||||
const updatedFiles = [...field.value];
|
||||
updatedFiles.splice(indexToRemove, 1);
|
||||
|
||||
const updatedPreviews = [...previews];
|
||||
URL.revokeObjectURL(updatedPreviews[indexToRemove]); // Clean up
|
||||
updatedPreviews.splice(indexToRemove, 1);
|
||||
|
||||
field.onChange(updatedFiles);
|
||||
setPreviews(updatedPreviews);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="py-3 space-y-2">
|
||||
<Label>
|
||||
|
|
@ -1281,28 +1303,52 @@ export default function FormImage() {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{field.value && field.value.length > 0 && (
|
||||
<>
|
||||
<ul className="mt-2 text-sm">
|
||||
{field.value.map((file, idx) => (
|
||||
<li key={idx}>
|
||||
{file.name} (
|
||||
{(file.size / (1024 * 1024)).toFixed(2)} MB)
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
<div className="flex justify-end mt-2">
|
||||
<div className="mt-3 space-y-3">
|
||||
{field.value.map((file: File, idx: number) => (
|
||||
<div
|
||||
key={idx}
|
||||
className="flex items-center gap-4 border p-2 rounded-md relative"
|
||||
>
|
||||
<img
|
||||
src={previews[idx]}
|
||||
alt={`preview-${idx}`}
|
||||
className="w-24 h-24 object-cover rounded border"
|
||||
/>
|
||||
<div className="flex-1 text-sm">
|
||||
<div className="font-medium">{file.name}</div>
|
||||
<div className="text-muted-foreground text-xs">
|
||||
{(file.size / (1024 * 1024)).toFixed(2)} MB
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="absolute top-1 right-1 text-muted-foreground hover:text-red-500"
|
||||
onClick={() => handleRemoveFile(idx)}
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
<div className="flex justify-end">
|
||||
<Button
|
||||
type="button"
|
||||
color="destructive"
|
||||
onClick={() => field.onChange([])}
|
||||
variant="default"
|
||||
onClick={() => {
|
||||
field.onChange([]);
|
||||
previews.forEach((url) =>
|
||||
URL.revokeObjectURL(url)
|
||||
);
|
||||
setPreviews([]);
|
||||
}}
|
||||
>
|
||||
{t("remove-all", {
|
||||
defaultValue: "Remove All",
|
||||
})}
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{errors.files?.message && (
|
||||
|
|
|
|||
|
|
@ -836,7 +836,7 @@
|
|||
"output-task": "Task Output",
|
||||
"attachment": "Attachment",
|
||||
"image": "Image",
|
||||
"audio-visual": "Audio Visual",
|
||||
"audio-visual": "Video",
|
||||
"text": "Text",
|
||||
"audio": "Audio",
|
||||
"voice-note": "Voice Note",
|
||||
|
|
@ -855,7 +855,9 @@
|
|||
"coverage-area": "Coverage Area",
|
||||
"only": "Only .jpg, .jpeg, .png files are allowed",
|
||||
"size": "File too large. Max 100MB",
|
||||
"onlyVd": "Upload files with mp4 or mov Maximum size 100mb."
|
||||
|
||||
"onlyVd": "Upload files with mp4 or mov Maximum size 100mb.",
|
||||
"searchTitle": "Find Title...",
|
||||
"selectFilter": "Select a Filter",
|
||||
"noResult": "No results."
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -856,6 +856,9 @@
|
|||
"coverage-area": "Cakupan Wilayah",
|
||||
"only": "Hanya file .jpg, .jpeg, .png yang diizinkan",
|
||||
"size": "File terlalu besar. Maksimal 100MB",
|
||||
"onlyVd": "Upload file dengan mp4 atau mov Ukuran maksimal 100mb."
|
||||
"onlyVd": "Upload file dengan mp4 atau mov Ukuran maksimal 100mb.",
|
||||
"searchTitle": "Cari Judul...",
|
||||
"selectFilter": "Pilih Filter",
|
||||
"noResult": "Tidak ada hasil"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue