fixing
This commit is contained in:
commit
6490679901
|
|
@ -26,12 +26,13 @@ import {
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
AdministrationLevelList,
|
AdministrationLevelList,
|
||||||
|
checkRolePlacementsAvailability,
|
||||||
getListCompetencies,
|
getListCompetencies,
|
||||||
getListExperiences,
|
getListExperiences,
|
||||||
saveUserInternal,
|
saveUserInternal,
|
||||||
saveUserRolePlacements,
|
saveUserRolePlacements,
|
||||||
} from "@/service/management-user/management-user";
|
} from "@/service/management-user/management-user";
|
||||||
import { loading } from "@/config/swal";
|
import { error, loading } from "@/config/swal";
|
||||||
import { Eye, EyeOff } from "lucide-react";
|
import { Eye, EyeOff } from "lucide-react";
|
||||||
|
|
||||||
const FormSchema = z.object({
|
const FormSchema = z.object({
|
||||||
|
|
@ -134,6 +135,26 @@ export default function AddExpertForm() {
|
||||||
};
|
};
|
||||||
|
|
||||||
loading();
|
loading();
|
||||||
|
|
||||||
|
// check availability first
|
||||||
|
var placementArr: any[] = [];
|
||||||
|
placementRows.forEach((row: any) => {
|
||||||
|
placementArr.push({
|
||||||
|
roleId: Number(row.roleId),
|
||||||
|
userLevelId: Number(row.userLevelId),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const dataReqAvail = {
|
||||||
|
placements: placementArr,
|
||||||
|
};
|
||||||
|
const resAvail = await checkRolePlacementsAvailability(dataReqAvail);
|
||||||
|
if (resAvail?.error) {
|
||||||
|
close();
|
||||||
|
error(resAvail.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
const res = await saveUserInternal(dataReq);
|
const res = await saveUserInternal(dataReq);
|
||||||
const resData = res?.data?.data;
|
const resData = res?.data?.data;
|
||||||
const userProfileId = resData?.id;
|
const userProfileId = resData?.id;
|
||||||
|
|
|
||||||
|
|
@ -49,11 +49,11 @@ const columns: ColumnDef<any>[] = [
|
||||||
header: "Jumlah Amplifikasi",
|
header: "Jumlah Amplifikasi",
|
||||||
cell: ({ row }) => <span>{row.getValue("link")}</span>,
|
cell: ({ row }) => <span>{row.getValue("link")}</span>,
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// accessorKey: "status",
|
accessorKey: "status",
|
||||||
// header: "Status",
|
header: "Status",
|
||||||
// cell: ({ row }) => <span>{row.getValue("status")}</span>,
|
cell: ({ row }) => <span>{row.getValue("status")}</span>,
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "date",
|
accessorKey: "date",
|
||||||
header: "Tanggal Penarikan",
|
header: "Tanggal Penarikan",
|
||||||
|
|
@ -77,12 +77,12 @@ const columns: ColumnDef<any>[] = [
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<DropdownMenuContent className="p-0" align="end">
|
||||||
<Link
|
<Link href={`/admin/media-tracking/detail/${row.original.id}`}>
|
||||||
href={`/admin/media-tracking/detail/${row.original.id}`}
|
|
||||||
>
|
|
||||||
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||||
<Eye className="w-4 h-4 me-1.5" />
|
<Eye className="w-4 h-4 me-1.5" />
|
||||||
Detail
|
View
|
||||||
|
{row.original.mediaUpload.fileType.secondaryName &&
|
||||||
|
row.original.mediaUpload.fileType.secondaryName.toLowerCase()}
|
||||||
</DropdownMenuItem>
|
</DropdownMenuItem>
|
||||||
</Link>
|
</Link>
|
||||||
</DropdownMenuContent>
|
</DropdownMenuContent>
|
||||||
|
|
|
||||||
|
|
@ -58,16 +58,6 @@ const columns: ColumnDef<any>[] = [
|
||||||
<span>{formatDateToIndonesian(row.getValue("createdAt"))}</span>
|
<span>{formatDateToIndonesian(row.getValue("createdAt"))}</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
accessorKey: "isStaticBanner",
|
|
||||||
header: "Static Banner",
|
|
||||||
cell: ({ row }) => (
|
|
||||||
<StaticToogle
|
|
||||||
id={row.original.id}
|
|
||||||
initChecked={row.original.isStaticBanner}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
accessorKey: "statusName",
|
accessorKey: "statusName",
|
||||||
header: "Status Banner",
|
header: "Status Banner",
|
||||||
|
|
@ -75,7 +65,6 @@ const columns: ColumnDef<any>[] = [
|
||||||
<StatusToogle id={row.original.id} initChecked={row.original.isBanner} />
|
<StatusToogle id={row.original.id} initChecked={row.original.isBanner} />
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: "actions",
|
id: "actions",
|
||||||
accessorKey: "action",
|
accessorKey: "action",
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ import CustomPagination from "@/components/table/custom-pagination";
|
||||||
const ContentListBanner = () => {
|
const ContentListBanner = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const [showData, setShowData] = React.useState("10");
|
const [showData, setShowData] = React.useState("9");
|
||||||
const [categories, setCategories] = React.useState<any>();
|
const [categories, setCategories] = React.useState<any>();
|
||||||
const [data, setData] = React.useState<any[]>([]);
|
const [data, setData] = React.useState<any[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
|
|
@ -412,7 +412,7 @@ const ContentListBanner = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<img
|
<img
|
||||||
src={item.thumbnailLink || "/placeholder.jpg"}
|
src={item.smallThumbnailLink || "/placeholder.jpg"}
|
||||||
alt={item.title}
|
alt={item.title}
|
||||||
className="w-full h-48 object-cover"
|
className="w-full h-48 object-cover"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ export default function AdminBanner() {
|
||||||
: "bg-white text-black "
|
: "bg-white text-black "
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Kontent
|
Konten
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
rounded="md"
|
rounded="md"
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,16 @@ const columns: ColumnDef<any>[] = [
|
||||||
</span>
|
</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
id: "created",
|
||||||
|
accessorKey: "created",
|
||||||
|
header: "Dibuat Oleh",
|
||||||
|
cell: ({ row }) => (
|
||||||
|
<div className="flex flex-col items-center">
|
||||||
|
<span className="text-sm text-gray-500">{row.original.createdByName}</span><span className="text-xs font-bold">({row.original.createdByUserLevelName})</span>
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
id: "actions",
|
id: "actions",
|
||||||
accessorKey: "action",
|
accessorKey: "action",
|
||||||
|
|
|
||||||
|
|
@ -58,24 +58,13 @@ const columns: ColumnDef<any>[] = [
|
||||||
<span>{formatDateToIndonesian(row.getValue("createdAt"))}</span>
|
<span>{formatDateToIndonesian(row.getValue("createdAt"))}</span>
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
{
|
|
||||||
accessorKey: "isStaticBanner",
|
|
||||||
header: "Static Banner",
|
|
||||||
cell: ({ row }) => (
|
|
||||||
<StaticToogle
|
|
||||||
id={row.original.id}
|
|
||||||
initChecked={row.original.isStaticBanner}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
accessorKey: "statusName",
|
accessorKey: "statusName",
|
||||||
header: "Status Banner",
|
header: "Status Pop Up",
|
||||||
cell: ({ row }) => (
|
cell: ({ row }) => (
|
||||||
<StatusToogle id={row.original.id} initChecked={row.original.isBanner} />
|
<StatusToogle id={row.original.id} initChecked={row.original.isInterstitial} />
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
id: "actions",
|
id: "actions",
|
||||||
accessorKey: "action",
|
accessorKey: "action",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { Switch } from "@/components/ui/switch";
|
import { Switch } from "@/components/ui/switch";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
import { useToast } from "@/components/ui/use-toast";
|
||||||
import { useRouter } from "@/i18n/routing";
|
import { useRouter } from "@/i18n/routing";
|
||||||
import { setBanner } from "@/service/settings/settings";
|
import { setBanner, setPopUp } from "@/service/settings/settings";
|
||||||
|
|
||||||
export default function StatusToogle(props: {
|
export default function StatusToogle(props: {
|
||||||
id: number;
|
id: number;
|
||||||
|
|
@ -12,7 +12,7 @@ export default function StatusToogle(props: {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const disableBanner = async () => {
|
const disableBanner = async () => {
|
||||||
const response = await setBanner(id, false);
|
const response = await setPopUp(id, false);
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
toast({
|
toast({
|
||||||
|
|
@ -25,7 +25,7 @@ export default function StatusToogle(props: {
|
||||||
toast({
|
toast({
|
||||||
title: "Success ",
|
title: "Success ",
|
||||||
});
|
});
|
||||||
router.push("/admin/settings/banner?dataChange=true");
|
router.push("/admin/settings/popup?dataChange=true");
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Switch
|
<Switch
|
||||||
|
|
|
||||||
|
|
@ -74,7 +74,7 @@ import CustomPagination from "@/components/table/custom-pagination";
|
||||||
const ContentListPopUp = () => {
|
const ContentListPopUp = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const searchParams = useSearchParams();
|
const searchParams = useSearchParams();
|
||||||
const [showData, setShowData] = React.useState("10");
|
const [showData, setShowData] = React.useState("9");
|
||||||
const [categories, setCategories] = React.useState<any>();
|
const [categories, setCategories] = React.useState<any>();
|
||||||
const [data, setData] = React.useState<any[]>([]);
|
const [data, setData] = React.useState<any[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
|
|
@ -433,7 +433,7 @@ const ContentListPopUp = () => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<img
|
<img
|
||||||
src={item.thumbnailLink || "/placeholder.jpg"}
|
src={item.smallThumbnailLink || "/placeholder.jpg"}
|
||||||
alt={item.title}
|
alt={item.title}
|
||||||
className="w-full h-48 object-cover"
|
className="w-full h-48 object-cover"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ export default function AdminPopup() {
|
||||||
: "bg-white text-black "
|
: "bg-white text-black "
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
Kontent
|
Konten
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
rounded="md"
|
rounded="md"
|
||||||
|
|
|
||||||
|
|
@ -9,12 +9,7 @@ import { Button } from "@/components/ui/button";
|
||||||
import { Label } from "@/components/ui/label";
|
import { Label } from "@/components/ui/label";
|
||||||
import { Calendar } from "@/components/ui/calendar";
|
import { Calendar } from "@/components/ui/calendar";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import {
|
import { Book, CheckCheck, Plus, Timer } from "lucide-react";
|
||||||
Book,
|
|
||||||
CheckCheck,
|
|
||||||
Plus,
|
|
||||||
Timer,
|
|
||||||
} from "lucide-react";
|
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { EventContentArg } from "@fullcalendar/core";
|
import { EventContentArg } from "@fullcalendar/core";
|
||||||
import EventModal from "./event-modal";
|
import EventModal from "./event-modal";
|
||||||
|
|
@ -237,9 +232,12 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
|
|
||||||
const allCategoryId = ["1", "2", "3", "4", "5"];
|
const allCategoryId = ["1", "2", "3", "4", "5"];
|
||||||
// Cek apakah SEMUA validTypeIds ada di typeIdsInData
|
// Cek apakah SEMUA validTypeIds ada di typeIdsInData
|
||||||
const hasAllCategories = allCategoryId.every(categoryId => selectedCategory.includes(categoryId));
|
const hasAllCategories = allCategoryId.every((categoryId) =>
|
||||||
|
selectedCategory.includes(categoryId)
|
||||||
|
);
|
||||||
|
|
||||||
return eventCategories?.some((cat: string) =>
|
return eventCategories?.some(
|
||||||
|
(cat: string) =>
|
||||||
selectedCategory.includes(cat) || (hasAllCategories && cat == "0")
|
selectedCategory.includes(cat) || (hasAllCategories && cat == "0")
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
@ -266,7 +264,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCategorySelection = (category: string) => {
|
const handleCategorySelection = (category: string) => {
|
||||||
setSelectedCategory(prev => {
|
setSelectedCategory((prev) => {
|
||||||
if (prev.includes(category)) {
|
if (prev.includes(category)) {
|
||||||
return prev.filter((c) => c !== category);
|
return prev.filter((c) => c !== category);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -346,15 +344,22 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
|
|
||||||
const renderEventContent = (eventInfo: any) => {
|
const renderEventContent = (eventInfo: any) => {
|
||||||
const { title } = eventInfo.event;
|
const { title } = eventInfo.event;
|
||||||
const { createdByName, isPublish, calendar } = eventInfo.event.extendedProps;
|
const { createdByName, isPublish, calendar } =
|
||||||
|
eventInfo.event.extendedProps;
|
||||||
const bgColor = getEventColor(calendar);
|
const bgColor = getEventColor(calendar);
|
||||||
const colorList = getEventColorList(calendar);
|
const colorList = getEventColorList(calendar);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={`w-full p-2 mb-2 rounded-md text-white text-sm flex justify-between items-stretch ${bgColor}`}>
|
<div
|
||||||
|
className={`w-full p-2 mb-2 rounded-md text-white text-sm flex justify-between items-stretch ${bgColor}`}
|
||||||
|
>
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<div className="flex flex-row items-center">
|
<div className="flex flex-row items-center">
|
||||||
{isPublish === true ? <CheckCheck size={15} /> : <Timer size={15} />}
|
{isPublish === true ? (
|
||||||
|
<CheckCheck size={15} />
|
||||||
|
) : (
|
||||||
|
<Timer size={15} />
|
||||||
|
)}
|
||||||
<p className="ml-1">{title}</p>
|
<p className="ml-1">{title}</p>
|
||||||
</div>
|
</div>
|
||||||
<p className="ml-1 text-xs text-start mt-2">
|
<p className="ml-1 text-xs text-start mt-2">
|
||||||
|
|
@ -461,8 +466,12 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
text={event.title}
|
text={event.title}
|
||||||
createdBy={event.createdByName}
|
createdBy={event.createdByName}
|
||||||
isPublish={event.isPublish}
|
isPublish={event.isPublish}
|
||||||
bgColor={getEventColor(event.agendaType as EventType)}
|
bgColor={getEventColor(
|
||||||
colorList={getEventColorList(event.agendaType as EventType)}
|
event.agendaType as EventType
|
||||||
|
)}
|
||||||
|
colorList={getEventColorList(
|
||||||
|
event.agendaType as EventType
|
||||||
|
)}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -593,7 +602,9 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
className={category.className}
|
className={category.className}
|
||||||
id={category.label}
|
id={category.label}
|
||||||
checked={selectedCategory.includes(category.value)}
|
checked={selectedCategory.includes(category.value)}
|
||||||
onCheckedChange={() => handleCategorySelection(category.value)}
|
onCheckedChange={() =>
|
||||||
|
handleCategorySelection(category.value)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
<Label htmlFor={category.label}>{category.label}</Label>
|
<Label htmlFor={category.label}>{category.label}</Label>
|
||||||
</li>
|
</li>
|
||||||
|
|
@ -605,7 +616,12 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
<Card className="col-span-12 lg:col-span-8 2xl:col-span-9 pt-5">
|
<Card className="col-span-12 lg:col-span-8 2xl:col-span-9 pt-5">
|
||||||
<CardContent className="dashcode-app-calendar">
|
<CardContent className="dashcode-app-calendar">
|
||||||
<FullCalendar
|
<FullCalendar
|
||||||
plugins={[dayGridPlugin, timeGridPlugin, interactionPlugin, listPlugin]}
|
plugins={[
|
||||||
|
dayGridPlugin,
|
||||||
|
timeGridPlugin,
|
||||||
|
interactionPlugin,
|
||||||
|
listPlugin,
|
||||||
|
]}
|
||||||
headerToolbar={{
|
headerToolbar={{
|
||||||
left: "prev,next today",
|
left: "prev,next today",
|
||||||
center: "title",
|
center: "title",
|
||||||
|
|
@ -636,7 +652,9 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
|
||||||
handleDateChange(info.view.currentStart, info.view.currentEnd);
|
handleDateChange(info.view.currentStart, info.view.currentEnd);
|
||||||
handleViewChange(info.view.type);
|
handleViewChange(info.view.type);
|
||||||
}}
|
}}
|
||||||
viewClassNames={activeView === "listYear" ? "hide-calendar-grid" : ""}
|
viewClassNames={
|
||||||
|
activeView === "listYear" ? "hide-calendar-grid" : ""
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{activeView === "listYear" && (
|
{activeView === "listYear" && (
|
||||||
|
|
|
||||||
|
|
@ -148,10 +148,12 @@ const EventModal = ({
|
||||||
satker: false,
|
satker: false,
|
||||||
international: false,
|
international: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [agendaType, setAgendaType] = React.useState(""); // State untuk agendaType
|
const [agendaType, setAgendaType] = React.useState(""); // State untuk agendaType
|
||||||
const [selectedPolda, setSelectedPolda] = React.useState([]); // Untuk data Polda
|
const [selectedPolda, setSelectedPolda] = useState<string[]>([]);
|
||||||
const [selectedSatker, setSelectedSatker] = React.useState([]);
|
const [selectedPolres, setSelectedPolres] = useState<string[]>([]);
|
||||||
const [selectedPolres, setSelectedPolres] = React.useState([]);
|
const [selectedSatker, setSelectedSatker] = useState<string[]>([]);
|
||||||
|
const isDetailMode = true;
|
||||||
const [wavesurfer, setWavesurfer] = useState<WaveSurfer>();
|
const [wavesurfer, setWavesurfer] = useState<WaveSurfer>();
|
||||||
const [isPlaying, setIsPlaying] = useState(false);
|
const [isPlaying, setIsPlaying] = useState(false);
|
||||||
const [isPublishing, setIsPublishing] = useState(false);
|
const [isPublishing, setIsPublishing] = useState(false);
|
||||||
|
|
@ -174,10 +176,7 @@ const EventModal = ({
|
||||||
const detail = res?.data?.data;
|
const detail = res?.data?.data;
|
||||||
setDetailData(detail);
|
setDetailData(detail);
|
||||||
|
|
||||||
const description = res?.data?.data?.description;
|
const description = detail?.description;
|
||||||
console.log("description", res?.data?.data?.description);
|
|
||||||
|
|
||||||
// Set nilai awal description ke form control
|
|
||||||
if (description) {
|
if (description) {
|
||||||
setValue("description", description);
|
setValue("description", description);
|
||||||
}
|
}
|
||||||
|
|
@ -196,17 +195,56 @@ const EventModal = ({
|
||||||
attachments?.filter((file: any) => file.fileTypeId == 4)
|
attachments?.filter((file: any) => file.fileTypeId == 4)
|
||||||
);
|
);
|
||||||
|
|
||||||
const agendaType = detail?.agendaType;
|
const rawAgendaTypes = detail?.agendaType?.split(",") || []; // ["0","1","2","3","4","5"]
|
||||||
setWilayahPublish({
|
const assignedToLevel = detail?.assignedToLevel?.split(",") || [];
|
||||||
semua: agendaType === "all",
|
|
||||||
nasional: agendaType === "mabes",
|
|
||||||
polda: agendaType === "polda",
|
|
||||||
polres: agendaType === "polres",
|
|
||||||
satker: agendaType === "satker",
|
|
||||||
international: agendaType === "international",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const wilayahState = {
|
||||||
|
semua: false,
|
||||||
|
nasional: false,
|
||||||
|
polda: false,
|
||||||
|
polres: false,
|
||||||
|
satker: false,
|
||||||
|
international: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
rawAgendaTypes.forEach((type: any) => {
|
||||||
|
switch (type) {
|
||||||
|
case "0":
|
||||||
|
wilayahState.semua = true;
|
||||||
|
break;
|
||||||
|
case "1":
|
||||||
|
wilayahState.nasional = true;
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
wilayahState.polda = true;
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
wilayahState.polres = true;
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
wilayahState.satker = true;
|
||||||
|
break;
|
||||||
|
case "5":
|
||||||
|
wilayahState.international = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
setWilayahPublish(wilayahState);
|
||||||
|
|
||||||
|
// Atur unit berdasarkan agendaType
|
||||||
|
if (rawAgendaTypes.includes("2")) {
|
||||||
|
setSelectedPolda(assignedToLevel);
|
||||||
|
}
|
||||||
|
if (rawAgendaTypes.includes("3")) {
|
||||||
|
setSelectedPolres(assignedToLevel);
|
||||||
|
}
|
||||||
|
if (rawAgendaTypes.includes("4")) {
|
||||||
|
setSelectedSatker(assignedToLevel);
|
||||||
|
}
|
||||||
|
}
|
||||||
fetchDetailData();
|
fetchDetailData();
|
||||||
}, [event, setValue]);
|
}, [event, setValue]);
|
||||||
|
|
||||||
|
|
@ -233,33 +271,39 @@ const EventModal = ({
|
||||||
|
|
||||||
const toggleWilayah = (key: string) => {
|
const toggleWilayah = (key: string) => {
|
||||||
setWilayahPublish((prev: any) => {
|
setWilayahPublish((prev: any) => {
|
||||||
const newState = { ...prev, [key]: !prev[key] };
|
let newState = { ...prev };
|
||||||
|
|
||||||
// Handle "semua" logic to check all options
|
// Jika key === semua dan sebelumnya belum aktif, aktifkan semua
|
||||||
if (key === "semua" && newState.semua) {
|
if (key === "semua") {
|
||||||
setAgendaType("all");
|
const newChecked = !prev.semua;
|
||||||
return {
|
newState = {
|
||||||
semua: true,
|
semua: newChecked,
|
||||||
nasional: true,
|
nasional: newChecked,
|
||||||
polda: true,
|
polda: newChecked,
|
||||||
polres: true,
|
polres: newChecked,
|
||||||
satker: true,
|
satker: newChecked,
|
||||||
international: true,
|
international: newChecked,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (newChecked) {
|
||||||
|
setAgendaType("0,1,2,3,4,5");
|
||||||
|
} else {
|
||||||
|
setAgendaType("");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Uncheck "semua" if any other option is selected
|
return newState;
|
||||||
if (key !== "semua") {
|
|
||||||
newState.semua = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set agendaType based on the selected checkbox
|
// Jika key bukan "semua"
|
||||||
if (newState.nasional) setAgendaType("mabes");
|
newState[key] = !prev[key];
|
||||||
else if (newState.polda) setAgendaType("polda");
|
newState.semua = false; // Uncheck "semua" jika yang dipilih adalah individu
|
||||||
else if (newState.polres) setAgendaType("polres");
|
|
||||||
else if (newState.satker) setAgendaType("satker");
|
// Hitung ulang agendaType berdasarkan pilihan
|
||||||
else if (newState.international) setAgendaType("international");
|
const selectedKeys = Object.entries(newState)
|
||||||
else setAgendaType(""); // Reset if no checkbox is selected
|
.filter(([k, v]) => v && k !== "semua")
|
||||||
|
.map(([k]) => wilayahValueMap[k]);
|
||||||
|
|
||||||
|
setAgendaType(selectedKeys.join(","));
|
||||||
|
|
||||||
return newState;
|
return newState;
|
||||||
});
|
});
|
||||||
|
|
@ -269,12 +313,25 @@ const EventModal = ({
|
||||||
const agendaTypeList: string[] = [];
|
const agendaTypeList: string[] = [];
|
||||||
const assignedToLevelList: string[] = [];
|
const assignedToLevelList: string[] = [];
|
||||||
|
|
||||||
// Mapping dari checkbox wilayah ke agendaType
|
// // Mapping dari checkbox wilayah ke agendaType
|
||||||
|
// Object.keys(wilayahPublish).forEach((key) => {
|
||||||
|
// if (wilayahPublish[key as keyof typeof wilayahPublish]) {
|
||||||
|
// agendaTypeList.push(wilayahValueMap[key]);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
if (wilayahPublish.semua) {
|
||||||
|
agendaTypeList.push("0", "1", "2", "3", "4", "5");
|
||||||
|
} else {
|
||||||
Object.keys(wilayahPublish).forEach((key) => {
|
Object.keys(wilayahPublish).forEach((key) => {
|
||||||
if (wilayahPublish[key as keyof typeof wilayahPublish]) {
|
if (
|
||||||
|
wilayahPublish[key as keyof typeof wilayahPublish] &&
|
||||||
|
key !== "semua"
|
||||||
|
) {
|
||||||
agendaTypeList.push(wilayahValueMap[key]);
|
agendaTypeList.push(wilayahValueMap[key]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Unit-unit berdasarkan wilayah yang aktif
|
// Unit-unit berdasarkan wilayah yang aktif
|
||||||
if (wilayahPublish.polda && selectedPolda.length > 0) {
|
if (wilayahPublish.polda && selectedPolda.length > 0) {
|
||||||
|
|
@ -558,6 +615,7 @@ const EventModal = ({
|
||||||
confirmButtonText: "OK",
|
confirmButtonText: "OK",
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
router.push(redirect);
|
router.push(redirect);
|
||||||
|
window.location.reload();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -784,7 +842,8 @@ const EventModal = ({
|
||||||
{wilayahPublish.polda && (
|
{wilayahPublish.polda && (
|
||||||
<UnitMapping
|
<UnitMapping
|
||||||
unit="Polda"
|
unit="Polda"
|
||||||
isDetail={false}
|
isDetail={isDetailMode} // jika Anda punya kondisi detail
|
||||||
|
initData={selectedPolda}
|
||||||
sendDataToParent={(data: any) =>
|
sendDataToParent={(data: any) =>
|
||||||
setSelectedPolda(data)
|
setSelectedPolda(data)
|
||||||
}
|
}
|
||||||
|
|
@ -802,8 +861,9 @@ const EventModal = ({
|
||||||
</label>
|
</label>
|
||||||
{wilayahPublish.polres && (
|
{wilayahPublish.polres && (
|
||||||
<UnitMapping
|
<UnitMapping
|
||||||
isDetail={false}
|
|
||||||
unit="Polres"
|
unit="Polres"
|
||||||
|
isDetail={isDetailMode}
|
||||||
|
initData={selectedPolres}
|
||||||
sendDataToParent={(data: any) =>
|
sendDataToParent={(data: any) =>
|
||||||
setSelectedPolres(data)
|
setSelectedPolres(data)
|
||||||
}
|
}
|
||||||
|
|
@ -821,8 +881,9 @@ const EventModal = ({
|
||||||
</label>
|
</label>
|
||||||
{wilayahPublish.satker && (
|
{wilayahPublish.satker && (
|
||||||
<UnitMapping
|
<UnitMapping
|
||||||
isDetail={false}
|
|
||||||
unit="Satker"
|
unit="Satker"
|
||||||
|
isDetail={isDetailMode}
|
||||||
|
initData={selectedSatker}
|
||||||
sendDataToParent={(data: any) =>
|
sendDataToParent={(data: any) =>
|
||||||
setSelectedSatker(data)
|
setSelectedSatker(data)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -97,15 +97,24 @@ const useTableColumns = () => {
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const isPublish = row.original.isPublish;
|
const isPublish = row.original.isPublish;
|
||||||
const isPublishOnPolda = row.original.isPublishOnPolda;
|
const isPublishOnPolda = row.original.isPublishOnPolda;
|
||||||
|
const creatorGroupParentLevelId = row.original.creatorGroupParentLevelId;
|
||||||
|
|
||||||
let displayText = "-";
|
let displayText = "-";
|
||||||
if (isPublish && !isPublishOnPolda) {
|
if (isPublish && !isPublishOnPolda) {
|
||||||
displayText = "Mabes";
|
displayText = "Mabes";
|
||||||
} else if (isPublish && isPublishOnPolda) {
|
} else if (isPublish && isPublishOnPolda) {
|
||||||
|
if (Number(creatorGroupParentLevelId) == 761) {
|
||||||
|
displayText = "Mabes & Satker";
|
||||||
|
} else {
|
||||||
displayText = "Mabes & Polda";
|
displayText = "Mabes & Polda";
|
||||||
|
}
|
||||||
} else if (!isPublish && isPublishOnPolda) {
|
} else if (!isPublish && isPublishOnPolda) {
|
||||||
|
if (Number(creatorGroupParentLevelId) == 761) {
|
||||||
|
displayText = "Satker";
|
||||||
|
} else {
|
||||||
displayText = "Polda";
|
displayText = "Polda";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-center whitespace-nowrap" title={displayText}>
|
<div className="text-center whitespace-nowrap" title={displayText}>
|
||||||
|
|
|
||||||
|
|
@ -100,15 +100,24 @@ const useTableColumns = () => {
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const isPublish = row.original.isPublish;
|
const isPublish = row.original.isPublish;
|
||||||
const isPublishOnPolda = row.original.isPublishOnPolda;
|
const isPublishOnPolda = row.original.isPublishOnPolda;
|
||||||
|
const creatorGroupParentLevelId = row.original.creatorGroupParentLevelId;
|
||||||
|
|
||||||
let displayText = "-";
|
let displayText = "-";
|
||||||
if (isPublish && !isPublishOnPolda) {
|
if (isPublish && !isPublishOnPolda) {
|
||||||
displayText = "Mabes";
|
displayText = "Mabes";
|
||||||
} else if (isPublish && isPublishOnPolda) {
|
} else if (isPublish && isPublishOnPolda) {
|
||||||
|
if (Number(creatorGroupParentLevelId) == 761) {
|
||||||
|
displayText = "Mabes & Satker";
|
||||||
|
} else {
|
||||||
displayText = "Mabes & Polda";
|
displayText = "Mabes & Polda";
|
||||||
|
}
|
||||||
} else if (!isPublish && isPublishOnPolda) {
|
} else if (!isPublish && isPublishOnPolda) {
|
||||||
|
if (Number(creatorGroupParentLevelId) == 761) {
|
||||||
|
displayText = "Satker";
|
||||||
|
} else {
|
||||||
displayText = "Polda";
|
displayText = "Polda";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-center whitespace-nowrap" title={displayText}>
|
<div className="text-center whitespace-nowrap" title={displayText}>
|
||||||
|
|
|
||||||
|
|
@ -97,15 +97,24 @@ const useTableColumns = () => {
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const isPublish = row.original.isPublish;
|
const isPublish = row.original.isPublish;
|
||||||
const isPublishOnPolda = row.original.isPublishOnPolda;
|
const isPublishOnPolda = row.original.isPublishOnPolda;
|
||||||
|
const creatorGroupParentLevelId = row.original.creatorGroupParentLevelId;
|
||||||
|
|
||||||
let displayText = "-";
|
let displayText = "-";
|
||||||
if (isPublish && !isPublishOnPolda) {
|
if (isPublish && !isPublishOnPolda) {
|
||||||
displayText = "Mabes";
|
displayText = "Mabes";
|
||||||
} else if (isPublish && isPublishOnPolda) {
|
} else if (isPublish && isPublishOnPolda) {
|
||||||
|
if (Number(creatorGroupParentLevelId) == 761) {
|
||||||
|
displayText = "Mabes & Satker";
|
||||||
|
} else {
|
||||||
displayText = "Mabes & Polda";
|
displayText = "Mabes & Polda";
|
||||||
|
}
|
||||||
} else if (!isPublish && isPublishOnPolda) {
|
} else if (!isPublish && isPublishOnPolda) {
|
||||||
|
if (Number(creatorGroupParentLevelId) == 761) {
|
||||||
|
displayText = "Satker";
|
||||||
|
} else {
|
||||||
displayText = "Polda";
|
displayText = "Polda";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-center whitespace-nowrap" title={displayText}>
|
<div className="text-center whitespace-nowrap" title={displayText}>
|
||||||
|
|
|
||||||
|
|
@ -97,15 +97,24 @@ const useTableColumns = () => {
|
||||||
cell: ({ row }) => {
|
cell: ({ row }) => {
|
||||||
const isPublish = row.original.isPublish;
|
const isPublish = row.original.isPublish;
|
||||||
const isPublishOnPolda = row.original.isPublishOnPolda;
|
const isPublishOnPolda = row.original.isPublishOnPolda;
|
||||||
|
const creatorGroupParentLevelId = row.original.creatorGroupParentLevelId;
|
||||||
|
|
||||||
let displayText = "-";
|
let displayText = "-";
|
||||||
if (isPublish && !isPublishOnPolda) {
|
if (isPublish && !isPublishOnPolda) {
|
||||||
displayText = "Mabes";
|
displayText = "Mabes";
|
||||||
} else if (isPublish && isPublishOnPolda) {
|
} else if (isPublish && isPublishOnPolda) {
|
||||||
|
if (Number(creatorGroupParentLevelId) == 761) {
|
||||||
|
displayText = "Mabes & Satker";
|
||||||
|
} else {
|
||||||
displayText = "Mabes & Polda";
|
displayText = "Mabes & Polda";
|
||||||
|
}
|
||||||
} else if (!isPublish && isPublishOnPolda) {
|
} else if (!isPublish && isPublishOnPolda) {
|
||||||
|
if (Number(creatorGroupParentLevelId) == 761) {
|
||||||
|
displayText = "Satker";
|
||||||
|
} else {
|
||||||
displayText = "Polda";
|
displayText = "Polda";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="text-center whitespace-nowrap" title={displayText}>
|
<div className="text-center whitespace-nowrap" title={displayText}>
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ import { Link, useRouter } from "@/components/navigation";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import { deleteBlog } from "@/service/blog/blog";
|
import { deleteBlog } from "@/service/blog/blog";
|
||||||
import { error, loading } from "@/lib/swal";
|
import { error, loading, close } from "@/lib/swal";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
||||||
|
|
@ -126,6 +126,7 @@ const useTableColumns = ({
|
||||||
|
|
||||||
const handleDownload = async (id: string) => {
|
const handleDownload = async (id: string) => {
|
||||||
try {
|
try {
|
||||||
|
loading();
|
||||||
const response = await axios.get(
|
const response = await axios.get(
|
||||||
`https://netidhub.com/api/media/report/download?id=${id}`,
|
`https://netidhub.com/api/media/report/download?id=${id}`,
|
||||||
{
|
{
|
||||||
|
|
@ -140,6 +141,7 @@ const useTableColumns = ({
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link);
|
||||||
link.click();
|
link.click();
|
||||||
link.remove();
|
link.remove();
|
||||||
|
close();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Download failed", error);
|
console.error("Download failed", error);
|
||||||
MySwal.fire({
|
MySwal.fire({
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ export default function ExecutiveDataDashboard() {
|
||||||
const state = Cookies.get("state");
|
const state = Cookies.get("state");
|
||||||
const provState = Cookies.get("state-prov");
|
const provState = Cookies.get("state-prov");
|
||||||
const t = useTranslations("AnalyticsDashboard");
|
const t = useTranslations("AnalyticsDashboard");
|
||||||
|
const [refreshTicket, setRefreshTicket] = useState(true);
|
||||||
|
|
||||||
const [ticket1, setTicket1] = useState("");
|
const [ticket1, setTicket1] = useState("");
|
||||||
const [ticket2, setTicket2] = useState("");
|
const [ticket2, setTicket2] = useState("");
|
||||||
|
|
@ -44,6 +45,7 @@ export default function ExecutiveDataDashboard() {
|
||||||
const [ticket4, setTicket4] = useState("");
|
const [ticket4, setTicket4] = useState("");
|
||||||
const [ticket5, setTicket5] = useState("");
|
const [ticket5, setTicket5] = useState("");
|
||||||
const [ticket6, setTicket6] = useState("");
|
const [ticket6, setTicket6] = useState("");
|
||||||
|
const [ticket7, setTicket7] = useState("");
|
||||||
const [isInternational, setIsInternational] = useState([false, false, false]);
|
const [isInternational, setIsInternational] = useState([false, false, false]);
|
||||||
|
|
||||||
const baseUrl = "https://analytic.sitani.info/";
|
const baseUrl = "https://analytic.sitani.info/";
|
||||||
|
|
@ -54,13 +56,40 @@ export default function ExecutiveDataDashboard() {
|
||||||
const view1 =
|
const view1 =
|
||||||
levelName == "MABES POLRI"
|
levelName == "MABES POLRI"
|
||||||
? isInternational[0]
|
? isInternational[0]
|
||||||
? "views/2023_08_MediaHUB-KtnMgt_Rev100/db-emg-issue-executive?"
|
? "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-per-polda-new?polda-selected=ALL"
|
||||||
: "views/2023_08_MediaHUB-KtnMgt_Rev100/db-emg-issue-executive?"
|
: "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-per-polda-new?polda-selected=ALL"
|
||||||
: safeLevelName.includes("POLDA")
|
: safeLevelName.includes("POLDA")
|
||||||
? `views/2023_08_MediaHUB-KtnMgt_Rev100/db-emg-issue?provinsi-polda=${state}&`
|
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-per-polda-new?polda-selected=${state}&`
|
||||||
: `views/2023_08_MediaHUB-KtnMgt_Rev100/db-emg-issue?provinsi-polda=${state}&`;
|
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-per-polda-new?polda-selected=${state}&`;
|
||||||
|
|
||||||
const view2 =
|
const view2 =
|
||||||
|
levelName == "MABES POLRI"
|
||||||
|
? isInternational[1]
|
||||||
|
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-content-interaction-per-satker?polda-selected=ALL"
|
||||||
|
: "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-per-satker?polda-selected=ALL"
|
||||||
|
: safeLevelName.includes("POLDA")
|
||||||
|
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-per-satker?polda-selected=SATKER POLRI&`
|
||||||
|
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-per-satker?polda-selected=SATKER POLRI&`;
|
||||||
|
|
||||||
|
const view3 =
|
||||||
|
levelName == "MABES POLRI"
|
||||||
|
? isInternational[2]
|
||||||
|
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-content-category-per-polda-new?polda-selected=ALL"
|
||||||
|
: "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-category-per-polda-new?polda-selected=ALL"
|
||||||
|
: safeLevelName.includes("POLDA")
|
||||||
|
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-category-per-polda-new?polda-selected=${state}&`
|
||||||
|
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-category-per-polda-new?polda-selected=${state}&`;
|
||||||
|
|
||||||
|
const view4 =
|
||||||
|
levelName == "MABES POLRI"
|
||||||
|
? isInternational[1]
|
||||||
|
? "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-category-per-satker?polda-selected=ALL"
|
||||||
|
: "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-category-per-satker?polda-selected=ALL"
|
||||||
|
: safeLevelName.includes("POLDA")
|
||||||
|
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-category-per-satker?polda-selected=SATKER POLRI&`
|
||||||
|
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-category-per-satker?polda-selected=SATKER POLRI&`;
|
||||||
|
|
||||||
|
const view5 =
|
||||||
levelName == "MABES POLRI"
|
levelName == "MABES POLRI"
|
||||||
? isInternational[1]
|
? isInternational[1]
|
||||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-published-produksi?"
|
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-published-produksi?"
|
||||||
|
|
@ -69,7 +98,7 @@ export default function ExecutiveDataDashboard() {
|
||||||
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-published-produksi-polda-executive?polda-selected=${state}&`
|
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-published-produksi-polda-executive?polda-selected=${state}&`
|
||||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-published-produksi-polda-executive?polda-selected=${state}&`;
|
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-published-produksi-polda-executive?polda-selected=${state}&`;
|
||||||
|
|
||||||
const view3 =
|
const view6 =
|
||||||
levelName == "MABES POLRI"
|
levelName == "MABES POLRI"
|
||||||
? isInternational[2]
|
? isInternational[2]
|
||||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-waktu-akses-pengguna?"
|
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-waktu-akses-pengguna?"
|
||||||
|
|
@ -78,59 +107,14 @@ export default function ExecutiveDataDashboard() {
|
||||||
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-waktu-akses-pengguna-polda-executive?polda-selected=${state}&`
|
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-waktu-akses-pengguna-polda-executive?polda-selected=${state}&`
|
||||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-waktu-akses-pengguna-polda-executive?polda-selected=${state}&`;
|
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-waktu-akses-pengguna-polda-executive?polda-selected=${state}&`;
|
||||||
|
|
||||||
const view4 =
|
|
||||||
levelName == "MABES POLRI"
|
|
||||||
? isInternational[1]
|
|
||||||
? "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-polda?"
|
|
||||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-polda?"
|
|
||||||
: safeLevelName.includes("POLDA")
|
|
||||||
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-per-polda-new?polda-selected=${state}&`
|
|
||||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-per-polda-new?polda-selected=${state}&`;
|
|
||||||
|
|
||||||
const view5 =
|
|
||||||
levelName == "MABES POLRI"
|
|
||||||
? isInternational[1]
|
|
||||||
? "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-polres?"
|
|
||||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-polres?"
|
|
||||||
: safeLevelName.includes("POLDA")
|
|
||||||
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-polres?provinsi-polda=${state}&`
|
|
||||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-polres?provinsi-polda=${state}&`;
|
|
||||||
|
|
||||||
const view6 =
|
|
||||||
levelName == "MABES POLRI"
|
|
||||||
? isInternational[1]
|
|
||||||
? "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-satker?"
|
|
||||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-satker?"
|
|
||||||
: safeLevelName.includes("POLDA")
|
|
||||||
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-satker?satker-selected=${state}&`
|
|
||||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-satker?satker-selected=${state}&`;
|
|
||||||
|
|
||||||
const view7 =
|
const view7 =
|
||||||
levelName == "MABES POLRI"
|
levelName == "MABES POLRI"
|
||||||
? isInternational[2]
|
? isInternational[2]
|
||||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-penugasan?"
|
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-penugasan-vertical-bar?"
|
||||||
: "views/2023_09_db-penugasan_rev100/db-penugasan?"
|
: "views/2023_09_db-penugasan_rev100/db-penugasan-vertical-bar?"
|
||||||
: safeLevelName.includes("POLDA")
|
: safeLevelName.includes("POLDA")
|
||||||
? `views/2023_09_db-penugasan_rev100/db-penugasan?polda-selected=${state}&`
|
? `views/2023_09_db-penugasan_rev100/db-penugasan-vertical-bar?polda-selected=${state}&`
|
||||||
: `views/2023_09_db-penugasan_rev100/db-penugasan?polda-selected=${state}&`;
|
: `views/2023_09_db-penugasan_rev100/db-penugasan-vertical-bar?polda-selected=${state}&`;
|
||||||
|
|
||||||
const view8 =
|
|
||||||
levelName == "MABES POLRI"
|
|
||||||
? isInternational[2]
|
|
||||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-konten-kategori-top10?"
|
|
||||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-konten-kategori-top10?"
|
|
||||||
: safeLevelName.includes("POLDA")
|
|
||||||
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-polda-new?polda-selected=${state}&`
|
|
||||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-content-interaction-polda-new?polda-selected=${state}&`;
|
|
||||||
|
|
||||||
const view9 =
|
|
||||||
levelName == "MABES POLRI"
|
|
||||||
? isInternational[3]
|
|
||||||
? "views/2023_04_MediaHUB-Viz_INTL_Rev202/db-konten-kategori?"
|
|
||||||
: "views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-konten-kategori?"
|
|
||||||
: safeLevelName.includes("POLDA")
|
|
||||||
? `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-konten-kategori-polda?polda-selected=${state}&`
|
|
||||||
: `views/2023_04_MediaHUB-Viz-POLDA_Rev200/db-konten-kategori-polda?polda-selected=${state}&`;
|
|
||||||
|
|
||||||
const param = ":embed=yes&:toolbar=no&:iframeSizedToWindow=true";
|
const param = ":embed=yes&:toolbar=no&:iframeSizedToWindow=true";
|
||||||
|
|
||||||
|
|
@ -153,10 +137,13 @@ export default function ExecutiveDataDashboard() {
|
||||||
|
|
||||||
const response6 = await generateTicket();
|
const response6 = await generateTicket();
|
||||||
setTicket6(response6?.data?.data);
|
setTicket6(response6?.data?.data);
|
||||||
|
|
||||||
|
const response7 = await generateTicket();
|
||||||
|
setTicket7(response7?.data?.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
initState();
|
initState();
|
||||||
}, [isInternational]);
|
}, [isInternational, refreshTicket]);
|
||||||
|
|
||||||
// Hooks
|
// Hooks
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
@ -178,7 +165,7 @@ export default function ExecutiveDataDashboard() {
|
||||||
<SiteBreadcrumb />
|
<SiteBreadcrumb />
|
||||||
<div>
|
<div>
|
||||||
<div className="my-3">
|
<div className="my-3">
|
||||||
<Tabs defaultValue="content-publish" className="w-full">
|
<Tabs defaultValue="content-publish" className="w-full" onValueChange={() => setRefreshTicket(!refreshTicket)}>
|
||||||
<TabsList className="flex-wrap bg-black">
|
<TabsList className="flex-wrap bg-black">
|
||||||
<TabsTrigger
|
<TabsTrigger
|
||||||
value="content-publish"
|
value="content-publish"
|
||||||
|
|
@ -217,19 +204,17 @@ export default function ExecutiveDataDashboard() {
|
||||||
{/* Polda */}
|
{/* Polda */}
|
||||||
{(levelNumber === "1" || levelNumber === "2") && (
|
{(levelNumber === "1" || levelNumber === "2") && (
|
||||||
<Card
|
<Card
|
||||||
className={`rounded-sm p-3 ${
|
className={`rounded-sm p-3 w-full`}
|
||||||
levelNumber === "2" ? "w-full" : "w-full"
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<div className="flex flex-row justify-between">
|
{/* <div className="flex flex-row justify-between">
|
||||||
<p className="text-base font-semibold">
|
<p className="text-base font-semibold">
|
||||||
Upload konten hari ini Polda
|
Upload konten hari ini Polda
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div> */}
|
||||||
<div className="my-5">
|
<div className="my-5">
|
||||||
{ticket1 == "w-full" ? (
|
{ticket1 == "w-full" ? (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${baseUrl + view4 + param}`}
|
src={`${baseUrl + view1 + param}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="750"
|
height="750"
|
||||||
className="w-full"
|
className="w-full"
|
||||||
|
|
@ -237,7 +222,7 @@ export default function ExecutiveDataDashboard() {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${url + ticket1}/${view4}${param}`}
|
src={`${url + ticket1}/${view1}${param}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="750"
|
height="750"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
|
|
@ -248,60 +233,26 @@ export default function ExecutiveDataDashboard() {
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Satker */}
|
{/* Satker */}
|
||||||
{(levelNumber === "1" || levelNumber === "3") && (
|
{(levelNumber === "1") && (
|
||||||
<Card
|
<Card
|
||||||
className={`rounded-sm p-3 ${
|
className={`rounded-sm p-3 w-full`}
|
||||||
levelNumber === "3" ? "w-full" : "w-full"
|
|
||||||
}`}
|
|
||||||
>
|
>
|
||||||
<div className="flex flex-row justify-between">
|
{/* <div className="flex flex-row justify-between">
|
||||||
<p className="text-base font-semibold">
|
<p className="text-base font-semibold">
|
||||||
Upload konten hari ini Satker
|
Upload konten hari ini Satker
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div> */}
|
||||||
<div className="my-5">
|
<div className="my-5">
|
||||||
{ticket2 == "" ? (
|
{ticket2 == "" ? (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${baseUrl + view6 + param}`}
|
src={`${baseUrl + view2 + param}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="750"
|
height="750"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${url + ticket2}/${view6}${param}`}
|
src={`${url + ticket2}/${view2}${param}`}
|
||||||
width="100%"
|
|
||||||
height="750"
|
|
||||||
frameBorder="0"
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</Card>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{/* Polres */}
|
|
||||||
{(levelNumber === "1" || levelNumber === "2") && (
|
|
||||||
<Card
|
|
||||||
className={`rounded-sm p-3 ${
|
|
||||||
levelNumber === "2" ? "w-full" : "w-full"
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
<div className="flex flex-row justify-between">
|
|
||||||
<p className="text-base font-semibold">
|
|
||||||
Upload konten hari ini Polres
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="my-5">
|
|
||||||
{ticket3 == "" ? (
|
|
||||||
<iframe
|
|
||||||
src={`${baseUrl + view5 + param}`}
|
|
||||||
width="100%"
|
|
||||||
height="750"
|
|
||||||
frameBorder="0"
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<iframe
|
|
||||||
src={`${url + ticket3}/${view5}${param}`}
|
|
||||||
width="100%"
|
width="100%"
|
||||||
height="750"
|
height="750"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
|
|
@ -313,56 +264,19 @@ export default function ExecutiveDataDashboard() {
|
||||||
</div>
|
</div>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="content-category">
|
<TabsContent value="content-category">
|
||||||
|
{(levelNumber === "1" || levelNumber === "2") && (
|
||||||
<Card className="px-3 py-3">
|
<Card className="px-3 py-3">
|
||||||
<p className="text-lg">
|
|
||||||
<b>
|
|
||||||
{isInternational[2]
|
|
||||||
? "INTERACTION OF THE MOST POPULAR CATEGORIES AND TITLES"
|
|
||||||
: "INTERAKSI KATEGORI DAN JUDUL TERPOPULER"}
|
|
||||||
</b>
|
|
||||||
</p>
|
|
||||||
{levelName === "MABES POLRI" ? (
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<p>{t("choose_category")}</p>
|
|
||||||
<div className="flex flex-row gap-1 border-2 w-fit">
|
|
||||||
<Button
|
|
||||||
onClick={() => handleInternational(2, false)}
|
|
||||||
className={` hover:text-white rounded-none
|
|
||||||
${
|
|
||||||
isInternational[2]
|
|
||||||
? "bg-white text-black "
|
|
||||||
: "bg-black text-white "
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
Indonesia
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => handleInternational(2, true)}
|
|
||||||
className={`hover:text-white rounded-none ${
|
|
||||||
isInternational[1]
|
|
||||||
? "bg-black text-white "
|
|
||||||
: "bg-white text-black "
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{t("international")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
<div className="my-5">
|
<div className="my-5">
|
||||||
{ticket3 == "" ? (
|
{ticket3 == "" ? (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${baseUrl + view8 + param}`}
|
src={`${baseUrl + view3 + param}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="750"
|
height="750"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${`${url + ticket3}/${view8}${param}`}`}
|
src={`${`${url + ticket3}/${view3}${param}`}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="750"
|
height="750"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
|
|
@ -370,25 +284,43 @@ export default function ExecutiveDataDashboard() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
)}
|
||||||
<TabsContent value="popular-content">
|
|
||||||
<Card className="rounded-sm p-3 h-[750px]">
|
{levelNumber === "1" && (
|
||||||
<div className="flex flex-row justify-between">
|
<Card className="px-3 py-3">
|
||||||
<p className="text-base font-semibold">
|
|
||||||
Konten Paling Populer
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="my-5">
|
<div className="my-5">
|
||||||
{ticket4 == "" ? (
|
{ticket4 == "" ? (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${baseUrl + view2 + param}`}
|
src={`${baseUrl + view4 + param}`}
|
||||||
|
width="100%"
|
||||||
|
height="750"
|
||||||
|
frameBorder="0"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<iframe
|
||||||
|
src={`${`${url + ticket4}/${view4}${param}`}`}
|
||||||
|
width="100%"
|
||||||
|
height="750"
|
||||||
|
frameBorder="0"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
)}
|
||||||
|
</TabsContent>
|
||||||
|
<TabsContent value="popular-content">
|
||||||
|
<Card className="rounded-sm p-3 h-[750px]">
|
||||||
|
<div className="my-5">
|
||||||
|
{ticket5 == "" ? (
|
||||||
|
<iframe
|
||||||
|
src={`${baseUrl + view5 + param}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="650"
|
height="650"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${`${url + ticket4}/${view2}${param}`}`}
|
src={`${`${url + ticket5}/${view5}${param}`}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="650"
|
height="650"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
|
|
@ -400,22 +332,17 @@ export default function ExecutiveDataDashboard() {
|
||||||
|
|
||||||
<TabsContent value="heatmap">
|
<TabsContent value="heatmap">
|
||||||
<Card className="rounded-sm p-3 h-[750px]">
|
<Card className="rounded-sm p-3 h-[750px]">
|
||||||
<div className="flex flex-row justify-between mx-3">
|
|
||||||
<p className="text-base font-semibold">
|
|
||||||
Heatmap Konten dan Kategori dengan Interaksi
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="my-5">
|
<div className="my-5">
|
||||||
{ticket5 == "" ? (
|
{ticket6 == "" ? (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${baseUrl + view3 + param}`}
|
src={`${baseUrl + view6 + param}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="600"
|
height="600"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${`${url + ticket5}/${view3}${param}`}`}
|
src={`${`${url + ticket6}/${view6}${param}`}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="600"
|
height="600"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
|
|
@ -425,42 +352,9 @@ export default function ExecutiveDataDashboard() {
|
||||||
</Card>
|
</Card>
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
<TabsContent value="task">
|
<TabsContent value="task">
|
||||||
<div className="grid grid-cols-12 gap-5">
|
<Card className="rounded-sm p-3 h-[750px]">
|
||||||
<div className="lg:col-span-12 col-span-12">
|
|
||||||
<Card className="px-3 py-3">
|
|
||||||
{levelName === "MABES POLRI" ? (
|
|
||||||
<div className="flex flex-col gap-1">
|
|
||||||
<p>{t("choose_category")}</p>
|
|
||||||
<div className="flex flex-row gap-1 border-2 w-fit">
|
|
||||||
<Button
|
|
||||||
onClick={() => handleInternational(2, false)}
|
|
||||||
className={` hover:text-white rounded-none
|
|
||||||
${
|
|
||||||
isInternational[2]
|
|
||||||
? "bg-white text-black "
|
|
||||||
: "bg-black text-white "
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
Indonesia
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
onClick={() => handleInternational(2, true)}
|
|
||||||
className={`hover:text-white rounded-none ${
|
|
||||||
isInternational[1]
|
|
||||||
? "bg-black text-white "
|
|
||||||
: "bg-white text-black "
|
|
||||||
}
|
|
||||||
`}
|
|
||||||
>
|
|
||||||
{t("international")}
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
""
|
|
||||||
)}
|
|
||||||
<div className="my-5">
|
<div className="my-5">
|
||||||
{ticket3 == "" ? (
|
{ticket7 == "" ? (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${baseUrl + view7 + param}`}
|
src={`${baseUrl + view7 + param}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
|
|
@ -469,7 +363,7 @@ export default function ExecutiveDataDashboard() {
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<iframe
|
<iframe
|
||||||
src={`${`${url + ticket3}/${view7}${param}`}`}
|
src={`${`${url + ticket7}/${view7}${param}`}`}
|
||||||
width="100%"
|
width="100%"
|
||||||
height="750"
|
height="750"
|
||||||
frameBorder="0"
|
frameBorder="0"
|
||||||
|
|
@ -477,8 +371,6 @@ export default function ExecutiveDataDashboard() {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</TabsContent>
|
</TabsContent>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ import { ChevronDownIcon } from "lucide-react";
|
||||||
import { getOperatorUser } from "@/service/management-user/management-user";
|
import { getOperatorUser } from "@/service/management-user/management-user";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
message: z.string().optional(),
|
title: z.string().optional(),
|
||||||
description: z.string().optional(),
|
description: z.string().optional(),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -275,7 +275,7 @@ export default function FormQuestionsReply() {
|
||||||
title: data.title,
|
title: data.title,
|
||||||
description: data.description,
|
description: data.description,
|
||||||
priorityId: selectedPriority,
|
priorityId: selectedPriority,
|
||||||
statusId: selectedStatus,
|
statusId: 1,
|
||||||
typeId: detailTickets?.typeId,
|
typeId: detailTickets?.typeId,
|
||||||
parentCommentId: detailTickets?.feedId,
|
parentCommentId: detailTickets?.feedId,
|
||||||
operatorTeam: selectedOperator.join(","),
|
operatorTeam: selectedOperator.join(","),
|
||||||
|
|
@ -507,7 +507,7 @@ export default function FormQuestionsReply() {
|
||||||
<Label>Judul</Label>
|
<Label>Judul</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="message"
|
name="title"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Input
|
<Input
|
||||||
size="md"
|
size="md"
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import { uploadThumbnailBlog } from "@/service/blog/blog";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import {
|
import {
|
||||||
generateDataArticle,
|
generateDataArticle,
|
||||||
|
generateDataRewrite,
|
||||||
getDetailArticle,
|
getDetailArticle,
|
||||||
getGenerateKeywords,
|
getGenerateKeywords,
|
||||||
getGenerateTitle,
|
getGenerateTitle,
|
||||||
|
|
@ -55,6 +56,7 @@ import dynamic from "next/dynamic";
|
||||||
import { getCsrfToken } from "@/service/auth";
|
import { getCsrfToken } from "@/service/auth";
|
||||||
import { Link } from "@/i18n/routing";
|
import { Link } from "@/i18n/routing";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
import { useParams } from "next/navigation";
|
||||||
|
|
||||||
interface FileWithPreview extends File {
|
interface FileWithPreview extends File {
|
||||||
preview: string;
|
preview: string;
|
||||||
|
|
@ -82,6 +84,10 @@ export default function FormAudio() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const editor = useRef(null);
|
const editor = useRef(null);
|
||||||
type AudioSchema = z.infer<typeof audioSchema>;
|
type AudioSchema = z.infer<typeof audioSchema>;
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
|
||||||
|
const [selectedFileType, setSelectedFileType] = useState("original");
|
||||||
|
|
||||||
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
||||||
const taskId = Cookies.get("taskId");
|
const taskId = Cookies.get("taskId");
|
||||||
|
|
@ -97,6 +103,11 @@ export default function FormAudio() {
|
||||||
const [preview, setPreview] = useState<string | null>(null);
|
const [preview, setPreview] = useState<string | null>(null);
|
||||||
const [selectedLanguage, setSelectedLanguage] = useState("");
|
const [selectedLanguage, setSelectedLanguage] = useState("");
|
||||||
|
|
||||||
|
const [selectedWritingStyle, setSelectedWritingStyle] =
|
||||||
|
useState("professional");
|
||||||
|
const [editorContent, setEditorContent] = useState(""); // Untuk original editor
|
||||||
|
const [rewriteEditorContent, setRewriteEditorContent] = useState("");
|
||||||
|
|
||||||
const [selectedSEO, setSelectedSEO] = useState<string>("");
|
const [selectedSEO, setSelectedSEO] = useState<string>("");
|
||||||
const [title, setTitle] = useState<string>("");
|
const [title, setTitle] = useState<string>("");
|
||||||
const [selectedAdvConfig, setSelectedAdvConfig] = useState<string>("");
|
const [selectedAdvConfig, setSelectedAdvConfig] = useState<string>("");
|
||||||
|
|
@ -111,7 +122,6 @@ export default function FormAudio() {
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
||||||
const [selectedWritingStyle, setSelectedWritingStyle] = useState("");
|
|
||||||
const [selectedSize, setSelectedSize] = useState("");
|
const [selectedSize, setSelectedSize] = useState("");
|
||||||
const [detailData, setDetailData] = useState<any>(null);
|
const [detailData, setDetailData] = useState<any>(null);
|
||||||
const [articleImages, setArticleImages] = useState<string[]>([]);
|
const [articleImages, setArticleImages] = useState<string[]>([]);
|
||||||
|
|
@ -133,6 +143,8 @@ export default function FormAudio() {
|
||||||
const [isStartUpload, setIsStartUpload] = useState(false);
|
const [isStartUpload, setIsStartUpload] = useState(false);
|
||||||
const [counterProgress, setCounterProgress] = useState(0);
|
const [counterProgress, setCounterProgress] = useState(0);
|
||||||
|
|
||||||
|
const [isContentRewriteClicked, setIsContentRewriteClicked] = useState(false);
|
||||||
|
const [showRewriteEditor, setShowRewriteEditor] = useState(false);
|
||||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||||
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
const [publishedFor, setPublishedFor] = useState<string[]>([]);
|
||||||
|
|
||||||
|
|
@ -155,15 +167,11 @@ export default function FormAudio() {
|
||||||
|
|
||||||
const audioSchema = z.object({
|
const audioSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
description: z
|
description: z.string().optional(),
|
||||||
.string()
|
descriptionOri: z.string().optional(), // Original editor
|
||||||
.min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." })
|
rewriteDescription: z.string().optional(), // Rewrite editor
|
||||||
.or(
|
|
||||||
z.literal(articleBody || "").refine((val) => val.length > 0, {
|
|
||||||
message: "Deskripsi diperlukan.",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
||||||
|
|
||||||
// tags: z.string().min(1, { message: "Judul diperlukan" }),
|
// tags: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -175,6 +183,11 @@ export default function FormAudio() {
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm<AudioSchema>({
|
} = useForm<AudioSchema>({
|
||||||
resolver: zodResolver(audioSchema),
|
resolver: zodResolver(audioSchema),
|
||||||
|
defaultValues: {
|
||||||
|
description: "",
|
||||||
|
descriptionOri: "",
|
||||||
|
rewriteDescription: "",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const doGenerateMainKeyword = async () => {
|
const doGenerateMainKeyword = async () => {
|
||||||
|
|
@ -437,12 +450,24 @@ export default function FormAudio() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (articleBody) {
|
||||||
|
// Set ke dua field jika rewrite juga aktif
|
||||||
|
setValue("description", articleBody);
|
||||||
|
setValue("rewriteDescription", articleBody);
|
||||||
|
}
|
||||||
|
}, [articleBody, setValue]);
|
||||||
|
|
||||||
const save = async (data: AudioSchema) => {
|
const save = async (data: AudioSchema) => {
|
||||||
loading();
|
loading();
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
const finalTitle = isSwitchOn ? title : data.title;
|
const finalTitle = isSwitchOn ? title : data.title;
|
||||||
const finalDescription = articleBody || data.description;
|
const finalDescription = isSwitchOn
|
||||||
if (!finalDescription.trim()) {
|
? data.description
|
||||||
|
: selectedFileType === "rewrite"
|
||||||
|
? data.rewriteDescription
|
||||||
|
: data.descriptionOri;
|
||||||
|
if (!finalDescription?.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -719,6 +744,45 @@ export default function FormAudio() {
|
||||||
}
|
}
|
||||||
}, [title, getValues, setValue]);
|
}, [title, getValues, setValue]);
|
||||||
|
|
||||||
|
const handleRewriteClick = async () => {
|
||||||
|
setIsContentRewriteClicked(true);
|
||||||
|
|
||||||
|
const request = {
|
||||||
|
style: selectedWritingStyle,
|
||||||
|
lang: "id",
|
||||||
|
contextType: "text",
|
||||||
|
urlContext: null,
|
||||||
|
context: editorContent, // Ambil isi editor original
|
||||||
|
createdBy: roleId,
|
||||||
|
sentiment: "Humorous",
|
||||||
|
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await generateDataRewrite(request);
|
||||||
|
close();
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
console.error(res.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newArticleId = res?.data?.data?.id;
|
||||||
|
setIsGeneratedArticle(true);
|
||||||
|
|
||||||
|
setArticleIds((prevIds: string[]) => {
|
||||||
|
if (prevIds.length < 3) {
|
||||||
|
return [...prevIds, newArticleId];
|
||||||
|
} else {
|
||||||
|
const updatedIds = [...prevIds];
|
||||||
|
updatedIds[2] = newArticleId;
|
||||||
|
return updatedIds;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds));
|
||||||
|
setShowRewriteEditor(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="flex flex-col lg:flex-row gap-10">
|
<div className="flex flex-col lg:flex-row gap-10">
|
||||||
|
|
@ -911,7 +975,7 @@ export default function FormAudio() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-5">
|
<div className="mt-5">
|
||||||
<Label>{t("special-instructions")} (Optional)</Label>
|
<Label>{t("special-instructions")}(Optional)</Label>
|
||||||
<div className="mt-3">
|
<div className="mt-3">
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -940,7 +1004,7 @@ export default function FormAudio() {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isGeneratedArticle && (
|
{isGeneratedArticle && (
|
||||||
<div className="mt-3 pb-0 flex flex-row ">
|
<div className="mt-3 pb-0 flex flex-row">
|
||||||
{articleIds.map((id: string, index: number) => (
|
{articleIds.map((id: string, index: number) => (
|
||||||
<p
|
<p
|
||||||
key={index}
|
key={index}
|
||||||
|
|
@ -960,27 +1024,23 @@ export default function FormAudio() {
|
||||||
<div className="pt-3">
|
<div className="pt-3">
|
||||||
<div className="flex flex-row justify-between items-center">
|
<div className="flex flex-row justify-between items-center">
|
||||||
{selectedArticleId && (
|
{selectedArticleId && (
|
||||||
<Link
|
|
||||||
href={`/contributor/content/audio/update-seo/${selectedArticleId}`}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Button
|
<Button
|
||||||
className="mb-2"
|
className="mb-2"
|
||||||
size="sm"
|
size="sm"
|
||||||
variant={"outline"}
|
variant={"outline"}
|
||||||
color="primary"
|
color="primary"
|
||||||
|
onClick={() => {
|
||||||
|
const url = `/${locale}/contributor/content/image/update-seo/${selectedArticleId}`;
|
||||||
|
window.open(url, "_blank", "noopener,noreferrer");
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t("update")}
|
{t("update")}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="py-3 space-y-2">
|
||||||
)}
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label>{t("description")}</Label>
|
<Label>{t("description")}</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -988,11 +1048,16 @@ export default function FormAudio() {
|
||||||
render={({ field: { onChange, value } }) =>
|
render={({ field: { onChange, value } }) =>
|
||||||
isLoadingData ? (
|
isLoadingData ? (
|
||||||
<div className="flex justify-center items-center h-40">
|
<div className="flex justify-center items-center h-40">
|
||||||
<p className="text-gray-500">Loading Proses Data...</p>
|
<p className="text-gray-500">
|
||||||
|
Loading Proses Data...
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<CustomEditor
|
<CustomEditor
|
||||||
onChange={onChange}
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setEditorContent(value);
|
||||||
|
}}
|
||||||
initialData={articleBody || value}
|
initialData={articleBody || value}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
@ -1004,6 +1069,110 @@ export default function FormAudio() {
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isSwitchOn && (
|
||||||
|
<>
|
||||||
|
<RadioGroup
|
||||||
|
onValueChange={(value) => setSelectedFileType(value)}
|
||||||
|
value={selectedFileType}
|
||||||
|
className=" grid-cols-1"
|
||||||
|
>
|
||||||
|
<div className="">
|
||||||
|
<RadioGroupItem value="original" id="original-file" />
|
||||||
|
<Label htmlFor="original-file">
|
||||||
|
Select Original Description
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="py-3 space-y-2">
|
||||||
|
<Label>{t("description")}</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="descriptionOri"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setEditorContent(value);
|
||||||
|
}}
|
||||||
|
initialData={value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{errors.description?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.description.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-sm font-semibold">Content Rewrite</p>
|
||||||
|
<div className="my-2">
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
type="button"
|
||||||
|
onClick={handleRewriteClick}
|
||||||
|
className="bg-blue-500 text-white py-2 px-4 rounded"
|
||||||
|
>
|
||||||
|
Content Rewrite
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{showRewriteEditor && (
|
||||||
|
<div>
|
||||||
|
{isGeneratedArticle && (
|
||||||
|
<div className="mt-3 pb-0 flex flex-row ">
|
||||||
|
{articleIds.map((id: string, index: number) => (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
key={index}
|
||||||
|
className={`mr-3 px-3 py-2 rounded-md ${
|
||||||
|
selectedArticleId === id
|
||||||
|
? "bg-green-500 text-white"
|
||||||
|
: "border-2 border-green-500 bg-white text-green-500 hover:bg-green-500 hover:text-white hover:border-green-500"
|
||||||
|
}`}
|
||||||
|
onClick={() => handleArticleIdClick(id)}
|
||||||
|
>
|
||||||
|
{"Narasi " + (index + 1)}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex items-center space-x-2 mt-3">
|
||||||
|
<RadioGroupItem value="rewrite" id="rewrite-file" />
|
||||||
|
<Label htmlFor="rewrite-file">
|
||||||
|
Select Description Rewrite
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="py-3 space-y-2">
|
||||||
|
<Label>{t("file-rewrite")}</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="rewriteDescription"
|
||||||
|
render={({ field: { onChange, value } }) =>
|
||||||
|
isLoadingData ? (
|
||||||
|
<div className="flex justify-center items-center h-40">
|
||||||
|
<p className="text-gray-500">
|
||||||
|
Loading Proses Data...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setRewriteEditorContent(value);
|
||||||
|
}}
|
||||||
|
initialData={articleBody || value}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</RadioGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
<Label>{t("select-file")}</Label>
|
<Label>{t("select-file")}</Label>
|
||||||
{/* <Input
|
{/* <Input
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import { uploadThumbnailBlog } from "@/service/blog/blog";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import {
|
import {
|
||||||
generateDataArticle,
|
generateDataArticle,
|
||||||
|
generateDataRewrite,
|
||||||
getDetailArticle,
|
getDetailArticle,
|
||||||
getGenerateKeywords,
|
getGenerateKeywords,
|
||||||
getGenerateTitle,
|
getGenerateTitle,
|
||||||
|
|
@ -94,6 +95,7 @@ export default function FormImage() {
|
||||||
const scheduleId = Cookies.get("scheduleId");
|
const scheduleId = Cookies.get("scheduleId");
|
||||||
const scheduleType = Cookies.get("scheduleType");
|
const scheduleType = Cookies.get("scheduleType");
|
||||||
const roleId = getCookiesDecrypt("urie");
|
const roleId = getCookiesDecrypt("urie");
|
||||||
|
const [selectedFileType, setSelectedFileType] = useState("original");
|
||||||
|
|
||||||
const [categories, setCategories] = useState<Category[]>([]);
|
const [categories, setCategories] = useState<Category[]>([]);
|
||||||
const [selectedCategory, setSelectedCategory] = useState<any>();
|
const [selectedCategory, setSelectedCategory] = useState<any>();
|
||||||
|
|
@ -116,7 +118,10 @@ export default function FormImage() {
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
||||||
const [selectedWritingStyle, setSelectedWritingStyle] = useState("");
|
const [selectedWritingStyle, setSelectedWritingStyle] =
|
||||||
|
useState("professional");
|
||||||
|
const [editorContent, setEditorContent] = useState(""); // Untuk original editor
|
||||||
|
const [rewriteEditorContent, setRewriteEditorContent] = useState("");
|
||||||
const [selectedSize, setSelectedSize] = useState("");
|
const [selectedSize, setSelectedSize] = useState("");
|
||||||
const [detailData, setDetailData] = useState<any>(null);
|
const [detailData, setDetailData] = useState<any>(null);
|
||||||
const [articleImages, setArticleImages] = useState<string[]>([]);
|
const [articleImages, setArticleImages] = useState<string[]>([]);
|
||||||
|
|
@ -125,6 +130,8 @@ export default function FormImage() {
|
||||||
|
|
||||||
const [content, setContent] = useState("");
|
const [content, setContent] = useState("");
|
||||||
|
|
||||||
|
const [isContentRewriteClicked, setIsContentRewriteClicked] = useState(false);
|
||||||
|
|
||||||
const [selectedTarget, setSelectedTarget] = useState("");
|
const [selectedTarget, setSelectedTarget] = useState("");
|
||||||
const [unitSelection, setUnitSelection] = useState({
|
const [unitSelection, setUnitSelection] = useState({
|
||||||
allUnit: false,
|
allUnit: false,
|
||||||
|
|
@ -140,6 +147,7 @@ export default function FormImage() {
|
||||||
let uploadPersen = 0;
|
let uploadPersen = 0;
|
||||||
const [isStartUpload, setIsStartUpload] = useState(false);
|
const [isStartUpload, setIsStartUpload] = useState(false);
|
||||||
const [counterProgress, setCounterProgress] = useState(0);
|
const [counterProgress, setCounterProgress] = useState(0);
|
||||||
|
const [showRewriteEditor, setShowRewriteEditor] = useState(false);
|
||||||
|
|
||||||
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
const [files, setFiles] = useState<FileWithPreview[]>([]);
|
||||||
const [filesTemp, setFilesTemp] = useState<File[]>([]);
|
const [filesTemp, setFilesTemp] = useState<File[]>([]);
|
||||||
|
|
@ -164,16 +172,10 @@ export default function FormImage() {
|
||||||
|
|
||||||
const imageSchema = z.object({
|
const imageSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
description: z
|
description: z.string().optional(),
|
||||||
.string()
|
descriptionOri: z.string().optional(),
|
||||||
.min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." })
|
rewriteDescription: z.string().optional(),
|
||||||
.or(
|
|
||||||
z.literal(articleBody || "").refine((val) => val.length > 0, {
|
|
||||||
message: "Deskripsi diperlukan.",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
||||||
// tags: z.string().min(1, { message: "Judul diperlukan" }),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|
@ -184,6 +186,11 @@ export default function FormImage() {
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm<ImageSchema>({
|
} = useForm<ImageSchema>({
|
||||||
resolver: zodResolver(imageSchema),
|
resolver: zodResolver(imageSchema),
|
||||||
|
defaultValues: {
|
||||||
|
description: "",
|
||||||
|
descriptionOri: "",
|
||||||
|
rewriteDescription: "",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const doGenerateMainKeyword = async () => {
|
const doGenerateMainKeyword = async () => {
|
||||||
|
|
@ -446,13 +453,25 @@ export default function FormImage() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (articleBody) {
|
||||||
|
setValue("description", articleBody);
|
||||||
|
setValue("rewriteDescription", articleBody);
|
||||||
|
}
|
||||||
|
}, [articleBody, setValue]);
|
||||||
|
|
||||||
const save = async (data: ImageSchema) => {
|
const save = async (data: ImageSchema) => {
|
||||||
loading();
|
loading();
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
const finalTitle = isSwitchOn ? title : data.title;
|
const finalTitle = isSwitchOn ? title : data.title;
|
||||||
const finalDescription = articleBody || data.description;
|
// const finalDescription = articleBody || data.description;
|
||||||
|
const finalDescription = isSwitchOn
|
||||||
|
? data.description
|
||||||
|
: selectedFileType === "rewrite"
|
||||||
|
? data.rewriteDescription
|
||||||
|
: data.descriptionOri;
|
||||||
|
|
||||||
if (!finalDescription.trim()) {
|
if (!finalDescription?.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -716,6 +735,45 @@ export default function FormImage() {
|
||||||
}
|
}
|
||||||
}, [title, getValues, setValue]);
|
}, [title, getValues, setValue]);
|
||||||
|
|
||||||
|
const handleRewriteClick = async () => {
|
||||||
|
setIsContentRewriteClicked(true);
|
||||||
|
|
||||||
|
const request = {
|
||||||
|
style: selectedWritingStyle,
|
||||||
|
lang: "id",
|
||||||
|
contextType: "text",
|
||||||
|
urlContext: null,
|
||||||
|
context: editorContent, // Ambil isi editor original
|
||||||
|
createdBy: roleId,
|
||||||
|
sentiment: "Humorous",
|
||||||
|
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await generateDataRewrite(request);
|
||||||
|
close();
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
console.error(res.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newArticleId = res?.data?.data?.id;
|
||||||
|
setIsGeneratedArticle(true);
|
||||||
|
|
||||||
|
setArticleIds((prevIds: string[]) => {
|
||||||
|
if (prevIds.length < 3) {
|
||||||
|
return [...prevIds, newArticleId];
|
||||||
|
} else {
|
||||||
|
const updatedIds = [...prevIds];
|
||||||
|
updatedIds[2] = newArticleId;
|
||||||
|
return updatedIds;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds));
|
||||||
|
setShowRewriteEditor(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="flex flex-col lg:flex-row gap-10">
|
<div className="flex flex-col lg:flex-row gap-10">
|
||||||
|
|
@ -930,6 +988,7 @@ export default function FormImage() {
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={handleGenerateArtikel}
|
onClick={handleGenerateArtikel}
|
||||||
size="sm"
|
size="sm"
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
Generate Article
|
Generate Article
|
||||||
</Button>
|
</Button>
|
||||||
|
|
@ -972,8 +1031,6 @@ export default function FormImage() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
<Label>{t("description")}</Label>
|
<Label>{t("description")}</Label>
|
||||||
<Controller
|
<Controller
|
||||||
|
|
@ -982,11 +1039,16 @@ export default function FormImage() {
|
||||||
render={({ field: { onChange, value } }) =>
|
render={({ field: { onChange, value } }) =>
|
||||||
isLoadingData ? (
|
isLoadingData ? (
|
||||||
<div className="flex justify-center items-center h-40">
|
<div className="flex justify-center items-center h-40">
|
||||||
<p className="text-gray-500">Loading Proses Data...</p>
|
<p className="text-gray-500">
|
||||||
|
Loading Proses Data...
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<CustomEditor
|
<CustomEditor
|
||||||
onChange={onChange}
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setEditorContent(value);
|
||||||
|
}}
|
||||||
initialData={articleBody || value}
|
initialData={articleBody || value}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
@ -998,6 +1060,110 @@ export default function FormImage() {
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isSwitchOn && (
|
||||||
|
<>
|
||||||
|
<RadioGroup
|
||||||
|
onValueChange={(value) => setSelectedFileType(value)}
|
||||||
|
value={selectedFileType}
|
||||||
|
className=" grid-cols-1"
|
||||||
|
>
|
||||||
|
<div className="">
|
||||||
|
<RadioGroupItem value="original" id="original-file" />
|
||||||
|
<Label htmlFor="original-file">
|
||||||
|
Select Original Description
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="py-3 space-y-2">
|
||||||
|
<Label>{t("description")}</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="descriptionOri"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setEditorContent(value);
|
||||||
|
}}
|
||||||
|
initialData={value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{errors.description?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.description.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-sm font-semibold">Content Rewrite</p>
|
||||||
|
<div className="my-2">
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
type="button"
|
||||||
|
onClick={handleRewriteClick}
|
||||||
|
className="bg-blue-500 text-white py-2 px-4 rounded"
|
||||||
|
>
|
||||||
|
Content Rewrite
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{showRewriteEditor && (
|
||||||
|
<div>
|
||||||
|
{isGeneratedArticle && (
|
||||||
|
<div className="mt-3 pb-0 flex flex-row ">
|
||||||
|
{articleIds.map((id: string, index: number) => (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
key={index}
|
||||||
|
className={`mr-3 px-3 py-2 rounded-md ${
|
||||||
|
selectedArticleId === id
|
||||||
|
? "bg-green-500 text-white"
|
||||||
|
: "border-2 border-green-500 bg-white text-green-500 hover:bg-green-500 hover:text-white hover:border-green-500"
|
||||||
|
}`}
|
||||||
|
onClick={() => handleArticleIdClick(id)}
|
||||||
|
>
|
||||||
|
{"Narasi " + (index + 1)}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex items-center space-x-2 mt-3">
|
||||||
|
<RadioGroupItem value="rewrite" id="rewrite-file" />
|
||||||
|
<Label htmlFor="rewrite-file">
|
||||||
|
Select Description Rewrite
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="py-3 space-y-2">
|
||||||
|
<Label>{t("file-rewrite")}</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="rewriteDescription"
|
||||||
|
render={({ field: { onChange, value } }) =>
|
||||||
|
isLoadingData ? (
|
||||||
|
<div className="flex justify-center items-center h-40">
|
||||||
|
<p className="text-gray-500">
|
||||||
|
Loading Proses Data...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setRewriteEditorContent(value);
|
||||||
|
}}
|
||||||
|
initialData={articleBody || value}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</RadioGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
<Label>{t("select-file")}</Label>
|
<Label>{t("select-file")}</Label>
|
||||||
{/* <Input
|
{/* <Input
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -16,7 +16,7 @@ import * as z from "zod";
|
||||||
import { Upload } from "tus-js-client";
|
import { Upload } from "tus-js-client";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import { redirect, useRouter } from "next/navigation";
|
import { redirect, useParams, useRouter } from "next/navigation";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
|
|
@ -40,6 +40,7 @@ import { uploadThumbnailBlog } from "@/service/blog/blog";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import {
|
import {
|
||||||
generateDataArticle,
|
generateDataArticle,
|
||||||
|
generateDataRewrite,
|
||||||
getDetailArticle,
|
getDetailArticle,
|
||||||
getGenerateKeywords,
|
getGenerateKeywords,
|
||||||
getGenerateTitle,
|
getGenerateTitle,
|
||||||
|
|
@ -83,11 +84,15 @@ export default function FormTeks() {
|
||||||
const editor = useRef(null);
|
const editor = useRef(null);
|
||||||
type TeksSchema = z.infer<typeof teksSchema>;
|
type TeksSchema = z.infer<typeof teksSchema>;
|
||||||
|
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
|
||||||
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
||||||
const taskId = Cookies.get("taskId");
|
const taskId = Cookies.get("taskId");
|
||||||
const scheduleId = Cookies.get("scheduleId");
|
const scheduleId = Cookies.get("scheduleId");
|
||||||
const scheduleType = Cookies.get("scheduleType");
|
const scheduleType = Cookies.get("scheduleType");
|
||||||
const roleId = getCookiesDecrypt("urie");
|
const roleId = getCookiesDecrypt("urie");
|
||||||
|
const [selectedFileType, setSelectedFileType] = useState("original");
|
||||||
|
|
||||||
const [categories, setCategories] = useState<Category[]>([]);
|
const [categories, setCategories] = useState<Category[]>([]);
|
||||||
const [selectedCategory, setSelectedCategory] = useState<any>();
|
const [selectedCategory, setSelectedCategory] = useState<any>();
|
||||||
|
|
@ -102,6 +107,10 @@ export default function FormTeks() {
|
||||||
const [editingArticleId, setEditingArticleId] = useState<string | null>(null);
|
const [editingArticleId, setEditingArticleId] = useState<string | null>(null);
|
||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
const [isLoadingData, setIsLoadingData] = useState<boolean>(false);
|
const [isLoadingData, setIsLoadingData] = useState<boolean>(false);
|
||||||
|
const [selectedWritingStyle, setSelectedWritingStyle] =
|
||||||
|
useState("professional");
|
||||||
|
const [editorContent, setEditorContent] = useState(""); // Untuk original editor
|
||||||
|
const [rewriteEditorContent, setRewriteEditorContent] = useState("");
|
||||||
|
|
||||||
const [articleIds, setArticleIds] = useState<string[]>([]);
|
const [articleIds, setArticleIds] = useState<string[]>([]);
|
||||||
const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
|
const [isGeneratedArticle, setIsGeneratedArticle] = useState(false);
|
||||||
|
|
@ -109,8 +118,9 @@ export default function FormTeks() {
|
||||||
const [selectedArticleId, setSelectedArticleId] = useState<string | null>(
|
const [selectedArticleId, setSelectedArticleId] = useState<string | null>(
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
const [isContentRewriteClicked, setIsContentRewriteClicked] = useState(false);
|
||||||
|
const [showRewriteEditor, setShowRewriteEditor] = useState(false);
|
||||||
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
||||||
const [selectedWritingStyle, setSelectedWritingStyle] = useState("");
|
|
||||||
const [selectedSize, setSelectedSize] = useState("");
|
const [selectedSize, setSelectedSize] = useState("");
|
||||||
const [detailData, setDetailData] = useState<any>(null);
|
const [detailData, setDetailData] = useState<any>(null);
|
||||||
const [articleImages, setArticleImages] = useState<string[]>([]);
|
const [articleImages, setArticleImages] = useState<string[]>([]);
|
||||||
|
|
@ -157,14 +167,9 @@ export default function FormTeks() {
|
||||||
|
|
||||||
const teksSchema = z.object({
|
const teksSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
description: z
|
description: z.string().optional(),
|
||||||
.string()
|
descriptionOri: z.string().optional(), // Original editor
|
||||||
.min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." })
|
rewriteDescription: z.string().optional(),
|
||||||
.or(
|
|
||||||
z.literal(articleBody || "").refine((val) => val.length > 0, {
|
|
||||||
message: "Deskripsi diperlukan.",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
||||||
// tags: z.string().min(1, { message: "Judul diperlukan" }),
|
// tags: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
});
|
});
|
||||||
|
|
@ -177,6 +182,11 @@ export default function FormTeks() {
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm<TeksSchema>({
|
} = useForm<TeksSchema>({
|
||||||
resolver: zodResolver(teksSchema),
|
resolver: zodResolver(teksSchema),
|
||||||
|
defaultValues: {
|
||||||
|
description: "",
|
||||||
|
descriptionOri: "",
|
||||||
|
rewriteDescription: "",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const doGenerateMainKeyword = async () => {
|
const doGenerateMainKeyword = async () => {
|
||||||
|
|
@ -439,12 +449,26 @@ export default function FormTeks() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (articleBody) {
|
||||||
|
// Set ke dua field jika rewrite juga aktif
|
||||||
|
setValue("description", articleBody);
|
||||||
|
setValue("rewriteDescription", articleBody);
|
||||||
|
}
|
||||||
|
}, [articleBody, setValue]);
|
||||||
|
|
||||||
const save = async (data: TeksSchema) => {
|
const save = async (data: TeksSchema) => {
|
||||||
loading();
|
loading();
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
const finalTitle = isSwitchOn ? title : data.title;
|
const finalTitle = isSwitchOn ? title : data.title;
|
||||||
const finalDescription = articleBody || data.description;
|
|
||||||
if (!finalDescription.trim()) {
|
const finalDescription = isSwitchOn
|
||||||
|
? data.description
|
||||||
|
: selectedFileType === "rewrite"
|
||||||
|
? data.rewriteDescription
|
||||||
|
: data.descriptionOri;
|
||||||
|
|
||||||
|
if (!finalDescription?.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -709,6 +733,45 @@ export default function FormTeks() {
|
||||||
}
|
}
|
||||||
}, [title, getValues, setValue]);
|
}, [title, getValues, setValue]);
|
||||||
|
|
||||||
|
const handleRewriteClick = async () => {
|
||||||
|
setIsContentRewriteClicked(true);
|
||||||
|
|
||||||
|
const request = {
|
||||||
|
style: selectedWritingStyle,
|
||||||
|
lang: "id",
|
||||||
|
contextType: "text",
|
||||||
|
urlContext: null,
|
||||||
|
context: editorContent, // Ambil isi editor original
|
||||||
|
createdBy: roleId,
|
||||||
|
sentiment: "Humorous",
|
||||||
|
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await generateDataRewrite(request);
|
||||||
|
close();
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
console.error(res.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newArticleId = res?.data?.data?.id;
|
||||||
|
setIsGeneratedArticle(true);
|
||||||
|
|
||||||
|
setArticleIds((prevIds: string[]) => {
|
||||||
|
if (prevIds.length < 3) {
|
||||||
|
return [...prevIds, newArticleId];
|
||||||
|
} else {
|
||||||
|
const updatedIds = [...prevIds];
|
||||||
|
updatedIds[2] = newArticleId;
|
||||||
|
return updatedIds;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds));
|
||||||
|
setShowRewriteEditor(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="flex flex-col lg:flex-row gap-10">
|
<div className="flex flex-col lg:flex-row gap-10">
|
||||||
|
|
@ -901,7 +964,7 @@ export default function FormTeks() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-5">
|
<div className="mt-5">
|
||||||
<Label>{t("special-instructions")} (Optional)</Label>
|
<Label>{t("special-instructions")}(Optional)</Label>
|
||||||
<div className="mt-3">
|
<div className="mt-3">
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -923,13 +986,14 @@ export default function FormTeks() {
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={handleGenerateArtikel}
|
onClick={handleGenerateArtikel}
|
||||||
size="sm"
|
size="sm"
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
Generate Article
|
Generate Article
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isGeneratedArticle && (
|
{isGeneratedArticle && (
|
||||||
<div className="mt-3 pb-0 flex flex-row ">
|
<div className="mt-3 pb-0 flex flex-row">
|
||||||
{articleIds.map((id: string, index: number) => (
|
{articleIds.map((id: string, index: number) => (
|
||||||
<p
|
<p
|
||||||
key={index}
|
key={index}
|
||||||
|
|
@ -949,27 +1013,23 @@ export default function FormTeks() {
|
||||||
<div className="pt-3">
|
<div className="pt-3">
|
||||||
<div className="flex flex-row justify-between items-center">
|
<div className="flex flex-row justify-between items-center">
|
||||||
{selectedArticleId && (
|
{selectedArticleId && (
|
||||||
<Link
|
|
||||||
href={`/contributor/content/teks/update-seo/${selectedArticleId}`}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Button
|
<Button
|
||||||
className="mb-2"
|
className="mb-2"
|
||||||
size="sm"
|
size="sm"
|
||||||
variant={"outline"}
|
variant={"outline"}
|
||||||
color="primary"
|
color="primary"
|
||||||
|
onClick={() => {
|
||||||
|
const url = `/${locale}/contributor/content/image/update-seo/${selectedArticleId}`;
|
||||||
|
window.open(url, "_blank", "noopener,noreferrer");
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t("update")}
|
{t("update")}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="py-3 space-y-2">
|
||||||
)}
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label>{t("description")}</Label>
|
<Label>{t("description")}</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -977,11 +1037,16 @@ export default function FormTeks() {
|
||||||
render={({ field: { onChange, value } }) =>
|
render={({ field: { onChange, value } }) =>
|
||||||
isLoadingData ? (
|
isLoadingData ? (
|
||||||
<div className="flex justify-center items-center h-40">
|
<div className="flex justify-center items-center h-40">
|
||||||
<p className="text-gray-500">Loading Proses Data...</p>
|
<p className="text-gray-500">
|
||||||
|
Loading Proses Data...
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<CustomEditor
|
<CustomEditor
|
||||||
onChange={onChange}
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setEditorContent(value);
|
||||||
|
}}
|
||||||
initialData={articleBody || value}
|
initialData={articleBody || value}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
@ -993,6 +1058,110 @@ export default function FormTeks() {
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isSwitchOn && (
|
||||||
|
<>
|
||||||
|
<RadioGroup
|
||||||
|
onValueChange={(value) => setSelectedFileType(value)}
|
||||||
|
value={selectedFileType}
|
||||||
|
className=" grid-cols-1"
|
||||||
|
>
|
||||||
|
<div className="">
|
||||||
|
<RadioGroupItem value="original" id="original-file" />
|
||||||
|
<Label htmlFor="original-file">
|
||||||
|
Select Original Description
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="py-3 space-y-2">
|
||||||
|
<Label>{t("description")}</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="descriptionOri"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setEditorContent(value);
|
||||||
|
}}
|
||||||
|
initialData={value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{errors.description?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.description.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-sm font-semibold">Content Rewrite</p>
|
||||||
|
<div className="my-2">
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
type="button"
|
||||||
|
onClick={handleRewriteClick}
|
||||||
|
className="bg-blue-500 text-white py-2 px-4 rounded"
|
||||||
|
>
|
||||||
|
Content Rewrite
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{showRewriteEditor && (
|
||||||
|
<div>
|
||||||
|
{isGeneratedArticle && (
|
||||||
|
<div className="mt-3 pb-0 flex flex-row ">
|
||||||
|
{articleIds.map((id: string, index: number) => (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
key={index}
|
||||||
|
className={`mr-3 px-3 py-2 rounded-md ${
|
||||||
|
selectedArticleId === id
|
||||||
|
? "bg-green-500 text-white"
|
||||||
|
: "border-2 border-green-500 bg-white text-green-500 hover:bg-green-500 hover:text-white hover:border-green-500"
|
||||||
|
}`}
|
||||||
|
onClick={() => handleArticleIdClick(id)}
|
||||||
|
>
|
||||||
|
{"Narasi " + (index + 1)}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex items-center space-x-2 mt-3">
|
||||||
|
<RadioGroupItem value="rewrite" id="rewrite-file" />
|
||||||
|
<Label htmlFor="rewrite-file">
|
||||||
|
Select Description Rewrite
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="py-3 space-y-2">
|
||||||
|
<Label>{t("file-rewrite")}</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="rewriteDescription"
|
||||||
|
render={({ field: { onChange, value } }) =>
|
||||||
|
isLoadingData ? (
|
||||||
|
<div className="flex justify-center items-center h-40">
|
||||||
|
<p className="text-gray-500">
|
||||||
|
Loading Proses Data...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setRewriteEditorContent(value);
|
||||||
|
}}
|
||||||
|
initialData={articleBody || value}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</RadioGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
<Label>{t("select-file")}</Label>
|
<Label>{t("select-file")}</Label>
|
||||||
{/* <Input
|
{/* <Input
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ import * as z from "zod";
|
||||||
import { Upload } from "tus-js-client";
|
import { Upload } from "tus-js-client";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import { redirect, useRouter } from "next/navigation";
|
import { redirect, useParams, useRouter } from "next/navigation";
|
||||||
import {
|
import {
|
||||||
Select,
|
Select,
|
||||||
SelectContent,
|
SelectContent,
|
||||||
|
|
@ -40,6 +40,7 @@ import { uploadThumbnailBlog } from "@/service/blog/blog";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
import {
|
import {
|
||||||
generateDataArticle,
|
generateDataArticle,
|
||||||
|
generateDataRewrite,
|
||||||
getDetailArticle,
|
getDetailArticle,
|
||||||
getGenerateKeywords,
|
getGenerateKeywords,
|
||||||
getGenerateTitle,
|
getGenerateTitle,
|
||||||
|
|
@ -82,12 +83,15 @@ export default function FormVideo() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const editor = useRef(null);
|
const editor = useRef(null);
|
||||||
type VideoSchema = z.infer<typeof videoSchema>;
|
type VideoSchema = z.infer<typeof videoSchema>;
|
||||||
|
const params = useParams();
|
||||||
|
const locale = params?.locale;
|
||||||
|
|
||||||
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
const [selectedFiles, setSelectedFiles] = useState<File[]>([]);
|
||||||
const taskId = Cookies.get("taskId");
|
const taskId = Cookies.get("taskId");
|
||||||
const scheduleId = Cookies.get("scheduleId");
|
const scheduleId = Cookies.get("scheduleId");
|
||||||
const scheduleType = Cookies.get("scheduleType");
|
const scheduleType = Cookies.get("scheduleType");
|
||||||
const roleId = getCookiesDecrypt("urie");
|
const roleId = getCookiesDecrypt("urie");
|
||||||
|
const [selectedFileType, setSelectedFileType] = useState("original");
|
||||||
|
|
||||||
const t = useTranslations("Form");
|
const t = useTranslations("Form");
|
||||||
const [categories, setCategories] = useState<Category[]>([]);
|
const [categories, setCategories] = useState<Category[]>([]);
|
||||||
|
|
@ -97,6 +101,11 @@ export default function FormVideo() {
|
||||||
const [preview, setPreview] = useState<string | null>(null);
|
const [preview, setPreview] = useState<string | null>(null);
|
||||||
const [selectedLanguage, setSelectedLanguage] = useState("");
|
const [selectedLanguage, setSelectedLanguage] = useState("");
|
||||||
|
|
||||||
|
const [selectedWritingStyle, setSelectedWritingStyle] =
|
||||||
|
useState("professional");
|
||||||
|
const [editorContent, setEditorContent] = useState(""); // Untuk original editor
|
||||||
|
const [rewriteEditorContent, setRewriteEditorContent] = useState("");
|
||||||
|
|
||||||
const [selectedSEO, setSelectedSEO] = useState<string>("");
|
const [selectedSEO, setSelectedSEO] = useState<string>("");
|
||||||
const [title, setTitle] = useState<string>("");
|
const [title, setTitle] = useState<string>("");
|
||||||
const [selectedAdvConfig, setSelectedAdvConfig] = useState<string>("");
|
const [selectedAdvConfig, setSelectedAdvConfig] = useState<string>("");
|
||||||
|
|
@ -111,13 +120,17 @@ export default function FormVideo() {
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
const [selectedMainKeyword, setSelectedMainKeyword] = useState("");
|
||||||
const [selectedWritingStyle, setSelectedWritingStyle] = useState("");
|
// const [selectedWritingStyle, setSelectedWritingStyle] = useState("");
|
||||||
const [selectedSize, setSelectedSize] = useState("");
|
const [selectedSize, setSelectedSize] = useState("");
|
||||||
const [detailData, setDetailData] = useState<any>(null);
|
const [detailData, setDetailData] = useState<any>(null);
|
||||||
const [articleImages, setArticleImages] = useState<string[]>([]);
|
const [articleImages, setArticleImages] = useState<string[]>([]);
|
||||||
const [isSwitchOn, setIsSwitchOn] = useState<boolean>(false);
|
const [isSwitchOn, setIsSwitchOn] = useState<boolean>(false);
|
||||||
const inputRef = useRef<HTMLInputElement>(null);
|
const inputRef = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const [showRewriteEditor, setShowRewriteEditor] = useState(false);
|
||||||
|
|
||||||
|
const [isContentRewriteClicked, setIsContentRewriteClicked] = useState(false);
|
||||||
|
|
||||||
const [selectedTarget, setSelectedTarget] = useState("");
|
const [selectedTarget, setSelectedTarget] = useState("");
|
||||||
const [unitSelection, setUnitSelection] = useState({
|
const [unitSelection, setUnitSelection] = useState({
|
||||||
allUnit: false,
|
allUnit: false,
|
||||||
|
|
@ -155,14 +168,9 @@ export default function FormVideo() {
|
||||||
|
|
||||||
const videoSchema = z.object({
|
const videoSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
title: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
description: z
|
description: z.string().optional(),
|
||||||
.string()
|
descriptionOri: z.string().optional(), // Original editor
|
||||||
.min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." })
|
rewriteDescription: z.string().optional(),
|
||||||
.or(
|
|
||||||
z.literal(articleBody || "").refine((val) => val.length > 0, {
|
|
||||||
message: "Deskripsi diperlukan.",
|
|
||||||
})
|
|
||||||
),
|
|
||||||
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
creatorName: z.string().min(1, { message: "Creator diperlukan" }),
|
||||||
// tags: z.string().min(1, { message: "Judul diperlukan" }),
|
// tags: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
});
|
});
|
||||||
|
|
@ -175,6 +183,11 @@ export default function FormVideo() {
|
||||||
formState: { errors },
|
formState: { errors },
|
||||||
} = useForm<VideoSchema>({
|
} = useForm<VideoSchema>({
|
||||||
resolver: zodResolver(videoSchema),
|
resolver: zodResolver(videoSchema),
|
||||||
|
defaultValues: {
|
||||||
|
description: "",
|
||||||
|
descriptionOri: "",
|
||||||
|
rewriteDescription: "",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const doGenerateMainKeyword = async () => {
|
const doGenerateMainKeyword = async () => {
|
||||||
|
|
@ -437,15 +450,30 @@ export default function FormVideo() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (articleBody) {
|
||||||
|
// Set ke dua field jika rewrite juga aktif
|
||||||
|
setValue("description", articleBody);
|
||||||
|
setValue("rewriteDescription", articleBody);
|
||||||
|
}
|
||||||
|
}, [articleBody, setValue]);
|
||||||
|
|
||||||
const save = async (data: VideoSchema) => {
|
const save = async (data: VideoSchema) => {
|
||||||
loading();
|
loading();
|
||||||
const finalTags = tags.join(", ");
|
const finalTags = tags.join(", ");
|
||||||
const finalTitle = isSwitchOn ? title : data.title;
|
const finalTitle = isSwitchOn ? title : data.title;
|
||||||
const finalDescription = articleBody || data.description;
|
// const finalDescription = articleBody || data.description;
|
||||||
if (!finalDescription.trim()) {
|
const finalDescription = isSwitchOn
|
||||||
|
? data.description
|
||||||
|
: selectedFileType === "rewrite"
|
||||||
|
? data.rewriteDescription
|
||||||
|
: data.descriptionOri;
|
||||||
|
|
||||||
|
if (!finalDescription?.trim()) {
|
||||||
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
MySwal.fire("Error", "Deskripsi tidak boleh kosong.", "error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let requestData: {
|
let requestData: {
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
|
|
@ -726,6 +754,45 @@ export default function FormVideo() {
|
||||||
}
|
}
|
||||||
}, [title, getValues, setValue]);
|
}, [title, getValues, setValue]);
|
||||||
|
|
||||||
|
const handleRewriteClick = async () => {
|
||||||
|
setIsContentRewriteClicked(true);
|
||||||
|
|
||||||
|
const request = {
|
||||||
|
style: selectedWritingStyle,
|
||||||
|
lang: "id",
|
||||||
|
contextType: "text",
|
||||||
|
urlContext: null,
|
||||||
|
context: editorContent, // Ambil isi editor original
|
||||||
|
createdBy: roleId,
|
||||||
|
sentiment: "Humorous",
|
||||||
|
clientId: "7QTW8cMojyayt6qnhqTOeJaBI70W4EaQ",
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await generateDataRewrite(request);
|
||||||
|
close();
|
||||||
|
|
||||||
|
if (res?.error) {
|
||||||
|
console.error(res.message);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const newArticleId = res?.data?.data?.id;
|
||||||
|
setIsGeneratedArticle(true);
|
||||||
|
|
||||||
|
setArticleIds((prevIds: string[]) => {
|
||||||
|
if (prevIds.length < 3) {
|
||||||
|
return [...prevIds, newArticleId];
|
||||||
|
} else {
|
||||||
|
const updatedIds = [...prevIds];
|
||||||
|
updatedIds[2] = newArticleId;
|
||||||
|
return updatedIds;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Cookies.set("nulisAIArticleIdTemp", JSON.stringify(articleIds));
|
||||||
|
setShowRewriteEditor(true);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="flex flex-col lg:flex-row gap-10">
|
<div className="flex flex-col lg:flex-row gap-10">
|
||||||
|
|
@ -917,7 +984,7 @@ export default function FormVideo() {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-5">
|
<div className="mt-5">
|
||||||
<Label>{t("special-instructions")} (Optional)</Label>
|
<Label>{t("special-instructions")}(Optional)</Label>
|
||||||
<div className="mt-3">
|
<div className="mt-3">
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -939,13 +1006,14 @@ export default function FormVideo() {
|
||||||
color="primary"
|
color="primary"
|
||||||
onClick={handleGenerateArtikel}
|
onClick={handleGenerateArtikel}
|
||||||
size="sm"
|
size="sm"
|
||||||
|
type="button"
|
||||||
>
|
>
|
||||||
Generate Article
|
Generate Article
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{isGeneratedArticle && (
|
{isGeneratedArticle && (
|
||||||
<div className="mt-3 pb-0 flex flex-row ">
|
<div className="mt-3 pb-0 flex flex-row">
|
||||||
{articleIds.map((id: string, index: number) => (
|
{articleIds.map((id: string, index: number) => (
|
||||||
<p
|
<p
|
||||||
key={index}
|
key={index}
|
||||||
|
|
@ -965,27 +1033,23 @@ export default function FormVideo() {
|
||||||
<div className="pt-3">
|
<div className="pt-3">
|
||||||
<div className="flex flex-row justify-between items-center">
|
<div className="flex flex-row justify-between items-center">
|
||||||
{selectedArticleId && (
|
{selectedArticleId && (
|
||||||
<Link
|
|
||||||
href={`/contributor/content/video/update-seo/${selectedArticleId}`}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
<Button
|
<Button
|
||||||
className="mb-2"
|
className="mb-2"
|
||||||
size="sm"
|
size="sm"
|
||||||
variant={"outline"}
|
variant={"outline"}
|
||||||
color="primary"
|
color="primary"
|
||||||
|
onClick={() => {
|
||||||
|
const url = `/${locale}/contributor/content/image/update-seo/${selectedArticleId}`;
|
||||||
|
window.open(url, "_blank", "noopener,noreferrer");
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t("update")}
|
{t("update")}
|
||||||
</Button>
|
</Button>
|
||||||
</Link>
|
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="py-3 space-y-2">
|
||||||
)}
|
|
||||||
<div className="space-y-2">
|
|
||||||
<Label>{t("description")}</Label>
|
<Label>{t("description")}</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
|
|
@ -993,11 +1057,16 @@ export default function FormVideo() {
|
||||||
render={({ field: { onChange, value } }) =>
|
render={({ field: { onChange, value } }) =>
|
||||||
isLoadingData ? (
|
isLoadingData ? (
|
||||||
<div className="flex justify-center items-center h-40">
|
<div className="flex justify-center items-center h-40">
|
||||||
<p className="text-gray-500">Loading Proses Data...</p>
|
<p className="text-gray-500">
|
||||||
|
Loading Proses Data...
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<CustomEditor
|
<CustomEditor
|
||||||
onChange={onChange}
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setEditorContent(value);
|
||||||
|
}}
|
||||||
initialData={articleBody || value}
|
initialData={articleBody || value}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
@ -1009,6 +1078,110 @@ export default function FormVideo() {
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{!isSwitchOn && (
|
||||||
|
<>
|
||||||
|
<RadioGroup
|
||||||
|
onValueChange={(value) => setSelectedFileType(value)}
|
||||||
|
value={selectedFileType}
|
||||||
|
className=" grid-cols-1"
|
||||||
|
>
|
||||||
|
<div className="">
|
||||||
|
<RadioGroupItem value="original" id="original-file" />
|
||||||
|
<Label htmlFor="original-file">
|
||||||
|
Select Original Description
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="py-3 space-y-2">
|
||||||
|
<Label>{t("description")}</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="descriptionOri"
|
||||||
|
render={({ field: { onChange, value } }) => (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setEditorContent(value);
|
||||||
|
}}
|
||||||
|
initialData={value}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{errors.description?.message && (
|
||||||
|
<p className="text-red-400 text-sm">
|
||||||
|
{errors.description.message}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="text-sm font-semibold">Content Rewrite</p>
|
||||||
|
<div className="my-2">
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
type="button"
|
||||||
|
onClick={handleRewriteClick}
|
||||||
|
className="bg-blue-500 text-white py-2 px-4 rounded"
|
||||||
|
>
|
||||||
|
Content Rewrite
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{showRewriteEditor && (
|
||||||
|
<div>
|
||||||
|
{isGeneratedArticle && (
|
||||||
|
<div className="mt-3 pb-0 flex flex-row ">
|
||||||
|
{articleIds.map((id: string, index: number) => (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
key={index}
|
||||||
|
className={`mr-3 px-3 py-2 rounded-md ${
|
||||||
|
selectedArticleId === id
|
||||||
|
? "bg-green-500 text-white"
|
||||||
|
: "border-2 border-green-500 bg-white text-green-500 hover:bg-green-500 hover:text-white hover:border-green-500"
|
||||||
|
}`}
|
||||||
|
onClick={() => handleArticleIdClick(id)}
|
||||||
|
>
|
||||||
|
{"Narasi " + (index + 1)}
|
||||||
|
</Button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="flex items-center space-x-2 mt-3">
|
||||||
|
<RadioGroupItem value="rewrite" id="rewrite-file" />
|
||||||
|
<Label htmlFor="rewrite-file">
|
||||||
|
Select Description Rewrite
|
||||||
|
</Label>
|
||||||
|
</div>
|
||||||
|
<div className="py-3 space-y-2">
|
||||||
|
<Label>{t("file-rewrite")}</Label>
|
||||||
|
<Controller
|
||||||
|
control={control}
|
||||||
|
name="rewriteDescription"
|
||||||
|
render={({ field: { onChange, value } }) =>
|
||||||
|
isLoadingData ? (
|
||||||
|
<div className="flex justify-center items-center h-40">
|
||||||
|
<p className="text-gray-500">
|
||||||
|
Loading Proses Data...
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<CustomEditor
|
||||||
|
onChange={(value: any) => {
|
||||||
|
onChange(value);
|
||||||
|
setRewriteEditorContent(value);
|
||||||
|
}}
|
||||||
|
initialData={articleBody || value}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</RadioGroup>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
<div className="py-3 space-y-2">
|
<div className="py-3 space-y-2">
|
||||||
<Label>{t("select-file")}</Label>
|
<Label>{t("select-file")}</Label>
|
||||||
{/* <Input
|
{/* <Input
|
||||||
|
|
|
||||||
|
|
@ -202,6 +202,23 @@ export default function FormAskExpert() {
|
||||||
const details = response?.data?.data;
|
const details = response?.data?.data;
|
||||||
|
|
||||||
setDetail(details);
|
setDetail(details);
|
||||||
|
|
||||||
|
if (details?.assignedToLevel) {
|
||||||
|
const levels: Set<number> = new Set(
|
||||||
|
details.assignedToLevel.split(",").map((x: any) => Number(x))
|
||||||
|
);
|
||||||
|
setCheckedLevels(levels);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (details?.assignedToUsers) {
|
||||||
|
const userIds = details.assignedToUsers.split(",").map(Number);
|
||||||
|
setCheckedLevels(new Set(userIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (details?.expertCompetencies) {
|
||||||
|
const compIds = details.expertCompetencies.split(",").map(Number);
|
||||||
|
setSelectedCompetencies(new Set(compIds));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
initState();
|
initState();
|
||||||
|
|
@ -515,7 +532,7 @@ export default function FormAskExpert() {
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<div className="px-6 py-6">
|
<div className="px-6 py-6">
|
||||||
<p className="text-lg font-semibold mb-3">{t("form-task")}</p>
|
<p className="text-lg font-semibold mb-3">{t("form-task-ta")}</p>
|
||||||
{detail !== undefined ? (
|
{detail !== undefined ? (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="gap-5 mb-5">
|
<div className="gap-5 mb-5">
|
||||||
|
|
@ -617,7 +634,14 @@ export default function FormAskExpert() {
|
||||||
}
|
}
|
||||||
className="mr-3"
|
className="mr-3"
|
||||||
/>
|
/>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<div className="font-bold">
|
||||||
{expert.fullname}
|
{expert.fullname}
|
||||||
|
</div>
|
||||||
|
<div className="italic">
|
||||||
|
({expert.username})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
@ -625,6 +649,46 @@ export default function FormAskExpert() {
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</div>
|
</div>
|
||||||
|
{checkedLevels.size > 0 && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Label className="text-sm text-gray-600 mb-2 block">
|
||||||
|
Tenaga Ahli Terpilih ({checkedLevels.size})
|
||||||
|
</Label>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{Array.from(checkedLevels).map((expertId) => {
|
||||||
|
const expert = listExpert?.find(
|
||||||
|
(exp: any) => exp.id === expertId
|
||||||
|
);
|
||||||
|
return expert ? (
|
||||||
|
<div
|
||||||
|
key={expert.id}
|
||||||
|
className="inline-flex items-center gap-2 bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1.5 rounded-full border border-blue-200"
|
||||||
|
>
|
||||||
|
<span>{expert.fullname}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleCheckboxChange(expert.id)}
|
||||||
|
className="ml-1 text-blue-600 hover:text-blue-800 hover:bg-blue-200 rounded-full p-0.5 transition-colors"
|
||||||
|
title="Remove expert"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-3 h-3"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
|
|
|
||||||
|
|
@ -636,7 +636,7 @@ export default function FormDoItYourself() {
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<div className="px-6 py-6">
|
<div className="px-6 py-6">
|
||||||
<p className="text-lg font-semibold mb-3">{t("form-task")}</p>
|
<p className="text-lg font-semibold mb-3">{t("form-task-ta-do")}</p>
|
||||||
{detail !== undefined ? (
|
{detail !== undefined ? (
|
||||||
<form onSubmit={handleSubmit(onSubmit)}>
|
<form onSubmit={handleSubmit(onSubmit)}>
|
||||||
<div className="gap-5 mb-5">
|
<div className="gap-5 mb-5">
|
||||||
|
|
|
||||||
|
|
@ -10,42 +10,23 @@ import * as z from "zod";
|
||||||
import Swal from "sweetalert2";
|
import Swal from "sweetalert2";
|
||||||
import withReactContent from "sweetalert2-react-content";
|
import withReactContent from "sweetalert2-react-content";
|
||||||
import { useParams, useRouter } from "next/navigation";
|
import { useParams, useRouter } from "next/navigation";
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
SelectContent,
|
|
||||||
SelectItem,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectValue,
|
|
||||||
} from "@/components/ui/select";
|
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
|
||||||
import JoditEditor from "jodit-react";
|
|
||||||
import {
|
import {
|
||||||
acceptAssignment,
|
acceptAssignmentTa,
|
||||||
createAssignmentResponse,
|
createAssignmentResponse,
|
||||||
createTask,
|
|
||||||
deleteAssignmentResponse,
|
deleteAssignmentResponse,
|
||||||
deleteTask,
|
deleteTask,
|
||||||
finishTask,
|
finishTaskTa,
|
||||||
getAcceptance,
|
getAcceptance,
|
||||||
getAcceptanceAssignmentStatus,
|
getAcceptanceAssignmentStatus,
|
||||||
getAssignmentResponseList,
|
getAssignmentResponseList,
|
||||||
getMediaUpload,
|
getMediaUpload,
|
||||||
getMediaUploadTa,
|
getMediaUploadTa,
|
||||||
getTask,
|
|
||||||
getTaskTa,
|
getTaskTa,
|
||||||
getUserLevelForAssignments,
|
getUserLevelForAssignments,
|
||||||
|
getUserLevelForExpert,
|
||||||
} from "@/service/task";
|
} from "@/service/task";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
|
||||||
DialogContent,
|
|
||||||
DialogHeader,
|
|
||||||
DialogTitle,
|
|
||||||
DialogTrigger,
|
|
||||||
} from "@/components/ui/dialog";
|
|
||||||
import {
|
|
||||||
ChevronDown,
|
|
||||||
ChevronUp,
|
|
||||||
Dock,
|
Dock,
|
||||||
DotSquare,
|
DotSquare,
|
||||||
ImageIcon,
|
ImageIcon,
|
||||||
|
|
@ -61,14 +42,20 @@ import { close, error, loading } from "@/lib/swal";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import { Avatar, AvatarImage } from "@/components/ui/avatar";
|
import { Avatar, AvatarImage } from "@/components/ui/avatar";
|
||||||
import { successCallback } from "@/config/swal";
|
import { successCallback } from "@/config/swal";
|
||||||
import FileUploader from "../shared/file-uploader";
|
|
||||||
import { AudioRecorder } from "react-audio-voice-recorder";
|
|
||||||
import Image from "next/image";
|
import Image from "next/image";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import WavesurferPlayer from "@wavesurfer/react";
|
import WavesurferPlayer from "@wavesurfer/react";
|
||||||
import WaveSurfer from "wavesurfer.js";
|
import WaveSurfer from "wavesurfer.js";
|
||||||
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
import { InputGroup, InputGroupText } from "@/components/ui/input-group";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { getListCompetencies } from "@/service/management-user/management-user";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
uniqueCode: z.string().min(1, { message: "Judul diperlukan" }),
|
uniqueCode: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -252,7 +239,11 @@ export default function FormTaskTaDetail() {
|
||||||
const [acceptAcceptance, setAcceptAcceptance] = useState<AcceptanceData[]>(
|
const [acceptAcceptance, setAcceptAcceptance] = useState<AcceptanceData[]>(
|
||||||
[]
|
[]
|
||||||
);
|
);
|
||||||
|
const [listExpert, setListExpert] = useState<any[]>([]);
|
||||||
|
const [userCompetencies, setUserCompetencies] = useState<any[]>([]);
|
||||||
|
const [selectedCompetencies, setSelectedCompetencies] = useState<Set<number>>(
|
||||||
|
new Set()
|
||||||
|
);
|
||||||
const [totalPage, setTotalPage] = React.useState(1);
|
const [totalPage, setTotalPage] = React.useState(1);
|
||||||
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
const [dataTable, setDataTable] = React.useState<any[]>([]);
|
||||||
const [totalData, setTotalData] = React.useState<number>(1);
|
const [totalData, setTotalData] = React.useState<number>(1);
|
||||||
|
|
@ -327,37 +318,37 @@ export default function FormTaskTaDetail() {
|
||||||
// setPlatformTypeVisible(selectedValue === 2);
|
// setPlatformTypeVisible(selectedValue === 2);
|
||||||
// };
|
// };
|
||||||
|
|
||||||
const handleExpertiseOutputChange = (
|
// const handleExpertiseOutputChange = (
|
||||||
key: keyof typeof expertise,
|
// key: keyof typeof expertise,
|
||||||
value: boolean
|
// value: boolean
|
||||||
) => {
|
// ) => {
|
||||||
if (key === "semua") {
|
// if (key === "semua") {
|
||||||
const newState = {
|
// const newState = {
|
||||||
semua: value,
|
// semua: value,
|
||||||
komunikasi: value,
|
// komunikasi: value,
|
||||||
hukum: value,
|
// hukum: value,
|
||||||
bahasa: value,
|
// bahasa: value,
|
||||||
ekonomi: value,
|
// ekonomi: value,
|
||||||
politik: value,
|
// politik: value,
|
||||||
sosiologi: value,
|
// sosiologi: value,
|
||||||
ilmuadministrasipemerintah: value,
|
// ilmuadministrasipemerintah: value,
|
||||||
ti: value,
|
// ti: value,
|
||||||
};
|
// };
|
||||||
setExpertiseOutput(newState);
|
// setExpertiseOutput(newState);
|
||||||
} else {
|
// } else {
|
||||||
const updated = {
|
// const updated = {
|
||||||
...expertise,
|
// ...expertise,
|
||||||
[key]: value,
|
// [key]: value,
|
||||||
};
|
// };
|
||||||
|
|
||||||
const allChecked = ["video", "audio", "image", "text"].every(
|
// const allChecked = ["video", "audio", "image", "text"].every(
|
||||||
(k) => updated[k as keyof typeof expertise]
|
// (k) => updated[k as keyof typeof expertise]
|
||||||
);
|
// );
|
||||||
|
|
||||||
updated.semua = allChecked;
|
// updated.semua = allChecked;
|
||||||
setExpertiseOutput(updated);
|
// setExpertiseOutput(updated);
|
||||||
}
|
// }
|
||||||
};
|
// };
|
||||||
|
|
||||||
const handleExpertOutputChange = (
|
const handleExpertOutputChange = (
|
||||||
key: keyof typeof expert,
|
key: keyof typeof expert,
|
||||||
|
|
@ -383,6 +374,68 @@ export default function FormTaskTaDetail() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getDataAdditional();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function getDataAdditional() {
|
||||||
|
const resCompetencies = await getListCompetencies();
|
||||||
|
console.log("competency", resCompetencies);
|
||||||
|
setUserCompetencies(resCompetencies?.data?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchListExpert() {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const response = await getUserLevelForExpert(id);
|
||||||
|
setListExpert(response?.data?.data);
|
||||||
|
console.log("tenaga ahli", response?.data?.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching Polda/Polres data:", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fetchListExpert();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchExpertsForCompetencies = async () => {
|
||||||
|
const allExperts: any[] = [];
|
||||||
|
|
||||||
|
for (const compId of Array.from(selectedCompetencies)) {
|
||||||
|
const response = await getUserLevelForExpert(compId);
|
||||||
|
const experts = response?.data?.data || [];
|
||||||
|
allExperts.push(...experts);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uniqueExperts = Array.from(
|
||||||
|
new Map(allExperts.map((e) => [e.id, e])).values()
|
||||||
|
);
|
||||||
|
|
||||||
|
setListExpert(uniqueExperts);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (selectedCompetencies.size > 0) {
|
||||||
|
fetchExpertsForCompetencies();
|
||||||
|
} else {
|
||||||
|
setListExpert([]);
|
||||||
|
}
|
||||||
|
}, [selectedCompetencies]);
|
||||||
|
|
||||||
|
const handleCompetencyChange = async (competencyId: number) => {
|
||||||
|
setSelectedCompetencies((prev) => {
|
||||||
|
const updated = new Set(prev);
|
||||||
|
if (updated.has(competencyId)) {
|
||||||
|
updated.delete(competencyId);
|
||||||
|
} else {
|
||||||
|
updated.add(competencyId);
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchPoldaPolres() {
|
async function fetchPoldaPolres() {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
@ -458,6 +511,16 @@ export default function FormTaskTaDetail() {
|
||||||
setCheckedLevels(levels);
|
setCheckedLevels(levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (details?.assignedToUsers) {
|
||||||
|
const userIds = details.assignedToUsers.split(",").map(Number);
|
||||||
|
setCheckedLevels(new Set(userIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (details?.expertCompetencies) {
|
||||||
|
const compIds = details.expertCompetencies.split(",").map(Number);
|
||||||
|
setSelectedCompetencies(new Set(compIds));
|
||||||
|
}
|
||||||
|
|
||||||
const attachment = details?.files;
|
const attachment = details?.files;
|
||||||
setImageUploadedFiles(
|
setImageUploadedFiles(
|
||||||
attachment?.filter((file: any) => file.fileTypeId == 1)
|
attachment?.filter((file: any) => file.fileTypeId == 1)
|
||||||
|
|
@ -542,7 +605,7 @@ export default function FormTaskTaDetail() {
|
||||||
confirmButtonText: "OK",
|
confirmButtonText: "OK",
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
router.push("/en/contributor/task");
|
router.push("/en/contributor/task-ta");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -682,7 +745,7 @@ export default function FormTaskTaDetail() {
|
||||||
const handleAcceptAcceptance = async () => {
|
const handleAcceptAcceptance = async () => {
|
||||||
loading();
|
loading();
|
||||||
console.log("Id user :", userId);
|
console.log("Id user :", userId);
|
||||||
const response = await acceptAssignment(id);
|
const response = await acceptAssignmentTa(id);
|
||||||
|
|
||||||
if (response?.error) {
|
if (response?.error) {
|
||||||
error(response?.message);
|
error(response?.message);
|
||||||
|
|
@ -773,7 +836,7 @@ export default function FormTaskTaDetail() {
|
||||||
);
|
);
|
||||||
|
|
||||||
async function finishAssignment() {
|
async function finishAssignment() {
|
||||||
const response = finishTask(id);
|
const response = finishTaskTa(id);
|
||||||
|
|
||||||
// if (response.error) {
|
// if (response.error) {
|
||||||
// error(response.message);
|
// error(response.message);
|
||||||
|
|
@ -1011,48 +1074,98 @@ export default function FormTaskTaDetail() {
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
<Label>{t("areas-expertise")}</Label>
|
<Label>{t("areas-expertise")}</Label>
|
||||||
<div className="flex flex-wrap gap-4">
|
<div className="flex flex-wrap gap-4">
|
||||||
{Object.keys(expertise).map((key) => (
|
{userCompetencies?.map((item: any) => (
|
||||||
<div className="flex items-center gap-2" key={key}>
|
<div className="flex items-center gap-2" key={item.id}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={key}
|
id={`comp-${item.id}`}
|
||||||
checked={expertise[key as keyof typeof expertise]}
|
checked={selectedCompetencies.has(item.id)}
|
||||||
onCheckedChange={(value) =>
|
onCheckedChange={() => handleCompetencyChange(item.id)}
|
||||||
handleExpertiseOutputChange(
|
|
||||||
key as keyof typeof expertise,
|
|
||||||
value as boolean
|
|
||||||
)
|
|
||||||
}
|
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
<Label htmlFor={key}>
|
<Label htmlFor={`comp-${item.id}`}>{item.name}</Label>
|
||||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
|
||||||
</Label>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
<Label>{t("choose-expert")}</Label>
|
{/* <Label>{t("choose-expert")}</Label>
|
||||||
<div className="flex flex-wrap gap-4">
|
<div className="flex flex-wrap gap-4">
|
||||||
{Object.keys(expert).map((key) => (
|
<Dialog>
|
||||||
<div className="flex items-center gap-2" key={key}>
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="soft" size="sm" color="primary">
|
||||||
|
[{"Pilih Tenaga Ahli"}]
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Daftar Tenaga Ahli</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
|
||||||
|
{listExpert?.map((expert: any) => (
|
||||||
|
<div key={expert.id} className="border p-2">
|
||||||
|
<Label className="flex items-center">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={key}
|
checked={checkedLevels.has(expert.id)}
|
||||||
checked={expert[key as keyof typeof expert]}
|
onCheckedChange={() =>
|
||||||
onCheckedChange={(value) =>
|
handleCheckboxChange(expert.id)
|
||||||
handleExpertOutputChange(
|
|
||||||
key as keyof typeof expert,
|
|
||||||
value as boolean
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
className="mr-3"
|
||||||
/>
|
/>
|
||||||
<Label htmlFor={key}>
|
<div className="flex flex-col gap-2">
|
||||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
<div className="font-bold">
|
||||||
|
{expert.fullname}
|
||||||
|
</div>
|
||||||
|
<div className="italic">
|
||||||
|
({expert.username})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div> */}
|
||||||
|
{checkedLevels.size > 0 && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Label className="text-sm text-gray-600 mb-2 block">
|
||||||
|
Tenaga Ahli Terpilih ({checkedLevels.size})
|
||||||
|
</Label>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{Array.from(checkedLevels).map((expertId) => {
|
||||||
|
const expert = listExpert?.find(
|
||||||
|
(exp: any) => exp.id === expertId
|
||||||
|
);
|
||||||
|
return expert ? (
|
||||||
|
<div
|
||||||
|
key={expert.id}
|
||||||
|
className="inline-flex items-center gap-2 bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1.5 rounded-full border border-blue-200"
|
||||||
|
>
|
||||||
|
<span>{expert.fullname}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleCheckboxChange(expert.id)}
|
||||||
|
className="ml-1 text-blue-600 hover:text-blue-800 hover:bg-blue-200 rounded-full p-0.5 transition-colors"
|
||||||
|
title="Remove expert"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-3 h-3"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div></div>
|
<div></div>
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ import {
|
||||||
getTask,
|
getTask,
|
||||||
getTaskTa,
|
getTaskTa,
|
||||||
getUserLevelForAssignments,
|
getUserLevelForAssignments,
|
||||||
|
getUserLevelForExpert,
|
||||||
} from "@/service/task";
|
} from "@/service/task";
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
|
|
@ -40,6 +41,7 @@ import {
|
||||||
Dock,
|
Dock,
|
||||||
ImageIcon,
|
ImageIcon,
|
||||||
Music,
|
Music,
|
||||||
|
Trash2,
|
||||||
VideoIcon,
|
VideoIcon,
|
||||||
} from "lucide-react";
|
} from "lucide-react";
|
||||||
import FileUploader from "../shared/file-uploader";
|
import FileUploader from "../shared/file-uploader";
|
||||||
|
|
@ -52,6 +54,7 @@ import { Upload } from "tus-js-client";
|
||||||
import { error, loading } from "@/lib/swal";
|
import { error, loading } from "@/lib/swal";
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from "next/dynamic";
|
||||||
import { useTranslations } from "next-intl";
|
import { useTranslations } from "next-intl";
|
||||||
|
import { getListCompetencies } from "@/service/management-user/management-user";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
// uniqueCode: z.string().min(1, { message: "Judul diperlukan" }),
|
// uniqueCode: z.string().min(1, { message: "Judul diperlukan" }),
|
||||||
|
|
@ -148,11 +151,18 @@ export default function FormTaskTaEdit() {
|
||||||
const [broadcastType, setBroadcastType] = useState<string>(""); // untuk Tipe Penugasan
|
const [broadcastType, setBroadcastType] = useState<string>(""); // untuk Tipe Penugasan
|
||||||
const [type, setType] = useState<string>("1");
|
const [type, setType] = useState<string>("1");
|
||||||
const [selectedTarget, setSelectedTarget] = useState("3,4");
|
const [selectedTarget, setSelectedTarget] = useState("3,4");
|
||||||
|
|
||||||
|
const [listExpert, setListExpert] = useState<any[]>([]);
|
||||||
|
const [userCompetencies, setUserCompetencies] = useState<any[]>([]);
|
||||||
|
const [selectedCompetencies, setSelectedCompetencies] = useState<Set<number>>(
|
||||||
|
new Set()
|
||||||
|
);
|
||||||
|
|
||||||
const [detail, setDetail] = useState<taskDetail>();
|
const [detail, setDetail] = useState<taskDetail>();
|
||||||
const [urlInputs, setUrlInputs] = useState<Url[]>([]);
|
const [urlInputs, setUrlInputs] = useState<Url[]>([]);
|
||||||
const [refresh] = useState(false);
|
const [refresh] = useState(false);
|
||||||
const [listDest, setListDest] = useState([]); // Data Polda dan Polres
|
const [listDest, setListDest] = useState([]); // Data Polda dan Polres
|
||||||
const [checkedLevels, setCheckedLevels] = useState(new Set());
|
const [checkedLevels, setCheckedLevels] = useState<Set<number>>(new Set());
|
||||||
const [expandedPolda, setExpandedPolda] = useState([{}]);
|
const [expandedPolda, setExpandedPolda] = useState([{}]);
|
||||||
const [isLoading, setIsLoading] = useState(false);
|
const [isLoading, setIsLoading] = useState(false);
|
||||||
const [audioFile, setAudioFile] = useState<File | null>(null);
|
const [audioFile, setAudioFile] = useState<File | null>(null);
|
||||||
|
|
@ -247,6 +257,68 @@ export default function FormTaskTaEdit() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getDataAdditional();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
async function getDataAdditional() {
|
||||||
|
const resCompetencies = await getListCompetencies();
|
||||||
|
console.log("competency", resCompetencies);
|
||||||
|
setUserCompetencies(resCompetencies?.data?.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
async function fetchListExpert() {
|
||||||
|
setIsLoading(true);
|
||||||
|
try {
|
||||||
|
const response = await getUserLevelForExpert(id);
|
||||||
|
setListExpert(response?.data?.data);
|
||||||
|
console.log("tenaga ahli", response?.data?.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching Polda/Polres data:", error);
|
||||||
|
} finally {
|
||||||
|
setIsLoading(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fetchListExpert();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchExpertsForCompetencies = async () => {
|
||||||
|
const allExperts: any[] = [];
|
||||||
|
|
||||||
|
for (const compId of Array.from(selectedCompetencies)) {
|
||||||
|
const response = await getUserLevelForExpert(compId);
|
||||||
|
const experts = response?.data?.data || [];
|
||||||
|
allExperts.push(...experts);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uniqueExperts = Array.from(
|
||||||
|
new Map(allExperts.map((e) => [e.id, e])).values()
|
||||||
|
);
|
||||||
|
|
||||||
|
setListExpert(uniqueExperts);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (selectedCompetencies.size > 0) {
|
||||||
|
fetchExpertsForCompetencies();
|
||||||
|
} else {
|
||||||
|
setListExpert([]);
|
||||||
|
}
|
||||||
|
}, [selectedCompetencies]);
|
||||||
|
|
||||||
|
const handleCompetencyChange = async (competencyId: number) => {
|
||||||
|
setSelectedCompetencies((prev) => {
|
||||||
|
const updated = new Set(prev);
|
||||||
|
if (updated.has(competencyId)) {
|
||||||
|
updated.delete(competencyId);
|
||||||
|
} else {
|
||||||
|
updated.add(competencyId);
|
||||||
|
}
|
||||||
|
return updated;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function fetchPoldaPolres() {
|
async function fetchPoldaPolres() {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
@ -285,12 +357,22 @@ export default function FormTaskTaEdit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (details?.assignedToLevel) {
|
if (details?.assignedToLevel) {
|
||||||
const levels = new Set(
|
const levels: Set<number> = new Set(
|
||||||
details.assignedToLevel.split(",").map(Number)
|
details.assignedToLevel.split(",").map((x: any) => Number(x))
|
||||||
);
|
);
|
||||||
setCheckedLevels(levels);
|
setCheckedLevels(levels);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (details?.assignedToUsers) {
|
||||||
|
const userIds = details.assignedToUsers.split(",").map(Number);
|
||||||
|
setCheckedLevels(new Set(userIds));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (details?.expertCompetencies) {
|
||||||
|
const compIds = details.expertCompetencies.split(",").map(Number);
|
||||||
|
setSelectedCompetencies(new Set(compIds));
|
||||||
|
}
|
||||||
|
|
||||||
const attachment = details?.files;
|
const attachment = details?.files;
|
||||||
setImageUploadedFiles(
|
setImageUploadedFiles(
|
||||||
attachment?.filter((file: any) => file.fileTypeId == 1)
|
attachment?.filter((file: any) => file.fileTypeId == 1)
|
||||||
|
|
@ -376,7 +458,7 @@ export default function FormTaskTaEdit() {
|
||||||
confirmButtonText: "OK",
|
confirmButtonText: "OK",
|
||||||
}).then((result) => {
|
}).then((result) => {
|
||||||
if (result.isConfirmed) {
|
if (result.isConfirmed) {
|
||||||
router.push("/en/contributor/task");
|
router.push("/en/contributor/task-ta");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
@ -393,9 +475,9 @@ export default function FormTaskTaEdit() {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePoldaPolresChange = () => {
|
// const handlePoldaPolresChange = () => {
|
||||||
return Array.from(checkedLevels).join(","); // Mengonversi Set ke string
|
// return Array.from(checkedLevels).join(","); // Mengonversi Set ke string
|
||||||
};
|
// };
|
||||||
|
|
||||||
const handleUnitChange = (
|
const handleUnitChange = (
|
||||||
key: keyof typeof unitSelection,
|
key: keyof typeof unitSelection,
|
||||||
|
|
@ -454,6 +536,10 @@ export default function FormTaskTaEdit() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleExpertChange = () => {
|
||||||
|
return Array.from(checkedLevels).join(",");
|
||||||
|
};
|
||||||
|
|
||||||
const save = async (data: TaskSchema) => {
|
const save = async (data: TaskSchema) => {
|
||||||
const fileTypeMapping = {
|
const fileTypeMapping = {
|
||||||
all: "1",
|
all: "1",
|
||||||
|
|
@ -483,16 +569,11 @@ export default function FormTaskTaEdit() {
|
||||||
const requestData: {
|
const requestData: {
|
||||||
id?: any;
|
id?: any;
|
||||||
title: string;
|
title: string;
|
||||||
assignedToLevel: any;
|
|
||||||
assignedToUsers: any;
|
assignedToUsers: any;
|
||||||
assignmentTypeId: string;
|
assignmentTypeId: string;
|
||||||
fileTypeOutput: string;
|
|
||||||
narration: string;
|
narration: string;
|
||||||
platformType: string | null;
|
|
||||||
assignmentMainTypeId: any;
|
|
||||||
assignmentType: string;
|
assignmentType: string;
|
||||||
assignedToRole: string;
|
assignedToRole: string;
|
||||||
broadcastType: string;
|
|
||||||
expertCompetencies: string;
|
expertCompetencies: string;
|
||||||
attachmentUrl: string[];
|
attachmentUrl: string[];
|
||||||
} = {
|
} = {
|
||||||
|
|
@ -500,17 +581,12 @@ export default function FormTaskTaEdit() {
|
||||||
// assignmentType,
|
// assignmentType,
|
||||||
// assignmentCategory,
|
// assignmentCategory,
|
||||||
id: detail?.id || null,
|
id: detail?.id || null,
|
||||||
assignedToLevel: handlePoldaPolresChange(),
|
assignedToUsers: handleExpertChange(),
|
||||||
assignedToUsers: assignmentPurposeString,
|
|
||||||
assignedToRole: selectedTarget,
|
assignedToRole: selectedTarget,
|
||||||
assignmentType: taskType,
|
assignmentType: taskType,
|
||||||
broadcastType: broadcastType,
|
|
||||||
assignmentMainTypeId: mainType,
|
|
||||||
assignmentTypeId: type,
|
assignmentTypeId: type,
|
||||||
fileTypeOutput: selectedOutputs,
|
|
||||||
narration: data.naration,
|
narration: data.naration,
|
||||||
platformType: "",
|
expertCompetencies: Array.from(selectedCompetencies).join(","),
|
||||||
expertCompetencies: "1,2,3",
|
|
||||||
title: data.title,
|
title: data.title,
|
||||||
attachmentUrl: links,
|
attachmentUrl: links,
|
||||||
};
|
};
|
||||||
|
|
@ -808,47 +884,97 @@ export default function FormTaskTaEdit() {
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
<Label>{t("areas-expertise")}</Label>
|
<Label>{t("areas-expertise")}</Label>
|
||||||
<div className="flex flex-wrap gap-4">
|
<div className="flex flex-wrap gap-4">
|
||||||
{Object.keys(expertise).map((key) => (
|
{userCompetencies?.map((item: any) => (
|
||||||
<div className="flex items-center gap-2" key={key}>
|
<div className="flex items-center gap-2" key={item.id}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={key}
|
id={`comp-${item.id}`}
|
||||||
checked={expertise[key as keyof typeof expertise]}
|
checked={selectedCompetencies.has(item.id)}
|
||||||
onCheckedChange={(value) =>
|
onCheckedChange={() => handleCompetencyChange(item.id)}
|
||||||
handleExpertiseOutputChange(
|
|
||||||
key as keyof typeof expertise,
|
|
||||||
value as boolean
|
|
||||||
)
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
<Label htmlFor={key}>
|
<Label htmlFor={`comp-${item.id}`}>{item.name}</Label>
|
||||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
|
||||||
</Label>
|
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
<Label>{t("choose-expert")}</Label>
|
<Label>{t("choose-expert")}</Label>
|
||||||
<div className="flex flex-wrap gap-4">
|
<div className="flex flex-wrap gap-4">
|
||||||
{Object.keys(expert).map((key) => (
|
<Dialog>
|
||||||
<div className="flex items-center gap-2" key={key}>
|
<DialogTrigger asChild>
|
||||||
|
<Button variant="soft" size="sm" color="primary">
|
||||||
|
[{"Pilih Tenaga Ahli"}]
|
||||||
|
</Button>
|
||||||
|
</DialogTrigger>
|
||||||
|
<DialogContent className="sm:max-w-[425px] md:max-w-[500px] lg:max-w-[1500px]">
|
||||||
|
<DialogHeader>
|
||||||
|
<DialogTitle>Daftar Tenaga Ahli</DialogTitle>
|
||||||
|
</DialogHeader>
|
||||||
|
<div className="grid grid-cols-2 gap-2 max-h-[400px] overflow-y-auto">
|
||||||
|
{listExpert?.map((expert: any) => (
|
||||||
|
<div key={expert.id} className="border p-2">
|
||||||
|
<Label className="flex items-center">
|
||||||
<Checkbox
|
<Checkbox
|
||||||
id={key}
|
checked={checkedLevels.has(expert.id)}
|
||||||
checked={expert[key as keyof typeof expert]}
|
onCheckedChange={() =>
|
||||||
onCheckedChange={(value) =>
|
handleCheckboxChange(expert.id)
|
||||||
handleExpertOutputChange(
|
|
||||||
key as keyof typeof expert,
|
|
||||||
value as boolean
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
className="mr-3"
|
||||||
/>
|
/>
|
||||||
<Label htmlFor={key}>
|
<div className="flex flex-col gap-2">
|
||||||
{key.charAt(0).toUpperCase() + key.slice(1)}
|
<div className="font-bold">
|
||||||
|
{expert.fullname}
|
||||||
|
</div>
|
||||||
|
<div className="italic">
|
||||||
|
({expert.username})
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</Label>
|
</Label>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
</DialogContent>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
{checkedLevels.size > 0 && (
|
||||||
|
<div className="mt-3">
|
||||||
|
<Label className="text-sm text-gray-600 mb-2 block">
|
||||||
|
Tenaga Ahli Terpilih ({checkedLevels.size})
|
||||||
|
</Label>
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
|
{Array.from(checkedLevels).map((expertId) => {
|
||||||
|
const expert = listExpert?.find(
|
||||||
|
(exp: any) => exp.id === expertId
|
||||||
|
);
|
||||||
|
return expert ? (
|
||||||
|
<div
|
||||||
|
key={expert.id}
|
||||||
|
className="inline-flex items-center gap-2 bg-blue-100 text-blue-800 text-sm font-medium px-3 py-1.5 rounded-full border border-blue-200"
|
||||||
|
>
|
||||||
|
<span>{expert.fullname}</span>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
onClick={() => handleCheckboxChange(expert.id)}
|
||||||
|
className="ml-1 text-blue-600 hover:text-blue-800 hover:bg-blue-200 rounded-full p-0.5 transition-colors"
|
||||||
|
title="Remove expert"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
className="w-3 h-3"
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="mt-5 space-y-2">
|
<div className="mt-5 space-y-2">
|
||||||
|
|
@ -1079,13 +1205,42 @@ export default function FormTaskTaEdit() {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
<div className="mt-4 space-y-2">
|
||||||
|
<Label className="">{t("news-links")}</Label>
|
||||||
|
{links.map((link, index) => (
|
||||||
|
<div
|
||||||
|
key={index}
|
||||||
|
className="flex items-center gap-2 mt-2"
|
||||||
|
>
|
||||||
|
<Input
|
||||||
|
type="url"
|
||||||
|
className="border rounded p-2 w-full"
|
||||||
|
placeholder={`Masukkan link berita ${index + 1}`}
|
||||||
|
value={link}
|
||||||
|
onChange={(e) =>
|
||||||
|
handleLinkChange(index, e.target.value)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{links.length > 1 && (
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="mt-4 bg-green-500 text-white px-4 py-2 rounded"
|
className="bg-red-500 text-white px-3 py-1 rounded"
|
||||||
onClick={handleAddLink}
|
onClick={() => handleRemoveRow(index)}
|
||||||
|
>
|
||||||
|
<Trash2 className="h-4 w-4" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
className="mt-2 bg-blue-500 text-white px-4 py-2 rounded"
|
||||||
|
onClick={handleAddRow}
|
||||||
|
size="sm"
|
||||||
>
|
>
|
||||||
{t("add-links")}
|
{t("add-links")}
|
||||||
</button>
|
</Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ const ContentCategory = (props: { group?: string; type: string }) => {
|
||||||
alt="category"
|
alt="category"
|
||||||
width={2560}
|
width={2560}
|
||||||
height={1440}
|
height={1440}
|
||||||
src={category?.smallThumbnailLink}
|
src={category?.thumbnailLink}
|
||||||
className="w-full lg:h-[300px] h-40 object-cover group-hover:scale-110 transition-transform duration-300"
|
className="w-full lg:h-[300px] h-40 object-cover group-hover:scale-110 transition-transform duration-300"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import Image from "next/image";
|
||||||
const regions = [
|
const regions = [
|
||||||
{ name: "ITWASUM POLRI", slug: "itwasum", logo: "/logo/satker/ITWASUM.png" },
|
{ name: "ITWASUM POLRI", slug: "itwasum", logo: "/logo/satker/ITWASUM.png" },
|
||||||
{
|
{
|
||||||
name: "BAINTELKAM POLRI",
|
name: "BAINTELKAM POLRI ",
|
||||||
slug: "baintelkam",
|
slug: "baintelkam",
|
||||||
logo: "/logo/satker/BAINTELKAM.png",
|
logo: "/logo/satker/BAINTELKAM.png",
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -71,22 +71,22 @@ export default function DashboardVisualization() {
|
||||||
setIsInternational(updatedIsInternational);
|
setIsInternational(updatedIsInternational);
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
async function fetchUrl() {
|
// async function fetchUrl() {
|
||||||
console.log("Fetch tableau");
|
// console.log("Fetch tableau");
|
||||||
const urlView = `${url + ticket1}/${view1}${param}`;
|
// const urlView = `${url + ticket1}/${view1}${param}`;
|
||||||
console.log("Fetch tableau ", urlView);
|
// console.log("Fetch tableau ", urlView);
|
||||||
const urlRender = await fetch(urlView)
|
// const urlRender = await fetch(urlView)
|
||||||
.then((response) => {
|
// .then((response) => {
|
||||||
console.log("Tableau res : ", response);
|
// console.log("Tableau res : ", response);
|
||||||
})
|
// })
|
||||||
.catch((error) => {
|
// .catch((error) => {
|
||||||
console.log("Tableau error: ", error);
|
// console.log("Tableau error: ", error);
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
|
|
||||||
fetchUrl();
|
// fetchUrl();
|
||||||
}, [ticket1]);
|
// }, [ticket1]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-2 bg-white rounded-lg p-3">
|
<div className="flex flex-col gap-2 bg-white rounded-lg p-3">
|
||||||
|
|
|
||||||
80
lib/menus.ts
80
lib/menus.ts
|
|
@ -3627,20 +3627,20 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
groupLabel: "",
|
// groupLabel: "",
|
||||||
id: "contest",
|
// id: "contest",
|
||||||
menus: [
|
// menus: [
|
||||||
{
|
// {
|
||||||
id: "contest",
|
// id: "contest",
|
||||||
href: "/shared/contest",
|
// href: "/shared/contest",
|
||||||
label: t("contest"),
|
// label: t("contest"),
|
||||||
active: pathname.includes("/contest"),
|
// active: pathname.includes("/contest"),
|
||||||
icon: "ic:outline-emoji-events",
|
// icon: "ic:outline-emoji-events",
|
||||||
submenus: [],
|
// submenus: [],
|
||||||
},
|
// },
|
||||||
],
|
// ],
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
groupLabel: "",
|
groupLabel: "",
|
||||||
id: "communication",
|
id: "communication",
|
||||||
|
|
@ -3896,16 +3896,16 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
icon: "material-symbols:map-search-outline",
|
icon: "material-symbols:map-search-outline",
|
||||||
submenus: [
|
submenus: [
|
||||||
{
|
{
|
||||||
href: "/admin/media-tracking/media-online",
|
href: "/admin/media-tracking/tracking-berita",
|
||||||
label: "Media Online",
|
label: "Tracking Beritra",
|
||||||
active: pathname === "/media-tracking/media-online",
|
active: pathname === "/admin/media-tracking/tracking-berita",
|
||||||
icon: "heroicons:arrow-trending-up",
|
icon: "heroicons:arrow-trending-up",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/admin/media-tracking/tb-news",
|
href: "/admin/media-tracking/results",
|
||||||
label: "Tracking Berita Hari Ini",
|
label: "Hasil",
|
||||||
active: pathname === "/media-tracking/news",
|
active: pathname === "/admin/media-tracking/results",
|
||||||
icon: "heroicons:arrow-trending-up",
|
icon: "heroicons:arrow-trending-up",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
|
|
@ -4079,20 +4079,20 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
// {
|
{
|
||||||
// groupLabel: "",
|
groupLabel: "",
|
||||||
// id: "performance-satker",
|
id: "performance-satker",
|
||||||
// menus: [
|
menus: [
|
||||||
// {
|
{
|
||||||
// id: "performance-polres",
|
id: "performance-polres",
|
||||||
// href: "/admin/performance-satker",
|
href: "/admin/performance-satker",
|
||||||
// label: t("performance-satker"),
|
label: t("performance-satker"),
|
||||||
// active: pathname.includes("/admin/performance-satker"),
|
active: pathname.includes("/admin/performance-satker"),
|
||||||
// icon: "ant-design:signal-filled",
|
icon: "ant-design:signal-filled",
|
||||||
// submenus: [],
|
submenus: [],
|
||||||
// },
|
},
|
||||||
// ],
|
],
|
||||||
// },
|
},
|
||||||
{
|
{
|
||||||
groupLabel: "",
|
groupLabel: "",
|
||||||
id: "media-tracking",
|
id: "media-tracking",
|
||||||
|
|
@ -4105,16 +4105,16 @@ export function getMenuList(pathname: string, t: any): Group[] {
|
||||||
icon: "material-symbols:map-search-outline",
|
icon: "material-symbols:map-search-outline",
|
||||||
submenus: [
|
submenus: [
|
||||||
{
|
{
|
||||||
href: "/admin/media-tracking/media-online",
|
href: "/admin/media-tracking/tracking-berita",
|
||||||
label: "Media Online",
|
label: "Tracking Beritra",
|
||||||
active: pathname === "/media-tracking/media-online",
|
active: pathname === "/admin/media-tracking/tracking-berita",
|
||||||
icon: "heroicons:arrow-trending-up",
|
icon: "heroicons:arrow-trending-up",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
href: "/admin/media-tracking/tb-news",
|
href: "/admin/media-tracking/results",
|
||||||
label: "Tracking Berita Hari Ini",
|
label: "Hasil",
|
||||||
active: pathname === "/media-tracking/news",
|
active: pathname === "/admin/media-tracking/results",
|
||||||
icon: "heroicons:arrow-trending-up",
|
icon: "heroicons:arrow-trending-up",
|
||||||
children: [],
|
children: [],
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -784,6 +784,8 @@
|
||||||
"assignment-type": "Assignment Type",
|
"assignment-type": "Assignment Type",
|
||||||
"description-task": "Description Task",
|
"description-task": "Description Task",
|
||||||
"form-task": "Form Task",
|
"form-task": "Form Task",
|
||||||
|
"form-task-ta": "Form Ask the Expert",
|
||||||
|
"form-task-ta-do": "Form Do it yourself",
|
||||||
"assignment-selection": "Assignment Recipient",
|
"assignment-selection": "Assignment Recipient",
|
||||||
"custom": "Costum",
|
"custom": "Costum",
|
||||||
"assigment-type": "Assigment Type",
|
"assigment-type": "Assigment Type",
|
||||||
|
|
|
||||||
|
|
@ -598,20 +598,6 @@
|
||||||
"survey8": "3. Seberapa puas Anda dengan informasi yang tersedia di MediaHub Polri?",
|
"survey8": "3. Seberapa puas Anda dengan informasi yang tersedia di MediaHub Polri?",
|
||||||
"survey9": "4. Apakah Anda merasa website ini membantu dalam mendapatkan informasi terkait Polri?",
|
"survey9": "4. Apakah Anda merasa website ini membantu dalam mendapatkan informasi terkait Polri?",
|
||||||
"survey10": "5. Apa saran atau masukan Anda?"
|
"survey10": "5. Apa saran atau masukan Anda?"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
"FilterPage": {
|
"FilterPage": {
|
||||||
"image": "Foto",
|
"image": "Foto",
|
||||||
|
|
@ -798,6 +784,8 @@
|
||||||
"assignment-type": "Jenis Penugasan",
|
"assignment-type": "Jenis Penugasan",
|
||||||
"description-task": "Narasi Penugasan",
|
"description-task": "Narasi Penugasan",
|
||||||
"form-task": "Form Penugasan",
|
"form-task": "Form Penugasan",
|
||||||
|
"form-task-ta": "Form Tanya Tenaga Ahli",
|
||||||
|
"form-task-ta-do": "Form Tenaga Ahli Kurasi",
|
||||||
"assignment-selection": "Penerima Tugas",
|
"assignment-selection": "Penerima Tugas",
|
||||||
"custom": "Kostum",
|
"custom": "Kostum",
|
||||||
"assigment-type": "Jenis Tugas",
|
"assigment-type": "Jenis Tugas",
|
||||||
|
|
|
||||||
|
|
@ -152,7 +152,7 @@ export async function getTagsBySubCategoryId(subCategory: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function listEnableCategory(type: any) {
|
export async function listEnableCategory(type: any) {
|
||||||
const url = `media/categories/list/enable?enablePage=0&sort=desc&sortBy=id&type=${type}`;
|
const url = `media/categories/list?enablePage=0&sort=desc&sortBy=id&type=${type}`;
|
||||||
return httpGetInterceptor(url);
|
return httpGetInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,11 @@ export async function saveUserInternal(data: any) {
|
||||||
return httpPostInterceptor(url, data);
|
return httpPostInterceptor(url, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function checkRolePlacementsAvailability(data: any) {
|
||||||
|
const url = "users/role-placements/availability";
|
||||||
|
return httpPostInterceptor(url, data);
|
||||||
|
}
|
||||||
|
|
||||||
export async function saveUserRolePlacements(data: any) {
|
export async function saveUserRolePlacements(data: any) {
|
||||||
const url = "users/role-placements";
|
const url = "users/role-placements";
|
||||||
return httpPostInterceptor(url, data);
|
return httpPostInterceptor(url, data);
|
||||||
|
|
|
||||||
|
|
@ -108,6 +108,11 @@ export async function acceptAssignment(id: any) {
|
||||||
return httpPostInterceptor(url, id);
|
return httpPostInterceptor(url, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function acceptAssignmentTa(id: any) {
|
||||||
|
const url = `assignment-expert/acceptance?id=${id}`;
|
||||||
|
return httpPostInterceptor(url, id);
|
||||||
|
}
|
||||||
|
|
||||||
export async function postFinishAcceptance(id: any) {
|
export async function postFinishAcceptance(id: any) {
|
||||||
const url = `assignment/finish-acceptance?id=${id}`;
|
const url = `assignment/finish-acceptance?id=${id}`;
|
||||||
return httpPostInterceptor(url, id);
|
return httpPostInterceptor(url, id);
|
||||||
|
|
@ -128,6 +133,11 @@ export async function finishTask(id: any) {
|
||||||
return httpPostInterceptor(url);
|
return httpPostInterceptor(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function finishTaskTa(id: any) {
|
||||||
|
const url = `assignment-expert/finish?id=${id}`;
|
||||||
|
return httpPostInterceptor(url);
|
||||||
|
}
|
||||||
|
|
||||||
export async function listTaskTa(
|
export async function listTaskTa(
|
||||||
page: any,
|
page: any,
|
||||||
title: string = "",
|
title: string = "",
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ const LoadScript = () => {
|
||||||
const script = document.createElement("script");
|
const script = document.createElement("script");
|
||||||
script.src = "https://cdn.userway.org/widget.js";
|
script.src = "https://cdn.userway.org/widget.js";
|
||||||
script.setAttribute("data-account", "X36s1DpjqB");
|
script.setAttribute("data-account", "X36s1DpjqB");
|
||||||
script.setAttribute("data-position", "3");
|
script.setAttribute("data-position", "5");
|
||||||
script.async = true;
|
script.async = true;
|
||||||
document.head.appendChild(script);
|
document.head.appendChild(script);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue