update filter status admin, fix button delete

This commit is contained in:
Anang Yusman 2025-07-24 16:36:05 +08:00
parent f878ab405e
commit 5216bcd8a5
6 changed files with 193 additions and 101 deletions

View File

@ -132,29 +132,36 @@ const useTableColumns = () => {
accessorKey: "statusName", accessorKey: "statusName",
header: "Status", header: "Status",
cell: ({ row }) => { cell: ({ row }) => {
const statusColors: Record<string, string> = { const statusId = Number(row.original?.statusId);
diterima: "bg-green-100 text-green-600", const reviewedAtLevel = row.original?.reviewedAtLevel || "";
"menunggu review": "bg-orange-100 text-orange-600", const creatorGroupLevelId = Number(row.original?.creatorGroupLevelId);
const needApprovalFromLevel = Number(
row.original?.needApprovalFromLevel
);
const userHasReviewed = reviewedAtLevel.includes(`:${userLevelId}:`);
const isCreator = creatorGroupLevelId === Number(userLevelId);
const isWaitingForReview =
statusId === 2 && !userHasReviewed && !isCreator;
const isApprovalNeeded =
statusId === 1 && needApprovalFromLevel === Number(userLevelId);
const label =
isWaitingForReview || isApprovalNeeded
? "Menunggu Review"
: statusId === 2
? "Diterima"
: row.original?.statusName;
const colors: Record<string, string> = {
"Menunggu Review": "bg-orange-100 text-orange-600",
Diterima: "bg-green-100 text-green-600",
default: "bg-red-200 text-red-600",
}; };
const colors = [ const statusStyles = colors[label] || colors.default;
"bg-orange-100 text-orange-600",
"bg-orange-100 text-orange-600",
"bg-green-100 text-green-600",
"bg-blue-100 text-blue-600",
"bg-red-200 text-red-600",
];
const status =
Number(row.original?.statusId) == 2 &&
row.original?.reviewedAtLevel !== null &&
!row.original?.reviewedAtLevel?.includes(`:${userLevelId}:`) &&
Number(row.original?.creatorGroupLevelId) != Number(userLevelId)
? "1"
: row.original?.statusId;
const statusStyles =
colors[Number(status)] || "bg-red-200 text-red-600";
// const statusStyles = statusColors[status] || "bg-red-200 text-red-600";
return ( return (
<Badge <Badge
@ -163,18 +170,7 @@ const useTableColumns = () => {
statusStyles statusStyles
)} )}
> >
{(Number(row.original?.statusId) == 2 && {label}
!row.original?.reviewedAtLevel !== null &&
!row.original?.reviewedAtLevel?.includes(
`:${Number(userLevelId)}:`
) &&
Number(row.original?.creatorGroupLevelId) !=
Number(userLevelId)) ||
(Number(row.original?.statusId) == 1 &&
Number(row.original?.needApprovalFromLevel) ==
Number(userLevelId))
? "Menunggu Review"
: row.original?.statusName}{" "}
</Badge> </Badge>
); );
}, },

View File

@ -24,6 +24,7 @@ import {
} from "@/components/ui/table"; } from "@/components/ui/table";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { import {
ChevronDown,
ChevronLeft, ChevronLeft,
ChevronRight, ChevronRight,
Eye, Eye,
@ -61,6 +62,7 @@ import {
SelectValue, SelectValue,
} from "@/components/ui/select"; } from "@/components/ui/select";
import { useTranslations } from "next-intl"; import { useTranslations } from "next-intl";
import { Label } from "@/components/ui/label";
type StatusFilter = string[]; type StatusFilter = string[];
@ -87,7 +89,8 @@ const ContentTable = () => {
const userLevelId = getCookiesDecrypt("ulie"); const userLevelId = getCookiesDecrypt("ulie");
const [categories, setCategories] = React.useState<string[]>(); const [categories, setCategories] = React.useState<string[]>();
const [categoryFilter, setCategoryFilter] = React.useState<string[]>([]); const [categoryFilter, setCategoryFilter] = React.useState<string[]>([]);
const [statusFilter, setStatusFilter] = React.useState<StatusFilter>([]); // const [statusFilter, setStatusFilter] = React.useState<StatusFilter>([]);
const [statusFilter, setStatusFilter] = React.useState<any[]>([]);
const [startDateString, setStartDateString] = React.useState<string>(""); const [startDateString, setStartDateString] = React.useState<string>("");
const [endDateString, setEndDateString] = React.useState<string>(""); const [endDateString, setEndDateString] = React.useState<string>("");
const [filterByCreator, setFilterByCreator] = React.useState<string>(""); const [filterByCreator, setFilterByCreator] = React.useState<string>("");
@ -168,6 +171,14 @@ const ContentTable = () => {
table.getColumn("judul")?.setFilterValue(e.target.value); table.getColumn("judul")?.setFilterValue(e.target.value);
}; };
function handleStatusCheckboxChange(value: any) {
setStatusFilter((prev: any) =>
prev.includes(value)
? prev.filter((status: any) => status !== value)
: [...prev, value]
);
}
return ( return (
<div className="w-full overflow-x-auto"> <div className="w-full overflow-x-auto">
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between md:flex-row md:items-center md:justify-between lg:flex-row items-start lg:justify-between lg:items-center px-5"> <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between md:flex-row md:items-center md:justify-between lg:flex-row items-start lg:justify-between lg:items-center px-5">
@ -185,31 +196,14 @@ const ContentTable = () => {
/> />
</InputGroup> </InputGroup>
</div> </div>
<div className=" items-center gap-3 w-full md:w-[200px]"> <div className="flex flex-row gap-3">
{/* <Select <div className=" items-center gap-3 w-full md:w-[152px] border border-black rounded-lg">
onValueChange={(value) => {
setStatusFilter([value]);
}}
>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Select a Filter Status" />
</SelectTrigger>
<SelectContent>
<SelectGroup>
<SelectLabel>Status</SelectLabel>
<SelectItem value="1">Menunggu Review</SelectItem>
<SelectItem value="2">Diterima</SelectItem>
<SelectItem value="3">Minta Update</SelectItem>
<SelectItem value="4">Ditolak</SelectItem>
</SelectGroup>
</SelectContent>
</Select> */}
<Select <Select
onValueChange={(value) => { onValueChange={(value) => {
setFileTypeFilter([value]); setFileTypeFilter([value]);
}} }}
> >
<SelectTrigger className="w-full lg:w-[180px]"> <SelectTrigger className="w-full lg:w-[150px]">
<SelectValue placeholder={t("selectFilter")} /> <SelectValue placeholder={t("selectFilter")} />
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
@ -218,11 +212,73 @@ const ContentTable = () => {
<SelectItem value="1">{t("image")}</SelectItem> <SelectItem value="1">{t("image")}</SelectItem>
<SelectItem value="2">{t("audio-visual")}</SelectItem> <SelectItem value="2">{t("audio-visual")}</SelectItem>
<SelectItem value="3">{t("text")}</SelectItem> <SelectItem value="3">{t("text")}</SelectItem>
<SelectItem value="4">Audio</SelectItem> <SelectItem value="4">{t("audio")}</SelectItem>
</SelectGroup> </SelectGroup>
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="outline" className="ml-auto" size="md">
Filter <ChevronDown />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent
align="end"
className="w-64 h-[150px] overflow-y-auto"
>
<Label className="ml-2 mt-2">Status</Label>
<div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-2"
className="mr-2"
checked={statusFilter.includes(1)}
onChange={() => handleStatusCheckboxChange(1)}
/>
<label htmlFor="status-2" className="text-sm">
Menunggu Review
</label>
</div>
<div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-2"
className="mr-2"
checked={statusFilter.includes(2)}
onChange={() => handleStatusCheckboxChange(2)}
/>
<label htmlFor="status-2" className="text-sm">
Diterima
</label>
</div>
<div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-3"
className="mr-2"
checked={statusFilter.includes(3)}
onChange={() => handleStatusCheckboxChange(3)}
/>
<label htmlFor="status-3" className="text-sm">
Minta Update
</label>
</div>
<div className="flex items-center px-4 py-1">
<input
type="checkbox"
id="status-4"
className="mr-2"
checked={statusFilter.includes(4)}
onChange={() => handleStatusCheckboxChange(4)}
/>
<label htmlFor="status-4" className="text-sm">
Ditolak
</label>
</div>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div> </div>
<Table className="overflow-hidden mt-3"> <Table className="overflow-hidden mt-3">
<TableHeader> <TableHeader>

View File

@ -570,6 +570,7 @@ export default function FormAudioUpdate() {
</div> </div>
<Button <Button
type="button"
size="icon" size="icon"
color="destructive" color="destructive"
variant="outline" variant="outline"
@ -668,7 +669,9 @@ export default function FormAudioUpdate() {
<div className="flex flex-col lg:flex-row gap-10"> <div className="flex flex-col lg:flex-row gap-10">
<Card className="w-full lg:w-8/12"> <Card className="w-full lg:w-8/12">
<div className="px-6 py-6"> <div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">{t("form-audio", { defaultValue: "Form Audio" })}</p> <p className="text-lg font-semibold mb-3">
{t("form-audio", { defaultValue: "Form Audio" })}
</p>
<div className="gap-5 mb-5"> <div className="gap-5 mb-5">
{/* Input Title */} {/* Input Title */}
<div className="space-y-2 py-3"> <div className="space-y-2 py-3">
@ -707,7 +710,11 @@ export default function FormAudioUpdate() {
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{/* Show the category from details if it doesn't exist in categories list */} {/* Show the category from details if it doesn't exist in categories list */}
{detail && !categories.find(cat => String(cat.id) === String(detail.category.id)) && ( {detail &&
!categories.find(
(cat) =>
String(cat.id) === String(detail.category.id)
) && (
<SelectItem <SelectItem
key={String(detail.category.id)} key={String(detail.category.id)}
value={String(detail.category.id)} value={String(detail.category.id)}
@ -730,7 +737,9 @@ export default function FormAudioUpdate() {
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("description", { defaultValue: "Description" })}</Label> <Label>
{t("description", { defaultValue: "Description" })}
</Label>
<Controller <Controller
control={control} control={control}
name="description" name="description"
@ -745,7 +754,9 @@ export default function FormAudioUpdate() {
)} )}
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("select-file", { defaultValue: "Select File" })}</Label> <Label>
{t("select-file", { defaultValue: "Select File" })}
</Label>
{/* <Input {/* <Input
id="fileInput" id="fileInput"
type="file" type="file"
@ -761,7 +772,9 @@ export default function FormAudioUpdate() {
{t("drag-file", { defaultValue: "Drag File" })} {t("drag-file", { defaultValue: "Drag File" })}
</h4> </h4>
<div className=" text-xs text-muted-foreground"> <div className=" text-xs text-muted-foreground">
{t("upload-file-audio-max", { defaultValue: "Upload File Audio Max" })} {t("upload-file-audio-max", {
defaultValue: "Upload File Audio Max",
})}
</div> </div>
</div> </div>
</div> </div>
@ -1010,7 +1023,9 @@ export default function FormAudioUpdate() {
</div> </div>
<div className="px-3 py-3"> <div className="px-3 py-3">
<div className="flex flex-col gap-6 space-y-2"> <div className="flex flex-col gap-6 space-y-2">
<Label>{t("publish-target", { defaultValue: "Publish Target" })}</Label> <Label>
{t("publish-target", { defaultValue: "Publish Target" })}
</Label>
{options.map((option: Option) => ( {options.map((option: Option) => (
<div key={option.id} className="flex gap-2 items-center"> <div key={option.id} className="flex gap-2 items-center">
<Checkbox <Checkbox

View File

@ -548,6 +548,7 @@ export default function FormImageUpdate() {
</div> </div>
<Button <Button
type="button"
size="icon" size="icon"
color="destructive" color="destructive"
variant="outline" variant="outline"

View File

@ -552,6 +552,7 @@ export default function FormTeksUpdate() {
</div> </div>
<Button <Button
type="button"
size="icon" size="icon"
color="destructive" color="destructive"
variant="outline" variant="outline"
@ -624,7 +625,9 @@ export default function FormTeksUpdate() {
<div className="flex flex-col lg:flex-row gap-10"> <div className="flex flex-col lg:flex-row gap-10">
<Card className="w-full lg:w-8/12"> <Card className="w-full lg:w-8/12">
<div className="px-6 py-6"> <div className="px-6 py-6">
<p className="text-lg font-semibold mb-3">{t("form-text", { defaultValue: "Form Text" })}</p> <p className="text-lg font-semibold mb-3">
{t("form-text", { defaultValue: "Form Text" })}
</p>
<div className="gap-5 mb-5"> <div className="gap-5 mb-5">
{/* Input Title */} {/* Input Title */}
<div className="space-y-2 py-3"> <div className="space-y-2 py-3">
@ -663,7 +666,11 @@ export default function FormTeksUpdate() {
</SelectTrigger> </SelectTrigger>
<SelectContent> <SelectContent>
{/* Show the category from details if it doesn't exist in categories list */} {/* Show the category from details if it doesn't exist in categories list */}
{detail && !categories.find(cat => String(cat.id) === String(detail.category.id)) && ( {detail &&
!categories.find(
(cat) =>
String(cat.id) === String(detail.category.id)
) && (
<SelectItem <SelectItem
key={String(detail.category.id)} key={String(detail.category.id)}
value={String(detail.category.id)} value={String(detail.category.id)}
@ -685,7 +692,9 @@ export default function FormTeksUpdate() {
</div> </div>
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("description", { defaultValue: "Description" })}</Label> <Label>
{t("description", { defaultValue: "Description" })}
</Label>
<Controller <Controller
control={control} control={control}
name="description" name="description"
@ -700,7 +709,9 @@ export default function FormTeksUpdate() {
)} )}
</div> </div>
<div className="py-3 space-y-2"> <div className="py-3 space-y-2">
<Label>{t("select-file", { defaultValue: "Select File" })}</Label> <Label>
{t("select-file", { defaultValue: "Select File" })}
</Label>
{/* <Input {/* <Input
id="fileInput" id="fileInput"
type="file" type="file"
@ -716,7 +727,9 @@ export default function FormTeksUpdate() {
{t("drag-file", { defaultValue: "Drag File" })} {t("drag-file", { defaultValue: "Drag File" })}
</h4> </h4>
<div className=" text-xs text-muted-foreground"> <div className=" text-xs text-muted-foreground">
{t("upload-file-text-max", { defaultValue: "Upload File Text Max" })} {t("upload-file-text-max", {
defaultValue: "Upload File Text Max",
})}
</div> </div>
</div> </div>
</div> </div>
@ -725,7 +738,9 @@ export default function FormTeksUpdate() {
<div>{fileList}</div> <div>{fileList}</div>
<div className=" flex justify-between gap-2"> <div className=" flex justify-between gap-2">
<div className="flex flex-row items-center gap-3 py-3"> <div className="flex flex-row items-center gap-3 py-3">
<Label>{t("watermark", { defaultValue: "Watermark" })}</Label> <Label>
{t("watermark", { defaultValue: "Watermark" })}
</Label>
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
<Switch defaultChecked color="primary" id="c2" /> <Switch defaultChecked color="primary" id="c2" />
</div> </div>
@ -765,7 +780,9 @@ export default function FormTeksUpdate() {
rel="noopener noreferrer" rel="noopener noreferrer"
className="text-blue-500 text-sm" className="text-blue-500 text-sm"
> >
{t("view-file", { defaultValue: "View File" })} {t("view-file", {
defaultValue: "View File",
})}
</a> </a>
</div> </div>
<div> <div>
@ -783,7 +800,9 @@ export default function FormTeksUpdate() {
} }
className="form-checkbox" className="form-checkbox"
/> />
<span>{t("all", { defaultValue: "All" })}</span> <span>
{t("all", { defaultValue: "All" })}
</span>
</Label> </Label>
</div> </div>
<div> <div>
@ -923,7 +942,9 @@ export default function FormTeksUpdate() {
</div> </div>
<div className="px-3 py-3"> <div className="px-3 py-3">
<div className="flex flex-col gap-6"> <div className="flex flex-col gap-6">
<Label>{t("publish-target", { defaultValue: "Publish Target" })}</Label> <Label>
{t("publish-target", { defaultValue: "Publish Target" })}
</Label>
{options.map((option) => ( {options.map((option) => (
<div key={option.id} className="flex gap-2 items-center"> <div key={option.id} className="flex gap-2 items-center">
<Checkbox <Checkbox
@ -944,7 +965,9 @@ export default function FormTeksUpdate() {
</div> </div>
<div className="px-3 py-3 flex flex-row items-center text-blue-500 gap-2 text-sm"> <div className="px-3 py-3 flex flex-row items-center text-blue-500 gap-2 text-sm">
<MailIcon /> <MailIcon />
<p className="">{t("suggestion-box", { defaultValue: "Suggestion Box" })} (0)</p> <p className="">
{t("suggestion-box", { defaultValue: "Suggestion Box" })} (0)
</p>
</div> </div>
<div className="px-3 py-3"> <div className="px-3 py-3">
<p>{t("information", { defaultValue: "Information" })}:</p> <p>{t("information", { defaultValue: "Information" })}:</p>

View File

@ -626,6 +626,7 @@ export default function FormVideoUpdate() {
</div> </div>
<Button <Button
type="button"
size="icon" size="icon"
color="destructive" color="destructive"
variant="outline" variant="outline"