diff --git a/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx b/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx index 2f078cd3..5157cefb 100644 --- a/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx +++ b/app/[locale]/(protected)/contributor/agenda-setting/calender-view.tsx @@ -12,24 +12,60 @@ import { Calendar } from "@/components/ui/calendar"; import { Card, CardContent, CardHeader } from "@/components/ui/card"; import { Plus } from "lucide-react"; import { Checkbox } from "@/components/ui/checkbox"; -import { CalendarEvent, CalendarCategory } from "./data"; +import { CalendarCategory } from "./data"; import { EventContentArg } from "@fullcalendar/core"; import EventModal from "./event-modal"; import { useTranslations } from "next-intl"; +import { getAgendaSettingsList } from "@/service/agenda-setting/agenda-setting"; const wait = () => new Promise((resolve) => setTimeout(resolve, 1000)); interface CalendarViewProps { events: CalendarEvent[]; categories: CalendarCategory[]; } +export interface CalendarEvent { + id: string; + title: string; + start: Date; + end: Date; + allDay: boolean; + extendedProps: { + calendar: string; + description?: string; + }; +} + +export interface AgendaSettingsAPIResponse { + id: number; + title: string; + description: string; + agendaType: string; + startDate: string; // API mengembalikan tanggal dalam bentuk string + endDate: string; + isActive: boolean; + createdAt: string; + updatedAt: string; + createdById: number | null; + createdByName: string | null; +} + +interface APIResponse { + error: boolean; + message: any; + data: AgendaSettingsAPIResponse[] | null; // `data` bisa berupa array atau null +} + const CalendarView = ({ events, categories }: CalendarViewProps) => { const [selectedCategory, setSelectedCategory] = useState( null ); const [selectedEventDate, setSelectedEventDate] = useState(null); - const [selectedEvent, setSelectedEvent] = useState( - null - ); + // const [selectedEvent, setSelectedEvent] = useState( + // null + // ); + + const [apiEvents, setApiEvents] = useState([]); + const [loading, setLoading] = useState(false); const [draggableInitialized, setDraggableInitialized] = useState(false); const t = useTranslations("CalendarApp"); @@ -48,6 +84,73 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => { setSelectedCategory(categories?.map((c) => c.value)); }, [events, categories]); + useEffect(() => { + console.log("Fetched events from API:", apiEvents); + }, [apiEvents]); + + const filteredEvents = apiEvents?.filter((event) => + selectedCategory?.includes(event.extendedProps.calendar) + ); + + const displayedEvents = + filteredEvents?.length > 0 ? filteredEvents : apiEvents; + + useEffect(() => { + console.log("Filtered events based on category:", displayedEvents); + }, [filteredEvents, apiEvents]); + + useEffect(() => { + setSelectedCategory(categories?.map((c) => c.value)); + }, [categories]); + + useEffect(() => { + console.log("Selected categories:", selectedCategory); + }, [selectedCategory]); + + useEffect(() => { + const fetchAgendaEvents = async () => { + setLoading(true); + try { + const selectedMonth = new Date(); // Replace with your logic for selected month + const year = selectedMonth.getFullYear().toString(); + const month = (selectedMonth.getMonth() + 1).toString(); + const typeFilter = ""; // Replace with your type filter logic if needed + + const response: APIResponse = await getAgendaSettingsList( + year, + month, + typeFilter + ); + + if (response.data && Array.isArray(response.data)) { + // Transform API data to match CalendarEvent type + const eventsFromAPI: CalendarEvent[] = response.data.map((item) => ({ + id: item.id.toString(), + title: item.title, + start: new Date(item.startDate), + end: new Date(item.endDate), + allDay: true, // Sesuaikan jika memang ada event sepanjang hari + extendedProps: { + calendar: item.agendaType, + description: item.description, + }, + })); + setApiEvents(eventsFromAPI); + } else { + console.warn("No events found in API response."); + setApiEvents([]); + } + } catch (error) { + console.error("Failed to fetch agenda settings:", error); + setApiEvents([]); + } finally { + setLoading(false); + } + }; + + fetchAgendaEvents(); + }, []); + useEffect(() => { const draggableEl = document.getElementById("external-events"); @@ -80,23 +183,24 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => { draggableEl?.removeEventListener("mousedown", initDraggable); }; }, [dragEvents]); + // event click const handleEventClick = (arg: any) => { setSelectedEventDate(null); setSheetOpen(true); - setSelectedEvent(arg); + setApiEvents(arg); wait().then(() => (document.body.style.pointerEvents = "auto")); }; // handle close modal const handleCloseModal = () => { setSheetOpen(false); - setSelectedEvent(null); + setApiEvents([]); setSelectedEventDate(null); }; const handleDateClick = (arg: any) => { setSheetOpen(true); setSelectedEventDate(arg); - setSelectedEvent(null); + setApiEvents([]); wait().then(() => (document.body.style.pointerEvents = "auto")); }; @@ -109,7 +213,7 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => { }; const handleClassName = (arg: EventContentArg) => { - if (arg.event.extendedProps.calendar === "national") { + if (arg.event.extendedProps.calendar === "mabes") { return "primary"; } else if (arg.event.extendedProps.calendar === "polda") { return "success"; @@ -122,10 +226,6 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => { } }; - const filteredEvents = events?.filter((event) => - selectedCategory?.includes(event.extendedProps.calendar) - ); - return ( <>
@@ -205,7 +305,7 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => { center: "title", right: "dayGridMonth,timeGridWeek,timeGridDay,listWeek", }} - events={filteredEvents} + events={displayedEvents} // Use apiEvents here editable={true} rerenderDelay={10} eventDurationEditable={false} @@ -226,7 +326,7 @@ const CalendarView = ({ events, categories }: CalendarViewProps) => { open={sheetOpen} onClose={handleCloseModal} categories={categories} - event={selectedEvent} + event={apiEvents} selectedDate={selectedEventDate} /> diff --git a/app/[locale]/(protected)/contributor/blog/components/blog-table.tsx b/app/[locale]/(protected)/contributor/blog/components/blog-table.tsx index 4fb90c53..32c794d6 100644 --- a/app/[locale]/(protected)/contributor/blog/components/blog-table.tsx +++ b/app/[locale]/(protected)/contributor/blog/components/blog-table.tsx @@ -55,6 +55,7 @@ const BlogTable = () => { const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); const table = useReactTable({ data: dataTable, @@ -86,11 +87,11 @@ const BlogTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { - const res = await paginationBlog(limit, page - 1, ""); + const res = await paginationBlog(limit, page - 1, search); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -107,6 +108,11 @@ const BlogTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -119,6 +125,8 @@ const BlogTable = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/blog/create/page.tsx b/app/[locale]/(protected)/contributor/blog/create/page.tsx new file mode 100644 index 00000000..9c4ac75f --- /dev/null +++ b/app/[locale]/(protected)/contributor/blog/create/page.tsx @@ -0,0 +1,18 @@ +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormTask from "@/components/form/task/task-form"; +import FormImage from "@/components/form/content/image-form"; +import FormBlog from "@/components/form/blog/blog-form"; + +const BlogCreatePage = async () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default BlogCreatePage; diff --git a/app/[locale]/(protected)/contributor/blog/page.tsx b/app/[locale]/(protected)/contributor/blog/page.tsx index 53644f7c..6cfc19b4 100644 --- a/app/[locale]/(protected)/contributor/blog/page.tsx +++ b/app/[locale]/(protected)/contributor/blog/page.tsx @@ -3,6 +3,7 @@ import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"; import BlogTable from "./components/blog-table"; import { Plus } from "lucide-react"; import { Button } from "@/components/ui/button"; +import { Link } from "@/components/navigation"; const BlogPage = async () => { return ( @@ -17,10 +18,12 @@ const BlogPage = async () => { Table Indeks
- + + +
diff --git a/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx b/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx index 4c8ed54b..fdbfd63f 100644 --- a/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx +++ b/app/[locale]/(protected)/contributor/content/audio/components/table-audio.tsx @@ -121,7 +121,7 @@ const TableAudio = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { @@ -140,7 +140,7 @@ const TableAudio = () => { filterBySource, startDateString, endDateString, - "" + search ); const data = res.data?.data; const contentData = data?.content; @@ -157,6 +157,10 @@ const TableAudio = () => { console.error("Error fetching tasks:", error); } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; return (
@@ -170,6 +174,8 @@ const TableAudio = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx b/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx index 2e6e83ba..c0908cfd 100644 --- a/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx +++ b/app/[locale]/(protected)/contributor/content/image/components/table-image.tsx @@ -73,7 +73,7 @@ const TableImage = () => { const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); - const [search, setSearch] = React.useState(""); + const [search, setSearch] = React.useState(""); const userId = getCookiesDecrypt("uie"); const userLevelId = getCookiesDecrypt("ulie"); @@ -117,7 +117,7 @@ const TableImage = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { @@ -136,7 +136,7 @@ const TableImage = () => { filterBySource, startDateString, endDateString, - "" + search ); const data = res.data?.data; const contentData = data?.content; @@ -154,6 +154,11 @@ const TableImage = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -166,6 +171,8 @@ const TableImage = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/content/nulis-ai/components/table-nulis.tsx b/app/[locale]/(protected)/contributor/content/nulis-ai/components/table-nulis.tsx index 6ee706c9..864f65b7 100644 --- a/app/[locale]/(protected)/contributor/content/nulis-ai/components/table-nulis.tsx +++ b/app/[locale]/(protected)/contributor/content/nulis-ai/components/table-nulis.tsx @@ -121,12 +121,12 @@ const TableTeks = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { const isForSelf = Number(roleId) == 4; - const res = await listNulisAI(limit, page - 1, ""); + const res = await listNulisAI(limit, page - 1, search); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -143,6 +143,11 @@ const TableTeks = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -155,6 +160,8 @@ const TableTeks = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx b/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx index 15c8688a..79799154 100644 --- a/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx +++ b/app/[locale]/(protected)/contributor/content/teks/components/table-teks.tsx @@ -117,7 +117,7 @@ const TableTeks = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { @@ -136,7 +136,7 @@ const TableTeks = () => { filterBySource, startDateString, endDateString, - "" + search ); const data = res.data?.data; const contentData = data?.content; @@ -154,6 +154,11 @@ const TableTeks = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -166,6 +171,8 @@ const TableTeks = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx b/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx index 8f3cbd6a..d4b3c9bc 100644 --- a/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx +++ b/app/[locale]/(protected)/contributor/content/video/components/table-video.tsx @@ -117,7 +117,7 @@ const TableImage = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { @@ -136,7 +136,7 @@ const TableImage = () => { filterBySource, startDateString, endDateString, - "" + search ); const data = res.data?.data; const contentData = data?.content; @@ -154,6 +154,11 @@ const TableImage = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -166,6 +171,8 @@ const TableImage = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/planning/mediahub/components/columns.tsx b/app/[locale]/(protected)/contributor/planning/mediahub/components/columns.tsx index 4a9af83f..eb08dbd9 100644 --- a/app/[locale]/(protected)/contributor/planning/mediahub/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/planning/mediahub/components/columns.tsx @@ -11,6 +11,8 @@ import { } from "@/components/ui/dropdown-menu"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; +import { format } from "date-fns"; +import { Link } from "@/components/navigation"; const columns: ColumnDef[] = [ { @@ -42,9 +44,18 @@ const columns: ColumnDef[] = [ { accessorKey: "createdAt", header: "Tanggal Unggah ", - cell: ({ row }) => ( - {row.getValue("createdAt")} - ), + cell: ({ row }) => { + const createdAt = row.getValue("createdAt") as + | string + | number + | undefined; + + const formattedDate = + createdAt && !isNaN(new Date(createdAt).getTime()) + ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") + : "-"; + return {formattedDate}; + }, }, { accessorKey: "isActive", @@ -81,15 +92,18 @@ const columns: ColumnDef[] = [ - - - View - - - - Edit - - + + + + Publish + + + deletePlan(row.id)} + > Delete diff --git a/app/[locale]/(protected)/contributor/planning/mediahub/components/mediahub-table.tsx b/app/[locale]/(protected)/contributor/planning/mediahub/components/mediahub-table.tsx index be5eda96..352174fd 100644 --- a/app/[locale]/(protected)/contributor/planning/mediahub/components/mediahub-table.tsx +++ b/app/[locale]/(protected)/contributor/planning/mediahub/components/mediahub-table.tsx @@ -52,6 +52,7 @@ import { useRouter, useSearchParams } from "next/navigation"; import TablePagination from "@/components/table/table-pagination"; import columns from "./columns"; import { getPlanningSentPagination } from "@/service/planning/planning"; +import search from "@/app/[locale]/(protected)/app/chat/components/search"; const MediahubTable = () => { const router = useRouter(); @@ -73,6 +74,7 @@ const MediahubTable = () => { const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); const table = useReactTable({ data: dataTable, @@ -104,11 +106,11 @@ const MediahubTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { - const res = await getPlanningSentPagination(limit, page - 1, 1, ""); + const res = await getPlanningSentPagination(limit, page - 1, 1, search); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -125,6 +127,11 @@ const MediahubTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -137,6 +144,8 @@ const MediahubTable = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/planning/mediahub/publish/[id]/page.tsx b/app/[locale]/(protected)/contributor/planning/mediahub/publish/[id]/page.tsx new file mode 100644 index 00000000..9f25656d --- /dev/null +++ b/app/[locale]/(protected)/contributor/planning/mediahub/publish/[id]/page.tsx @@ -0,0 +1,17 @@ +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import FormTask from "@/components/form/task/task-form"; +import PublishMediahub from "@/components/form/planning/mediahub-publish"; + +const MediahubPublishPage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default MediahubPublishPage; diff --git a/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/columns.tsx b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/columns.tsx index 4a9af83f..f7820c16 100644 --- a/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/columns.tsx @@ -11,6 +11,8 @@ import { } from "@/components/ui/dropdown-menu"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; +import { format } from "date-fns"; +import { Link } from "@/components/navigation"; const columns: ColumnDef[] = [ { @@ -42,9 +44,18 @@ const columns: ColumnDef[] = [ { accessorKey: "createdAt", header: "Tanggal Unggah ", - cell: ({ row }) => ( - {row.getValue("createdAt")} - ), + cell: ({ row }) => { + const createdAt = row.getValue("createdAt") as + | string + | number + | undefined; + + const formattedDate = + createdAt && !isNaN(new Date(createdAt).getTime()) + ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") + : "-"; + return {formattedDate}; + }, }, { accessorKey: "isActive", @@ -81,14 +92,15 @@ const columns: ColumnDef[] = [ - - - View - - - - Edit - + + + + Publish + + + Delete diff --git a/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/medsos-table.tsx b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/medsos-table.tsx index 1507a7d4..fb4e1743 100644 --- a/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/medsos-table.tsx +++ b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/components/medsos-table.tsx @@ -73,6 +73,7 @@ const MedsosTable = () => { const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); const table = useReactTable({ data: dataTable, @@ -104,11 +105,11 @@ const MedsosTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { - const res = await getPlanningSentPagination(limit, page - 1, 2, ""); + const res = await getPlanningSentPagination(limit, page - 1, 2, search); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -125,6 +126,11 @@ const MedsosTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -137,6 +143,8 @@ const MedsosTable = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + onChange={handleSearch} + value={search} />
diff --git a/app/[locale]/(protected)/contributor/planning/medsos-mediahub/publish/[id]/page.tsx b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/publish/[id]/page.tsx new file mode 100644 index 00000000..7920fc4e --- /dev/null +++ b/app/[locale]/(protected)/contributor/planning/medsos-mediahub/publish/[id]/page.tsx @@ -0,0 +1,16 @@ +import { Card, CardContent } from "@/components/ui/card"; +import SiteBreadcrumb from "@/components/site-breadcrumb"; +import PublishMedsos from "@/components/form/planning/medsos-publish"; + +const MedsosPublishPage = () => { + return ( +
+ +
+ +
+
+ ); +}; + +export default MedsosPublishPage; diff --git a/app/[locale]/(protected)/contributor/schedule/event/components/event-table.tsx b/app/[locale]/(protected)/contributor/schedule/event/components/event-table.tsx index 6d1eddd6..4e58ef1a 100644 --- a/app/[locale]/(protected)/contributor/schedule/event/components/event-table.tsx +++ b/app/[locale]/(protected)/contributor/schedule/event/components/event-table.tsx @@ -50,6 +50,7 @@ const EventTable = () => { const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); const table = useReactTable({ data: dataTable, @@ -81,11 +82,11 @@ const EventTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { - const res = await paginationSchedule(limit, page - 1, 2, ""); + const res = await paginationSchedule(limit, page - 1, 2, search); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -102,6 +103,11 @@ const EventTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -114,6 +120,8 @@ const EventTable = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/schedule/press-conference/components/presscon-table.tsx b/app/[locale]/(protected)/contributor/schedule/press-conference/components/presscon-table.tsx index 9524979e..5fa152f1 100644 --- a/app/[locale]/(protected)/contributor/schedule/press-conference/components/presscon-table.tsx +++ b/app/[locale]/(protected)/contributor/schedule/press-conference/components/presscon-table.tsx @@ -63,6 +63,7 @@ const PressConferenceTable = () => { const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); const table = useReactTable({ data: dataTable, @@ -94,11 +95,11 @@ const PressConferenceTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { - const res = await paginationSchedule(limit, page - 1, 1, ""); + const res = await paginationSchedule(limit, page - 1, 1, search); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -115,6 +116,11 @@ const PressConferenceTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -127,6 +133,8 @@ const PressConferenceTable = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx b/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx index 3f962c8f..a66fb7ec 100644 --- a/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx +++ b/app/[locale]/(protected)/contributor/schedule/press-release/components/pressrilis-table.tsx @@ -64,6 +64,7 @@ const PressReleaseTable = () => { const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); const table = useReactTable({ data: dataTable, @@ -95,11 +96,11 @@ const PressReleaseTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { - const res = await paginationSchedule(limit, page - 1, 3, ""); + const res = await paginationSchedule(limit, page - 1, 3, search); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -116,9 +117,14 @@ const PressReleaseTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
-
+
@@ -128,6 +134,8 @@ const PressReleaseTable = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/contributor/task/components/columns.tsx b/app/[locale]/(protected)/contributor/task/components/columns.tsx index b998497f..3d7be186 100644 --- a/app/[locale]/(protected)/contributor/task/components/columns.tsx +++ b/app/[locale]/(protected)/contributor/task/components/columns.tsx @@ -12,6 +12,7 @@ import { import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { format } from "date-fns"; +import { Link } from "@/components/navigation"; const columns: ColumnDef[] = [ { @@ -111,10 +112,12 @@ const columns: ColumnDef[] = [ - - - View - + + + + View + + Edit diff --git a/app/[locale]/(protected)/contributor/task/components/task-table.tsx b/app/[locale]/(protected)/contributor/task/components/task-table.tsx index 1291014a..69636f6a 100644 --- a/app/[locale]/(protected)/contributor/task/components/task-table.tsx +++ b/app/[locale]/(protected)/contributor/task/components/task-table.tsx @@ -74,6 +74,7 @@ const TaskTable = () => { const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); const [isSpecificAttention, setIsSpecificAttention] = React.useState(true); + const [search, setSearch] = React.useState(""); const table = useReactTable({ data: dataTable, @@ -105,11 +106,16 @@ const TaskTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit, isSpecificAttention]); + }, [page, limit, isSpecificAttention, search]); async function fetchData() { try { - const res = await listTask("", page - 1, limit, isSpecificAttention ? "atensi-khusu" : "tugas-harian"); + const res = await listTask( + search, + page - 1, + limit, + isSpecificAttention ? "atensi-khusus" : "tugas-harian" + ); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -126,6 +132,11 @@ const TaskTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -133,7 +144,11 @@ const TaskTable = () => {
diff --git a/app/[locale]/(protected)/dashboard/page.tsx b/app/[locale]/(protected)/dashboard/page.tsx index 362f45a0..b44c2581 100644 --- a/app/[locale]/(protected)/dashboard/page.tsx +++ b/app/[locale]/(protected)/dashboard/page.tsx @@ -5,11 +5,12 @@ import { useTranslations } from "next-intl"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Button } from "@/components/ui/button"; import { UploadIcon } from "lucide-react"; -import RecentActivity from "./routine-task/recent-activity"; -import CompanyTable from "./routine-task/routine-task-table"; import TaskTable from "../contributor/task/components/task-table"; import PressConferenceTable from "../contributor/schedule/press-release/components/pressrilis-table"; import BlogTable from "../contributor/blog/components/blog-table"; +import ContentTable from "./routine-task/components/content-table"; +import RecentActivity from "./routine-task/components/recent-activity"; +import { Link } from "@/components/navigation"; const DashboardPage = () => { const t = useTranslations("AnalyticsDashboard"); @@ -94,7 +95,7 @@ const DashboardPage = () => { - +
@@ -110,14 +111,16 @@ const DashboardPage = () => { Table Penugasan
- + + +
- + @@ -128,7 +131,7 @@ const DashboardPage = () => {
- + @@ -145,14 +148,16 @@ const DashboardPage = () => { Table Indeks
- + + +
- + diff --git a/app/[locale]/(protected)/dashboard/routine-task/components/columns.tsx b/app/[locale]/(protected)/dashboard/routine-task/components/columns.tsx new file mode 100644 index 00000000..3e16b258 --- /dev/null +++ b/app/[locale]/(protected)/dashboard/routine-task/components/columns.tsx @@ -0,0 +1,174 @@ +import * as React from "react"; +import { ColumnDef } from "@tanstack/react-table"; + +import { Eye, MoreVertical, SquarePen, Trash2 } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuTrigger, + DropdownMenuItem, +} from "@/components/ui/dropdown-menu"; +import { Button } from "@/components/ui/button"; +import { format } from "date-fns"; + +const columns: ColumnDef[] = [ + { + accessorKey: "no", + header: "No", + cell: ({ row }) => ( +
+
+

+ {row.getValue("no")} +

+
+
+ ), + }, + { + accessorKey: "title", + header: "Title", + cell: ({ row }: { row: { getValue: (key: string) => string } }) => { + const title: string = row.getValue("title"); + return ( + + {title.length > 50 ? `${title.slice(0, 10)}...` : title} + + ); + }, + }, + { + accessorKey: "createdAt", + header: "Upload Date", + cell: ({ row }) => { + const createdAt = row.getValue("createdAt") as + | string + | number + | undefined; + + const formattedDate = + createdAt && !isNaN(new Date(createdAt).getTime()) + ? format(new Date(createdAt), "dd-MM-yyyy HH:mm:ss") + : "-"; + return {formattedDate}; + }, + }, + { + accessorKey: "fileTypeName", + header: "Type Content", + cell: ({ row }: { row: { getValue: (key: string) => string } }) => { + const title: string = row.getValue("fileTypeName"); + return ( + + {title.length > 50 ? `${title.slice(0, 30)}...` : title} + + ); + }, + }, + // { + // accessorKey: "creatorGroup", + // header: "Creator Group", + // cell: ({ row }) => ( + // {row.getValue("creatorGroup")} + // ), + // }, + // { + // accessorKey: "creatorName", + // header: "Sumber", + // cell: ({ row }) => ( + // {row.getValue("creatorName")} + // ), + // }, + // { + // accessorKey: "publishedOn", + // header: "Published", + // cell: ({ row }) => { + // const isPublish = row.original.isPublish; + // const isPublishOnPolda = row.original.isPublishOnPolda; + + // let displayText = "-"; + // if (isPublish && !isPublishOnPolda) { + // displayText = "Mabes"; + // } else if (isPublish && isPublishOnPolda) { + // displayText = "Mabes & Polda"; + // } else if (!isPublish && isPublishOnPolda) { + // displayText = "Polda"; + // } + + // return ( + //
+ // {displayText} + //
+ // ); + // }, + // }, + + { + accessorKey: "statusName", + header: "Status", + cell: ({ row }) => { + // Mendapatkan nilai statusName + const statusName = row.getValue("statusName"); + + // Mapping warna berdasarkan statusName + const colorMapping: Record = { + "Menunggu Review": "text-orange-500 border-orange-500", + Diterima: "text-green-500 border-green-500", + "Minta Update": "text-blue-500 border-blue-500", + Ditolak: "text-red-500 border-red-500", + }; + + // Mendapatkan kelas warna dari mapping, default ke abu-abu jika tidak ditemukan + const buttonClass = + colorMapping[statusName] || "text-gray-500 border-gray-500"; + + return ( +
+ +
+ ); + }, + }, + { + id: "actions", + accessorKey: "action", + header: "Actions", + enableHiding: false, + cell: ({ row }) => { + return ( + + + + + + + + + View + + + + + Delete + + + + ); + }, + }, +]; + +export default columns; diff --git a/app/[locale]/(protected)/dashboard/routine-task/components/content-table.tsx b/app/[locale]/(protected)/dashboard/routine-task/components/content-table.tsx new file mode 100644 index 00000000..a8d3b6de --- /dev/null +++ b/app/[locale]/(protected)/dashboard/routine-task/components/content-table.tsx @@ -0,0 +1,278 @@ +"use client"; +import * as React from "react"; +import { + ColumnDef, + ColumnFiltersState, + PaginationState, + SortingState, + VisibilityState, + flexRender, + getCoreRowModel, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + useReactTable, +} from "@tanstack/react-table"; +import { Button } from "@/components/ui/button"; +import { + Table, + TableBody, + TableCell, + TableHead, + TableHeader, + TableRow, +} from "@/components/ui/table"; +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; +import { + ChevronLeft, + ChevronRight, + Eye, + MoreVertical, + Search, + SquarePen, + Trash2, + TrendingDown, + TrendingUp, +} from "lucide-react"; +import { cn, getCookiesDecrypt } from "@/lib/utils"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Input } from "@/components/ui/input"; +import { InputGroup, InputGroupText } from "@/components/ui/input-group"; +import { paginationBlog } from "@/service/blog/blog"; +import { ticketingPagination } from "@/service/ticketing/ticketing"; +import { Badge } from "@/components/ui/badge"; +import { useRouter, useSearchParams } from "next/navigation"; +import TablePagination from "@/components/table/table-pagination"; +import columns from "./columns"; +import { listDataAll, listDataImage } from "@/service/content/content"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; + +type StatusFilter = string[]; + +const ContentTable = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const [dataTable, setDataTable] = React.useState([]); + const [totalData, setTotalData] = React.useState(1); + const [sorting, setSorting] = React.useState([]); + const [columnFilters, setColumnFilters] = React.useState( + [] + ); + const [columnVisibility, setColumnVisibility] = + React.useState({}); + const [rowSelection, setRowSelection] = React.useState({}); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: 10, + }); + const [page, setPage] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); + const [limit, setLimit] = React.useState(10); + const userId = getCookiesDecrypt("uie"); + const userLevelId = getCookiesDecrypt("ulie"); + + const [categories, setCategories] = React.useState(); + const [categoryFilter, setCategoryFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); + const [startDateString, setStartDateString] = React.useState(""); + const [endDateString, setEndDateString] = React.useState(""); + const [filterByCreator, setFilterByCreator] = React.useState(""); + const [fileTypeFilter, setFileTypeFilter] = React.useState([]); + const [filterBySource, setFilterBySource] = React.useState(""); + const [search, setSearch] = React.useState(""); + + const roleId = getCookiesDecrypt("urie"); + + const table = useReactTable({ + data: dataTable, + columns, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + getCoreRowModel: getCoreRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getSortedRowModel: getSortedRowModel(), + getFilteredRowModel: getFilteredRowModel(), + onColumnVisibilityChange: setColumnVisibility, + onRowSelectionChange: setRowSelection, + onPaginationChange: setPagination, + state: { + sorting, + columnFilters, + columnVisibility, + rowSelection, + pagination, + }, + }); + + React.useEffect(() => { + const pageFromUrl = searchParams?.get("page"); + if (pageFromUrl) { + setPage(Number(pageFromUrl)); + } + }, [searchParams]); + + React.useEffect(() => { + fetchData(); + }, [page, limit, fileTypeFilter, statusFilter, search]); + + async function fetchData() { + try { + const isForSelf = Number(roleId) === 4; + const res = await listDataAll( + isForSelf, + !isForSelf, + page - 1, + limit, + fileTypeFilter.sort().join(","), + categoryFilter.sort().join(","), + statusFilter.sort().join(","), + statusFilter.sort().join(",").includes("1") ? userLevelId : "", + filterByCreator, + filterBySource, + startDateString, + endDateString, + search + ); + const data = res.data?.data; + const contentData = data?.content; + contentData.forEach((item: any, index: number) => { + item.no = (page - 1) * limit + index + 1; + }); + + console.log("contentData : ", contentData); + + setDataTable(contentData); + setTotalData(data?.totalElements); + setTotalPage(data?.totalPages); + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + + return ( +
+
+
+ + + + + + +
+
+ {/* */} + +
+
+ + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + {header.isPlaceholder + ? null + : flexRender( + header.column.columnDef.header, + header.getContext() + )} + + ))} + + ))} + + + {table.getRowModel().rows?.length ? ( + table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + )) + ) : ( + + + No results. + + + )} + +
+ +
+ ); +}; + +export default ContentTable; diff --git a/app/[locale]/(protected)/dashboard/routine-task/data.ts b/app/[locale]/(protected)/dashboard/routine-task/components/data.ts similarity index 100% rename from app/[locale]/(protected)/dashboard/routine-task/data.ts rename to app/[locale]/(protected)/dashboard/routine-task/components/data.ts diff --git a/app/[locale]/(protected)/dashboard/routine-task/most-sales.tsx b/app/[locale]/(protected)/dashboard/routine-task/components/most-sales.tsx similarity index 100% rename from app/[locale]/(protected)/dashboard/routine-task/most-sales.tsx rename to app/[locale]/(protected)/dashboard/routine-task/components/most-sales.tsx diff --git a/app/[locale]/(protected)/dashboard/routine-task/overview-chart.tsx b/app/[locale]/(protected)/dashboard/routine-task/components/overview-chart.tsx similarity index 100% rename from app/[locale]/(protected)/dashboard/routine-task/overview-chart.tsx rename to app/[locale]/(protected)/dashboard/routine-task/components/overview-chart.tsx diff --git a/app/[locale]/(protected)/dashboard/routine-task/overview-radial.tsx b/app/[locale]/(protected)/dashboard/routine-task/components/overview-radial.tsx similarity index 100% rename from app/[locale]/(protected)/dashboard/routine-task/overview-radial.tsx rename to app/[locale]/(protected)/dashboard/routine-task/components/overview-radial.tsx diff --git a/app/[locale]/(protected)/dashboard/routine-task/components/recent-activity.tsx b/app/[locale]/(protected)/dashboard/routine-task/components/recent-activity.tsx new file mode 100644 index 00000000..3b01f6ca --- /dev/null +++ b/app/[locale]/(protected)/dashboard/routine-task/components/recent-activity.tsx @@ -0,0 +1,136 @@ +"use client"; + +import { getCookiesDecrypt } from "@/lib/utils"; +import { listDataAll } from "@/service/content/content"; +import { + ColumnFiltersState, + PaginationState, + SortingState, + VisibilityState, +} from "@tanstack/react-table"; +import { DockIcon, ImageIcon, MicIcon, YoutubeIcon } from "lucide-react"; +import { useRouter, useSearchParams } from "next/navigation"; +import React from "react"; +import search from "../../../app/chat/components/search"; + +type StatusFilter = string[]; + +interface Counts { + images: number; + audiovisual: number; + text: number; + audio: number; +} + +const RecentActivity: React.FC = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + + const [dataTable, setDataTable] = React.useState([]); + const [totalData, setTotalData] = React.useState(1); + const [sorting, setSorting] = React.useState([]); + const [columnFilters, setColumnFilters] = React.useState( + [] + ); + const [columnVisibility, setColumnVisibility] = + React.useState({}); + const [rowSelection, setRowSelection] = React.useState({}); + const [pagination, setPagination] = React.useState({ + pageIndex: 0, + pageSize: 10, + }); + const [page, setPage] = React.useState(1); + const [totalPage, setTotalPage] = React.useState(1); + const [limit, setLimit] = React.useState(10); + const [search, setSearch] = React.useState(""); + const userId = getCookiesDecrypt("uie"); + const userLevelId = getCookiesDecrypt("ulie"); + + const [categories, setCategories] = React.useState(); + const [categoryFilter, setCategoryFilter] = React.useState([]); + const [statusFilter, setStatusFilter] = React.useState([]); + const [startDateString, setStartDateString] = React.useState(""); + const [endDateString, setEndDateString] = React.useState(""); + const [filterByCreator, setFilterByCreator] = React.useState(""); + const [fileTypeFilter, setFileTypeFilter] = React.useState([]); + const [filterBySource, setFilterBySource] = React.useState(""); + + const [counts, setCounts] = React.useState({ + images: 0, + audiovisual: 0, + text: 0, + audio: 0, + }); + + const roleId = getCookiesDecrypt("urie"); + + React.useEffect(() => { + const pageFromUrl = searchParams?.get("page"); + if (pageFromUrl) { + setPage(Number(pageFromUrl)); + } + }, [searchParams]); + + React.useEffect(() => { + fetchData(); + }, [page, limit]); + + async function fetchData() { + try { + const isForSelf = Number(roleId) === 4; + const res = await listDataAll( + isForSelf, + !isForSelf, + page - 1, + limit, + search, + fileTypeFilter.sort().join(","), + categoryFilter.sort().join(","), + statusFilter.sort().join(","), + statusFilter.sort().join(",").includes("1") ? userLevelId : "", + filterByCreator, + filterBySource, + startDateString, + endDateString + ); + const data = res.data?.data; + const { content } = data || []; + + // Calculate counts for each typeId + const newCounts: Counts = { + images: content.filter((item: any) => item.typeId === 1).length, + audiovisual: content.filter((item: any) => item.typeId === 2).length, + text: content.filter((item: any) => item.typeId === 3).length, + audio: content.filter((item: any) => item.typeId === 4).length, + }; + + setDataTable(content); + setCounts(newCounts); + } catch (error) { + console.error("Error fetching tasks:", error); + } + } + + return ( +
+
+ +

{counts.images} FOTO

+
+
+ +

{counts.audiovisual} AUDIO VISUAL

+
+
+ +

{counts.text} TEXT

+
+
+ +

{counts.audio} AUDIO

+
+
+ ); +}; + +export default RecentActivity; diff --git a/app/[locale]/(protected)/dashboard/routine-task/recent-activity.tsx b/app/[locale]/(protected)/dashboard/routine-task/recent-activity.tsx deleted file mode 100644 index f684ed29..00000000 --- a/app/[locale]/(protected)/dashboard/routine-task/recent-activity.tsx +++ /dev/null @@ -1,36 +0,0 @@ -"use client"; - -import { - DockIcon, - ImageIcon, - MicIcon, - PaperclipIcon, - TextIcon, - VideoIcon, - YoutubeIcon, -} from "lucide-react"; - -const RecentActivity = () => { - return ( -
-
- -

0 FOTO

-
-
- -

0 AUDIO VISUAL

-
-
- -

0 TEXT

-
-
- -

0 AUDIO

-
-
- ); -}; - -export default RecentActivity; diff --git a/app/[locale]/(protected)/dashboard/routine-task/routine-task-table.tsx b/app/[locale]/(protected)/dashboard/routine-task/routine-task-table.tsx deleted file mode 100644 index 4d271bc0..00000000 --- a/app/[locale]/(protected)/dashboard/routine-task/routine-task-table.tsx +++ /dev/null @@ -1,272 +0,0 @@ -"use client"; - -import * as React from "react"; -import { - ColumnDef, - ColumnFiltersState, - PaginationState, - SortingState, - VisibilityState, - flexRender, - getCoreRowModel, - getFilteredRowModel, - getPaginationRowModel, - getSortedRowModel, - useReactTable, -} from "@tanstack/react-table"; -import { Button } from "@/components/ui/button"; -import { data } from "./data"; -import { - Table, - TableBody, - TableCell, - TableHead, - TableHeader, - TableRow, -} from "@/components/ui/table"; -import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; -import { - Badge, - ChevronLeft, - ChevronRight, - Eye, - MoreVertical, - SquarePen, - Trash2, - TrendingDown, - TrendingUp, -} from "lucide-react"; -import { cn } from "@/lib/utils"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; - -export type CompanyData = { - company: string; - category: string; - revenue: string; - sales: number; - status: string; - up: boolean; -}; - -export const columns: ColumnDef[] = [ - { - accessorKey: "company", - header: "Judul", - cell: ({ row }) => ( -
-
-
- - - SC - -
-
-
-

- Biffco Enterprises Ltd. -

-
- Biffco@example.com -
-
-
- ), - }, - { - accessorKey: "category", - header: "Tanggal Unggah", - cell: ({ row }) => ( - {row.getValue("category")} - ), - }, - { - accessorKey: "sales", - header: "Tipe Konten", - cell: ({ row }) => ( -
- {row.getValue("sales")} - {row?.original.up ? ( - - ) : ( - - )} -
- ), - }, - { - accessorKey: "status", - header: "Status", - cell: ({ row }) => { - const statusColors: Record = { - paid: "bg-success/20 text-success", - due: "bg-warning/20 text-warning", - canceled: "bg-destructive/20 text-destructive", - }; - const status = row.getValue("status"); - return ( - - {status} - - ); - }, - }, - { - id: "actions", - accessorKey: "action", - header: "Actions", - enableHiding: false, - cell: ({ row }) => { - return ( - - - - - - - - View - - - - Edit - - - - Delete - - - - ); - }, - }, -]; - -const CompanyTable = () => { - const [sorting, setSorting] = React.useState([]); - const [columnFilters, setColumnFilters] = React.useState( - [] - ); - const [columnVisibility, setColumnVisibility] = - React.useState({}); - const [rowSelection, setRowSelection] = React.useState({}); - const [pagination, setPagination] = React.useState({ - pageIndex: 0, - pageSize: 6, - }); - - const table = useReactTable({ - data, - columns, - onSortingChange: setSorting, - onColumnFiltersChange: setColumnFilters, - getCoreRowModel: getCoreRowModel(), - getPaginationRowModel: getPaginationRowModel(), - getSortedRowModel: getSortedRowModel(), - getFilteredRowModel: getFilteredRowModel(), - onColumnVisibilityChange: setColumnVisibility, - onRowSelectionChange: setRowSelection, - onPaginationChange: setPagination, - state: { - sorting, - columnFilters, - columnVisibility, - rowSelection, - pagination, - }, - }); - - return ( -
- - - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => ( - - {header.isPlaceholder - ? null - : flexRender( - header.column.columnDef.header, - header.getContext() - )} - - ))} - - ))} - - - {table.getRowModel().rows?.length ? ( - table.getRowModel().rows.map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - )) - ) : ( - - - No results. - - - )} - -
-
- - {table.getPageOptions().map((page, pageIndex) => ( - - ))} - -
-
- ); -}; - -export default CompanyTable; diff --git a/app/[locale]/(protected)/shared/communication/collaboration/components/collabroation-table.tsx b/app/[locale]/(protected)/shared/communication/collaboration/components/collabroation-table.tsx index a468a664..3f1dcc30 100644 --- a/app/[locale]/(protected)/shared/communication/collaboration/components/collabroation-table.tsx +++ b/app/[locale]/(protected)/shared/communication/collaboration/components/collabroation-table.tsx @@ -126,14 +126,14 @@ const EscalationTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { const res = await getTicketingCollaborationPagination( page - 1, limit, - "" + search ); const data = res.data?.data; const contentData = data?.content; @@ -149,10 +149,15 @@ const EscalationTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
-
+
@@ -161,6 +166,8 @@ const EscalationTable = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/shared/communication/escalation/table-escalation/escalation-table.tsx b/app/[locale]/(protected)/shared/communication/escalation/table-escalation/escalation-table.tsx index 362f7a88..acfc1496 100644 --- a/app/[locale]/(protected)/shared/communication/escalation/table-escalation/escalation-table.tsx +++ b/app/[locale]/(protected)/shared/communication/escalation/table-escalation/escalation-table.tsx @@ -125,11 +125,15 @@ const EscalationTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { - const res = await getTicketingEscalationPagination(page - 1, limit, ""); + const res = await getTicketingEscalationPagination( + page - 1, + limit, + search + ); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -144,10 +148,15 @@ const EscalationTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
-
+
@@ -156,6 +165,8 @@ const EscalationTable = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/shared/communication/internal/components/internal-table.tsx b/app/[locale]/(protected)/shared/communication/internal/components/internal-table.tsx index 3c031a6a..5ef7dad3 100644 --- a/app/[locale]/(protected)/shared/communication/internal/components/internal-table.tsx +++ b/app/[locale]/(protected)/shared/communication/internal/components/internal-table.tsx @@ -122,11 +122,11 @@ const TableAudio = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { - const res = await listTicketingInternal(page - 1, limit, ""); + const res = await listTicketingInternal(page - 1, limit, search); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -143,10 +143,15 @@ const TableAudio = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); // Perbarui state search + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return ( -
+
-
+
@@ -155,6 +160,8 @@ const TableAudio = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/shared/contest/components/contest-table.tsx b/app/[locale]/(protected)/shared/contest/components/contest-table.tsx index 47e4da65..f04e94c0 100644 --- a/app/[locale]/(protected)/shared/contest/components/contest-table.tsx +++ b/app/[locale]/(protected)/shared/contest/components/contest-table.tsx @@ -36,22 +36,11 @@ import { TrendingDown, TrendingUp, } from "lucide-react"; -import { cn } from "@/lib/utils"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; import { Input } from "@/components/ui/input"; import { InputGroup, InputGroupText } from "@/components/ui/input-group"; -import { paginationBlog } from "@/service/blog/blog"; -import { ticketingPagination } from "@/service/ticketing/ticketing"; -import { Badge } from "@/components/ui/badge"; import { useRouter, useSearchParams } from "next/navigation"; import TablePagination from "@/components/table/table-pagination"; import columns from "./columns"; -import { listTask } from "@/service/task"; import { listContest } from "@/service/contest/contest"; const TaskTable = () => { @@ -74,7 +63,7 @@ const TaskTable = () => { const [page, setPage] = React.useState(1); const [totalPage, setTotalPage] = React.useState(1); const [limit, setLimit] = React.useState(10); - const [activeTab, setActiveTab] = React.useState("atensi-khusus"); + const [search, setSearch] = React.useState(""); const table = useReactTable({ data: dataTable, @@ -106,11 +95,11 @@ const TaskTable = () => { React.useEffect(() => { fetchData(); - }, [page, limit]); + }, [page, limit, search]); async function fetchData() { try { - const res = await listContest(limit, page - 1, ""); + const res = await listContest(search, limit, page - 1); const data = res.data?.data; const contentData = data?.content; contentData.forEach((item: any, index: number) => { @@ -127,6 +116,11 @@ const TaskTable = () => { } } + const handleSearch = (e: React.ChangeEvent) => { + setSearch(e.target.value); + table.getColumn("judul")?.setFilterValue(e.target.value); // Set filter tabel + }; + return (
@@ -139,6 +133,8 @@ const TaskTable = () => { type="text" placeholder="Search Judul..." className="bg-transparent dark:border-secondary dark:placeholder-white/80 dark:focus:border-secondary dark:text-white" + value={search} + onChange={handleSearch} />
diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio-visual.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio-visual.tsx deleted file mode 100644 index b6936baa..00000000 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio-visual.tsx +++ /dev/null @@ -1,78 +0,0 @@ -"use client"; -import { Link } from "@/components/navigation"; -import { - Carousel, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel"; -import { getListContent } from "@/service/landing/landing"; -import { formatDateToIndonesian, generateLocalizedPath } from "@/utils/globals"; -import { Icon } from "@iconify/react/dist/iconify.js"; -import { useParams, usePathname, useRouter } from "next/navigation"; -import React, { Component, useEffect, useState } from "react"; - -const VideoSliderPage = () => { - const [newContent, setNewContent] = useState(); - const [selectedTab, setSelectedTab] = useState("video"); - const router = useRouter(); - const pathname = usePathname(); - const params = useParams(); - const locale = params?.locale; - const type = "popular"; - useEffect(() => { - initFetch(); - }); - const initFetch = async () => { - const request = { - sortBy: type == "popular" ? "clickCount" : "createdAt", - contentTypeId: "2", - }; - const response = await getListContent(request); - console.log("category", response); - setNewContent(response?.data?.data?.content); - }; - return ( -
- - - {newContent?.map((video: any) => ( - - - -
-

- {video?.title} -

-

- {formatDateToIndonesian(new Date(video?.createdAt))}{" "} - {video?.timezone ? video?.timezone : "WIB"} |{" "} - {" "} - {video.clickCount}{" "} -

-
- -
- ))} -
- - -
-
- ); -}; - -export default VideoSliderPage; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio.tsx deleted file mode 100644 index a95e3750..00000000 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio.tsx +++ /dev/null @@ -1,89 +0,0 @@ -"use client"; -import { Link } from "@/components/navigation"; -import { - Carousel, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel"; -import { getListContent } from "@/service/landing/landing"; -import { - formatDateToIndonesian, - generateLocalizedPath, - textEllipsis, -} from "@/utils/globals"; -import { Icon } from "@iconify/react/dist/iconify.js"; -import { useParams, usePathname, useRouter } from "next/navigation"; -import React, { Component, useEffect, useState } from "react"; - -const AudioSliderPage = () => { - const [newContent, setNewContent] = useState(); - const [selectedTab, setSelectedTab] = useState("video"); - const router = useRouter(); - const pathname = usePathname(); - const params = useParams(); - const locale = params?.locale; - const type = "popular"; - useEffect(() => { - initFetch(); - }); - const initFetch = async () => { - const request = { - sortBy: type == "popular" ? "clickCount" : "createdAt", - contentTypeId: "4", - }; - const response = await getListContent(request); - console.log("category", response); - setNewContent(response?.data?.data?.content); - }; - return ( - - ); -}; - -export default AudioSliderPage; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx new file mode 100644 index 00000000..e18d163c --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/audio.tsx @@ -0,0 +1,128 @@ +"use client"; +import { Link } from "@/components/navigation"; +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from "@/components/ui/carousel"; +import { getListContent } from "@/service/landing/landing"; +import { + formatDateToIndonesian, + generateLocalizedPath, + textEllipsis, +} from "@/utils/globals"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import { useParams, usePathname, useRouter } from "next/navigation"; +import React, { Component, useEffect, useState } from "react"; + +const AudioSliderPage = () => { + const [audioData, setAudioData] = useState(); + const [displayAudio, setDisplayAudio] = useState([]); + const [page, setPage] = useState(1); + + useEffect(() => { + initFetch(); + }, []); + + useEffect(() => { + if (audioData?.length > 0) { + shuffleAndSetVideos(); + const interval = setInterval(shuffleAndSetVideos, 5000); + return () => clearInterval(interval); // Cleanup interval on unmount + } + }, [audioData]); + + const initFetch = async () => { + const response = await getListContent({ + page: page - 1, + size: 12, + sortBy: "createdAt", + contentTypeId: "4", + }); + console.log(response); + setAudioData(response?.data?.data?.content); + }; + + const shuffleAndSetVideos = () => { + const shuffled = shuffleArray([...audioData]); + setDisplayAudio(shuffled.slice(0, 3)); + }; + + const shuffleArray = (array: any[]) => { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; + }; + + return ( +
+
+ {displayAudio?.map((audio: any) => ( + +
+ + + +
+ +
+
+ {formatDateToIndonesian(new Date(audio?.createdAt))}{" "} + {audio?.timezone ? audio?.timezone : "WIB"} |{" "} + 518 +
+
+ {audio?.title} +
+
+
+
+ +
+
+ # +
+ {audio?.duration} +
+ + + +
+
+ + ))} +
+
+ ); +}; + +export default AudioSliderPage; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx new file mode 100644 index 00000000..5e41f378 --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/audio/detail/[id]/page.tsx @@ -0,0 +1,549 @@ +"use client"; +import React, { ChangeEvent, useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card, CardContent } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import Cookies from "js-cookie"; +import { postBlog } from "@/service/blog/blog"; +import { Textarea } from "@/components/ui/textarea"; +import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; +import { detailMedia } from "@/service/curated-content/curated-content"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/free-mode"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; +import "swiper/css/thumbs"; +import "swiper/css"; +import "swiper/css/navigation"; +import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; +import { Avatar, AvatarImage } from "@/components/ui/avatar"; + +const detailSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + categoryName: z.string().min(1, { message: "Judul diperlukan" }), + meta: z.string().min(1, { message: "Judul diperlukan" }), + description: z + .string() + .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +type Category = { + id: string; + categoryName: string; +}; + +export type curationDetail = { + id: number; + title: string; + categoryName: string; + description: string; + uploadedBy: { + id: number; + fullname: string; + username: string | null; + email: string; + isActive: boolean; + isDefault: boolean; + isInternational: boolean; + userLevel: { + id: number; + name: string; + aliasName: string; + userGroupId: number; + }; + }; + tags: string; + provinceId: string; + is_active: string; +}; + +const initialComments = [ + { + id: 1, + username: "Esther Howard", + date: "07-04-2023 20:00 WIB", + text: "Tolong untuk narasinya mengikuti 5W + 1H!", + avatar: "/images/avatar/avatar-3.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 2, + username: "Brooklyn Simmons", + date: "07-04-2023 20:00 WIB", + text: "Ok Baik, Saya segera melakukan perbaikan. Terima kasih atas masukannya. 🙏", + avatar: "/images/avatar/avatar-5.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 3, + username: "Leslie Alexander", + date: "07-04-2023 20:00 WIB", + text: "Sangat berguna. Terima Kasih!", + avatar: "/images/avatar/avatar-7.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, +]; + +export default function DetailAudio() { + const MySwal = withReactContent(Swal); + const { id } = useParams() as { id: string }; + console.log(id); + const editor = useRef(null); + type DetailSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + const [selectedTarget, setSelectedTarget] = useState(""); + // const [detail, setDetail] = useState({ + // title: null, + // tags: null, + // files: [], + // fileType: null, + // }); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [detailThumb, setDetailThumb] = useState([]); + const [thumbsSwiper, setThumbsSwiper] = useState(null); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(detailSchema), + }); + + const [commentsData, setCommentsData] = useState(initialComments); + const [replyText, setReplyText] = useState(""); + const [replyingTo, setReplyingTo] = useState(null); + + const handleReply = (commentId: number) => { + setReplyingTo(commentId); + }; + + const addReply = (commentId: number) => { + if (replyText.trim()) { + const newCommentData = commentsData.map((comment: any) => { + if (comment.id === commentId) { + return { + ...comment, + replies: [ + ...comment.replies, + { + text: replyText, + username: "You", + date: new Date().toLocaleString(), + }, + ], + }; + } + return comment; + }); + + setCommentsData(newCommentData); + setReplyText(""); + setReplyingTo(null); + } + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await detailMedia(id); + const details = response.data?.data; + + setDetail(details); + const filesData = details.files || []; + const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) => + file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" + ); + setDetailThumb(fileUrls); + } + } + initState(); + }, [id, refresh]); + + return ( +
+ {detail !== undefined ? ( + +
+

Kurasi Detail

+ +
+
+
+
+ + ( + + )} + /> + {errors.title?.message && ( +

+ {errors.title.message} +

+ )} +
+
+
+ + ( + + )} + /> +
+
+
+
+ + ( + +
+
+ + + +
+
+ +
+ + {commentsData.map((comment) => ( +
+ + + +
+ + {comment.username} + + + {comment.date} + +

{comment.text}

+
handleReply(comment.id)} + > + + Balas +
+ {comment.replies.length > 0 && ( +
+ {comment.replies.map((reply: any, index: any) => ( +
+ + + +
+ + {reply.username} + + + {reply.date} + +

+ {reply.text} +

+
+
+ ))} +
+ )} +
+
+ ))} + {replyingTo !== null && ( +
+ + +
+ )} +
+
+ +
+ + ) : ( + "" + )} +
+ ); +} diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx new file mode 100644 index 00000000..afa89b2b --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/detail/[id]/page.tsx @@ -0,0 +1,518 @@ +"use client"; +import React, { ChangeEvent, useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card, CardContent } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import Cookies from "js-cookie"; +import { postBlog } from "@/service/blog/blog"; +import { Textarea } from "@/components/ui/textarea"; +import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; +import { detailMedia } from "@/service/curated-content/curated-content"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/free-mode"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; +import "swiper/css/thumbs"; +import "swiper/css"; +import "swiper/css/navigation"; +import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; +import { Avatar, AvatarImage } from "@/components/ui/avatar"; +import JoditEditor from "jodit-react"; + +const detailSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + categoryName: z.string().min(1, { message: "Judul diperlukan" }), + meta: z.string().min(1, { message: "Judul diperlukan" }), + description: z + .string() + .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +type Category = { + id: string; + categoryName: string; +}; + +export type curationDetail = { + id: number; + title: string; + categoryName: string; + description: string; + uploadedBy: { + id: number; + fullname: string; + username: string | null; + email: string; + isActive: boolean; + isDefault: boolean; + isInternational: boolean; + userLevel: { + id: number; + name: string; + aliasName: string; + userGroupId: number; + }; + }; + tags: string; + provinceId: string; + is_active: string; +}; + +const initialComments = [ + { + id: 1, + username: "Esther Howard", + date: "07-04-2023 20:00 WIB", + text: "Tolong untuk narasinya mengikuti 5W + 1H!", + avatar: "/images/avatar/avatar-3.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 2, + username: "Brooklyn Simmons", + date: "07-04-2023 20:00 WIB", + text: "Ok Baik, Saya segera melakukan perbaikan. Terima kasih atas masukannya. 🙏", + avatar: "/images/avatar/avatar-5.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 3, + username: "Leslie Alexander", + date: "07-04-2023 20:00 WIB", + text: "Sangat berguna. Terima Kasih!", + avatar: "/images/avatar/avatar-7.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, +]; + +export default function DetailDocument() { + const MySwal = withReactContent(Swal); + const { id } = useParams() as { id: string }; + console.log(id); + const editor = useRef(null); + type DetailSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + const [selectedTarget, setSelectedTarget] = useState(""); + // const [detail, setDetail] = useState({ + // title: null, + // tags: null, + // files: [], + // fileType: null, + // }); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [detailThumb, setDetailThumb] = useState([]); + const [thumbsSwiper, setThumbsSwiper] = useState(null); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(detailSchema), + }); + + const [commentsData, setCommentsData] = useState(initialComments); + const [replyText, setReplyText] = useState(""); + const [replyingTo, setReplyingTo] = useState(null); + + const handleReply = (commentId: number) => { + setReplyingTo(commentId); + }; + + const addReply = (commentId: number) => { + if (replyText.trim()) { + const newCommentData = commentsData.map((comment: any) => { + if (comment.id === commentId) { + return { + ...comment, + replies: [ + ...comment.replies, + { + text: replyText, + username: "You", + date: new Date().toLocaleString(), + }, + ], + }; + } + return comment; + }); + + setCommentsData(newCommentData); + setReplyText(""); + setReplyingTo(null); + } + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await detailMedia(id); + const details = response.data?.data; + + setDetail(details); + const filesData = details.files || []; + const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) => + file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" + ); + setDetailThumb(fileUrls); + } + } + initState(); + }, [id, refresh]); + + return ( +
+ {detail !== undefined ? ( + +
+

Kurasi Detail

+ +
+
+
+
+ + ( + + )} + /> + {errors.title?.message && ( +

+ {errors.title.message} +

+ )} +
+
+
+ + ( + + )} + /> +
+
+
+
+ + ( + +
+
+ + + +
+
+ +
+ + {commentsData.map((comment) => ( +
+ + + +
+ + {comment.username} + + + {comment.date} + +

{comment.text}

+
handleReply(comment.id)} + > + + Balas +
+ {comment.replies.length > 0 && ( +
+ {comment.replies.map((reply: any, index: any) => ( +
+ + + +
+ + {reply.username} + + + {reply.date} + +

+ {reply.text} +

+
+
+ ))} +
+ )} +
+
+ ))} + {replyingTo !== null && ( +
+ + +
+ )} +
+
+ +
+ + ) : ( + "" + )} +
+ ); +} diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx new file mode 100644 index 00000000..20e89711 --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/document/teks.tsx @@ -0,0 +1,115 @@ +"use client"; +import { Link } from "@/components/navigation"; +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from "@/components/ui/carousel"; +import { getListContent } from "@/service/landing/landing"; +import { + formatDateToIndonesian, + generateLocalizedPath, + textEllipsis, +} from "@/utils/globals"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import { useParams, usePathname, useRouter } from "next/navigation"; +import React, { Component, useEffect, useState } from "react"; + +const TeksSliderPage = () => { + const [documentData, setDocumentData] = useState(); + const [displayDocument, setDisplayDocument] = useState([]); + const [page, setPage] = useState(1); + + useEffect(() => { + initFetch(); + }, []); + + useEffect(() => { + if (documentData?.length > 0) { + shuffleAndSetVideos(); + const interval = setInterval(shuffleAndSetVideos, 5000); + return () => clearInterval(interval); // Cleanup interval on unmount + } + }, [documentData]); + + const initFetch = async () => { + const response = await getListContent({ + page: page - 1, + size: 12, + sortBy: "createdAt", + contentTypeId: "3", + }); + console.log(response); + setDocumentData(response?.data?.data?.content); + }; + const shuffleAndSetVideos = () => { + const shuffled = shuffleArray([...documentData]); + setDisplayDocument(shuffled.slice(0, 2)); + }; + + const shuffleArray = (array: any[]) => { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; + }; + + return ( +
+
+ {displayDocument?.map((document: any) => ( + +
+ + + +
+ +
+
+ {formatDateToIndonesian(new Date(document?.createdAt))}{" "} + {document?.timezone ? document?.timezone : "WIB"} |{" "} + 518 +
+
+ {document?.title} +
+
+ + + + Download Dokumen +
+
+ + ))} +
+
+ ); +}; + +export default TeksSliderPage; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/image.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/image.tsx deleted file mode 100644 index 54e823fd..00000000 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/image.tsx +++ /dev/null @@ -1,79 +0,0 @@ -"use client"; -import { Link } from "@/components/navigation"; -import { - Carousel, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel"; -import { getListContent } from "@/service/landing/landing"; -import { - formatDateToIndonesian, - generateLocalizedPath, - textEllipsis, -} from "@/utils/globals"; -import { Icon } from "@iconify/react/dist/iconify.js"; -import { useParams, usePathname, useRouter } from "next/navigation"; -import React, { Component, useEffect, useState } from "react"; - -const ImageSliderPage = () => { - const [newContent, setNewContent] = useState(); - const [selectedTab, setSelectedTab] = useState("video"); - const router = useRouter(); - const pathname = usePathname(); - const params = useParams(); - const locale = params?.locale; - const type = "popular"; - useEffect(() => { - initFetch(); - }); - const initFetch = async () => { - const request = { - sortBy: type == "popular" ? "clickCount" : "createdAt", - contentTypeId: "3", - }; - const response = await getListContent(request); - console.log("category", response); - setNewContent(response?.data?.data?.content); - }; - return ( -
- - - {newContent?.map((image: any) => ( - - - -
-

- {image?.title} -

-

- {formatDateToIndonesian(new Date(image?.createdAt))}{" "} - {image?.timezone ? image?.timezone : "WIB"}|{" "} - {" "} - {image?.clickCount}{" "} -

-
- -
- ))} -
- - -
-
- ); -}; - -export default ImageSliderPage; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx new file mode 100644 index 00000000..05ad3fff --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/image/detail/[id]/page.tsx @@ -0,0 +1,543 @@ +"use client"; +import React, { ChangeEvent, useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card, CardContent } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import Cookies from "js-cookie"; +import { postBlog } from "@/service/blog/blog"; +import { Textarea } from "@/components/ui/textarea"; +import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; +import { detailMedia } from "@/service/curated-content/curated-content"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/free-mode"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; +import "swiper/css/thumbs"; +import "swiper/css"; +import "swiper/css/navigation"; +import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; +import { Avatar, AvatarImage } from "@/components/ui/avatar"; + +const detailSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + categoryName: z.string().min(1, { message: "Judul diperlukan" }), + meta: z.string().min(1, { message: "Judul diperlukan" }), + description: z + .string() + .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +type Category = { + id: string; + categoryName: string; +}; + +export type curationDetail = { + id: number; + title: string; + categoryName: string; + description: string; + uploadedBy: { + id: number; + fullname: string; + username: string | null; + email: string; + isActive: boolean; + isDefault: boolean; + isInternational: boolean; + userLevel: { + id: number; + name: string; + aliasName: string; + userGroupId: number; + }; + }; + tags: string; + provinceId: string; + is_active: string; +}; + +const initialComments = [ + { + id: 1, + username: "Esther Howard", + date: "07-04-2023 20:00 WIB", + text: "Tolong untuk narasinya mengikuti 5W + 1H!", + avatar: "/images/avatar/avatar-3.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 2, + username: "Brooklyn Simmons", + date: "07-04-2023 20:00 WIB", + text: "Ok Baik, Saya segera melakukan perbaikan. Terima kasih atas masukannya. 🙏", + avatar: "/images/avatar/avatar-5.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 3, + username: "Leslie Alexander", + date: "07-04-2023 20:00 WIB", + text: "Sangat berguna. Terima Kasih!", + avatar: "/images/avatar/avatar-7.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, +]; + +export default function DetailImage() { + const MySwal = withReactContent(Swal); + const { id } = useParams() as { id: string }; + console.log(id); + const editor = useRef(null); + type DetailSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + const [selectedTarget, setSelectedTarget] = useState(""); + // const [detail, setDetail] = useState({ + // title: null, + // tags: null, + // files: [], + // fileType: null, + // }); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [detailThumb, setDetailThumb] = useState([]); + const [thumbsSwiper, setThumbsSwiper] = useState(null); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(detailSchema), + }); + + const [commentsData, setCommentsData] = useState(initialComments); + const [replyText, setReplyText] = useState(""); + const [replyingTo, setReplyingTo] = useState(null); + + const handleReply = (commentId: number) => { + setReplyingTo(commentId); + }; + + const addReply = (commentId: number) => { + if (replyText.trim()) { + const newCommentData = commentsData.map((comment: any) => { + if (comment.id === commentId) { + return { + ...comment, + replies: [ + ...comment.replies, + { + text: replyText, + username: "You", + date: new Date().toLocaleString(), + }, + ], + }; + } + return comment; + }); + + setCommentsData(newCommentData); + setReplyText(""); + setReplyingTo(null); + } + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await detailMedia(id); + const details = response.data?.data; + + setDetail(details); + const filesData = details.files || []; + const fileUrls = filesData.map((file: { thumbnailFileUrl: string }) => + file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" + ); + setDetailThumb(fileUrls); + } + } + initState(); + }, [id, refresh]); + + return ( +
+ {detail !== undefined ? ( + +
+

Kurasi Detail

+ +
+
+
+
+ + ( + + )} + /> + {errors.title?.message && ( +

+ {errors.title.message} +

+ )} +
+
+
+ + ( + + )} + /> +
+
+
+
+ + ( + +
+
+ + + +
+
+ +
+ + {commentsData.map((comment) => ( +
+ + + +
+ + {comment.username} + + + {comment.date} + +

{comment.text}

+
handleReply(comment.id)} + > + + Balas +
+ {comment.replies.length > 0 && ( +
+ {comment.replies.map((reply: any, index: any) => ( +
+ + + +
+ + {reply.username} + + + {reply.date} + +

+ {reply.text} +

+
+
+ ))} +
+ )} +
+
+ ))} + {replyingTo !== null && ( +
+ + +
+ )} +
+
+ +
+ + ) : ( + "" + )} +
+ ); +} diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/image/image.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/image/image.tsx new file mode 100644 index 00000000..f4f3162e --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/image/image.tsx @@ -0,0 +1,122 @@ +"use client"; +import { Link } from "@/components/navigation"; +import { Card, CardContent } from "@/components/ui/card"; +import { + Carousel, + CarouselContent, + CarouselItem, + CarouselNext, + CarouselPrevious, +} from "@/components/ui/carousel"; +import { getListContent } from "@/service/landing/landing"; +import { + formatDateToIndonesian, + generateLocalizedPath, + textEllipsis, +} from "@/utils/globals"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import { + SortingState, + ColumnFiltersState, + VisibilityState, + PaginationState, +} from "@tanstack/react-table"; +import { + useParams, + usePathname, + useRouter, + useSearchParams, +} from "next/navigation"; +import React, { Component, useEffect, useState } from "react"; + +const ImageSliderPage = () => { + const router = useRouter(); + const searchParams = useSearchParams(); + const [imageData, setImageData] = useState(); + const [displayImage, setDisplayImage] = useState([]); + const [page, setPage] = useState(1); + + useEffect(() => { + fetchData(); + }, [page]); + + useEffect(() => { + if (imageData?.length > 0) { + shuffleAndSetVideos(); + const interval = setInterval(shuffleAndSetVideos, 5000); + return () => clearInterval(interval); // Cleanup interval on unmount + } + }, [imageData]); + + const fetchData = async () => { + const response = await getListContent({ + page: page - 1, + size: 6, + sortBy: "createdAt", + contentTypeId: "1", + }); + console.log(response); + + const data = response.data?.data; + const contentData = data?.content; + setImageData(contentData); + }; + + const shuffleAndSetVideos = () => { + const shuffled = shuffleArray([...imageData]); + setDisplayImage(shuffled.slice(0, 3)); + }; + + const shuffleArray = (array: any[]) => { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; + }; + return ( +
+
+ {displayImage?.map((image: any) => ( + + + + +
+ {formatDateToIndonesian(new Date(image?.createdAt))}{" "} + {image?.timezone ? image?.timezone : "WIB"}|{" "} + + {image?.clickCount}{" "} + + + {" "} +
+
+ {image?.title} +
+
+ +
+ ))} +
+
+ ); +}; + +export default ImageSliderPage; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/teks.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/teks.tsx deleted file mode 100644 index 3eda793a..00000000 --- a/app/[locale]/(protected)/shared/curated-content/giat-routine/teks.tsx +++ /dev/null @@ -1,103 +0,0 @@ -"use client"; -import { Link } from "@/components/navigation"; -import { - Carousel, - CarouselContent, - CarouselItem, - CarouselNext, - CarouselPrevious, -} from "@/components/ui/carousel"; -import { getListContent } from "@/service/landing/landing"; -import { - formatDateToIndonesian, - generateLocalizedPath, - textEllipsis, -} from "@/utils/globals"; -import { Icon } from "@iconify/react/dist/iconify.js"; -import { useParams, usePathname, useRouter } from "next/navigation"; -import React, { Component, useEffect, useState } from "react"; - -const TeksSliderPage = () => { - const [newContent, setNewContent] = useState(); - const [selectedTab, setSelectedTab] = useState("video"); - const router = useRouter(); - const pathname = usePathname(); - const params = useParams(); - const locale = params?.locale; - const type = "popular"; - useEffect(() => { - initFetch(); - }); - const initFetch = async () => { - const request = { - sortBy: type == "popular" ? "clickCount" : "createdAt", - contentTypeId: "1", - }; - const response = await getListContent(request); - console.log("category", response); - setNewContent(response?.data?.data?.content); - }; - return ( - - ); -}; - -export default TeksSliderPage; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/video/audio-visual.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/video/audio-visual.tsx new file mode 100644 index 00000000..523f860e --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/video/audio-visual.tsx @@ -0,0 +1,95 @@ +"use client"; +import { Link } from "@/components/navigation"; +import { Card, CardContent } from "@/components/ui/card"; +import { getListContent } from "@/service/landing/landing"; +import { formatDateToIndonesian } from "@/utils/globals"; +import { Icon } from "@iconify/react/dist/iconify.js"; +import image from "next/image"; +import React, { useEffect, useState } from "react"; + +const VideoSliderPage = () => { + const [allVideoData, setAllVideoData] = useState([]); + const [displayVideos, setDisplayVideos] = useState([]); + const [page, setPage] = useState(1); + + useEffect(() => { + initFetch(); + }, []); + + useEffect(() => { + if (allVideoData?.length > 0) { + shuffleAndSetVideos(); + const interval = setInterval(shuffleAndSetVideos, 5000); + return () => clearInterval(interval); // Cleanup interval on unmount + } + }, [allVideoData]); + + const initFetch = async () => { + const response = await getListContent({ + page: page - 1, + size: 12, + sortBy: "createdAt", + contentTypeId: "2", + }); + setAllVideoData(response?.data?.data?.content || []); + }; + + const shuffleAndSetVideos = () => { + const shuffled = shuffleArray([...allVideoData]); + setDisplayVideos(shuffled.slice(0, 3)); + }; + + const shuffleArray = (array: any[]) => { + for (let i = array.length - 1; i > 0; i--) { + const j = Math.floor(Math.random() * (i + 1)); + [array[i], array[j]] = [array[j], array[i]]; + } + return array; + }; + + return ( +
+
+ {displayVideos.map((video: any) => ( + + + + +
+ {formatDateToIndonesian(new Date(video?.createdAt))}{" "} + {video?.timezone || "WIB"} | + + {video?.clickCount} + + + +
+
+ {video?.title} +
+
+ +
+ ))} +
+
+ ); +}; + +export default VideoSliderPage; diff --git a/app/[locale]/(protected)/shared/curated-content/giat-routine/video/detail/[id]/page.tsx b/app/[locale]/(protected)/shared/curated-content/giat-routine/video/detail/[id]/page.tsx new file mode 100644 index 00000000..ce86d7b7 --- /dev/null +++ b/app/[locale]/(protected)/shared/curated-content/giat-routine/video/detail/[id]/page.tsx @@ -0,0 +1,551 @@ +"use client"; +import React, { ChangeEvent, useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card, CardContent } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import Cookies from "js-cookie"; +import { postBlog } from "@/service/blog/blog"; +import { Textarea } from "@/components/ui/textarea"; +import { DotSquare, InboxIcon, PaperclipIcon, SmileIcon } from "lucide-react"; +import { detailMedia } from "@/service/curated-content/curated-content"; +import { Swiper, SwiperSlide } from "swiper/react"; +import "swiper/css"; +import "swiper/css/free-mode"; +import "swiper/css/navigation"; +import "swiper/css/pagination"; +import "swiper/css/thumbs"; +import "swiper/css"; +import "swiper/css/navigation"; +import { FreeMode, Navigation, Pagination, Thumbs } from "swiper/modules"; +import { Avatar, AvatarImage } from "@/components/ui/avatar"; + +const detailSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + categoryName: z.string().min(1, { message: "Judul diperlukan" }), + meta: z.string().min(1, { message: "Judul diperlukan" }), + description: z + .string() + .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +type Category = { + id: string; + categoryName: string; +}; + +export type curationDetail = { + id: number; + title: string; + categoryName: string; + description: string; + uploadedBy: { + id: number; + fullname: string; + username: string | null; + email: string; + isActive: boolean; + isDefault: boolean; + isInternational: boolean; + userLevel: { + id: number; + name: string; + aliasName: string; + userGroupId: number; + }; + }; + tags: string; + provinceId: string; + is_active: string; +}; + +const initialComments = [ + { + id: 1, + username: "Esther Howard", + date: "07-04-2023 20:00 WIB", + text: "Tolong untuk narasinya mengikuti 5W + 1H!", + avatar: "/images/avatar/avatar-3.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 2, + username: "Brooklyn Simmons", + date: "07-04-2023 20:00 WIB", + text: "Ok Baik, Saya segera melakukan perbaikan. Terima kasih atas masukannya. 🙏", + avatar: "/images/avatar/avatar-5.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, + { + id: 3, + username: "Leslie Alexander", + date: "07-04-2023 20:00 WIB", + text: "Sangat berguna. Terima Kasih!", + avatar: "/images/avatar/avatar-7.png", // URL avatar atau path gambar pengguna + replies: [], // Komentar balasan + }, +]; + +export default function DetailImage() { + const MySwal = withReactContent(Swal); + const { id } = useParams() as { id: string }; + console.log(id); + const editor = useRef(null); + type DetailSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + const [selectedTarget, setSelectedTarget] = useState(""); + // const [detail, setDetail] = useState({ + // title: null, + // tags: null, + // files: [], + // fileType: null, + // }); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + const [detailVideo, setDetailVideo] = useState([]); + const [detailThumb, setDetailThumb] = useState([]); + const [thumbsSwiper, setThumbsSwiper] = useState(null); + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(detailSchema), + }); + + const [commentsData, setCommentsData] = useState(initialComments); + const [replyText, setReplyText] = useState(""); + const [replyingTo, setReplyingTo] = useState(null); + + const handleReply = (commentId: number) => { + setReplyingTo(commentId); + }; + + const addReply = (commentId: number) => { + if (replyText.trim()) { + const newCommentData = commentsData.map((comment: any) => { + if (comment.id === commentId) { + return { + ...comment, + replies: [ + ...comment.replies, + { + text: replyText, + username: "You", + date: new Date().toLocaleString(), + }, + ], + }; + } + return comment; + }); + + setCommentsData(newCommentData); + setReplyText(""); + setReplyingTo(null); + } + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await detailMedia(id); + const details = response.data?.data; + + setDetail(details); + const filesData = details.files || []; + const fileUrls = filesData.map((file: { url: string }) => + file.url ? file.url : "default-image.jpg" + ); + setDetailVideo(fileUrls); + const filesDataThumbnail = details.files || []; + const fileUrlsThumbnail = filesDataThumbnail.map( + (file: { thumbnailFileUrl: string }) => + file.thumbnailFileUrl ? file.thumbnailFileUrl : "default-image.jpg" + ); + setDetailThumb(fileUrlsThumbnail); + } + } + initState(); + }, [id, refresh]); + + return ( +
+ {detail !== undefined ? ( + +
+

Kurasi Detail

+ +
+
+
+
+ + ( + + )} + /> + {errors.title?.message && ( +

+ {errors.title.message} +

+ )} +
+
+
+ + ( + + )} + /> +
+
+
+
+ + ( + +
+
+ + + +
+
+ +
+ + {commentsData.map((comment) => ( +
+ + + +
+ + {comment.username} + + + {comment.date} + +

{comment.text}

+
handleReply(comment.id)} + > + + Balas +
+ {comment.replies.length > 0 && ( +
+ {comment.replies.map((reply: any, index: any) => ( +
+ + + +
+ + {reply.username} + + + {reply.date} + +

+ {reply.text} +

+
+
+ ))} +
+ )} +
+
+ ))} + {replyingTo !== null && ( +
+ + +
+ )} +
+
+ +
+ + ) : ( + "" + )} +
+ ); +} diff --git a/app/[locale]/(protected)/shared/curated-content/page.tsx b/app/[locale]/(protected)/shared/curated-content/page.tsx index 5509506b..fceac0cd 100644 --- a/app/[locale]/(protected)/shared/curated-content/page.tsx +++ b/app/[locale]/(protected)/shared/curated-content/page.tsx @@ -19,11 +19,11 @@ import newContent from "@/components/landing-page/new-content"; import { locale } from "dayjs"; import { useEffect, useState } from "react"; import { getListContent } from "@/service/landing/landing"; -import GiatRoutine from "./giat-routine/audio-visual"; -import VideoSliderPage from "./giat-routine/audio-visual"; -import AudioSliderPage from "./giat-routine/audio"; -import ImageSliderPage from "./giat-routine/image"; -import TeksSliderPage from "./giat-routine/teks"; +import GiatRoutine from "./giat-routine/video/audio-visual"; +import VideoSliderPage from "./giat-routine/video/audio-visual"; +import AudioSliderPage from "./giat-routine/audio/audio"; +import ImageSliderPage from "./giat-routine/image/image"; +import TeksSliderPage from "./giat-routine/document/teks"; import ContestTable from "../contest/components/contest-table"; const CuratedContentPage = () => { diff --git a/components/form/blog/blog-form.tsx b/components/form/blog/blog-form.tsx new file mode 100644 index 00000000..a35c7a7f --- /dev/null +++ b/components/form/blog/blog-form.tsx @@ -0,0 +1,422 @@ +"use client"; +import React, { ChangeEvent, useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Checkbox } from "@/components/ui/checkbox"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import JoditEditor from "jodit-react"; +import { register } from "module"; +import { Switch } from "@/components/ui/switch"; +import Cookies from "js-cookie"; +import { createTask } from "@/config/api"; +import { + createMedia, + getTagsBySubCategoryId, + listEnableCategory, +} from "@/service/content/content"; +import { postBlog } from "@/service/blog/blog"; + +const taskSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + slug: z.string().min(1, { message: "Judul diperlukan" }), + meta: z.string().min(1, { message: "Judul diperlukan" }), + description: z + .string() + .min(2, { message: "Narasi Penugasan harus lebih dari 2 karakter." }), + // tags: z.string().min(1, { message: "Judul diperlukan" }), +}); + +type Category = { + id: string; + name: string; +}; + +const initialCategories: Category[] = [ + { + id: "1", + name: "Giat Polri", + }, + { + id: "2", + name: "Giat Pimpinan", + }, + { + id: "3", + name: "Liputan Kegiatan", + }, + { + id: "4", + name: "Seputar Prestasi", + }, +]; + +export default function FormBlog() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type TaskSchema = z.infer; + + const [selectedFiles, setSelectedFiles] = useState([]); + const taskId = Cookies.get("taskId"); + const scheduleId = Cookies.get("scheduleId"); + const scheduleType = Cookies.get("scheduleType"); + + const [categories] = useState(initialCategories); // State untuk kategori + const [selectedTarget, setSelectedTarget] = useState(""); + const [selectedCategory, setSelectedCategory] = useState(); + const [tags, setTags] = useState([]); + const [isDraft, setIsDraft] = useState(false); + + const [unitSelection, setUnitSelection] = useState({ + allUnit: false, + mabes: false, + polda: false, + polres: false, + }); + + let fileTypeId = "1"; + + const { + control, + handleSubmit, + setValue, + formState: { errors }, + } = useForm({ + resolver: zodResolver(taskSchema), + }); + + // const handleKeyDown = (e: any) => { + // const newTag = e.target.value.trim(); // Ambil nilai input + // if (e.key === "Enter" && newTag) { + // e.preventDefault(); // Hentikan submit form + // if (!tags.includes(newTag)) { + // setTags((prevTags) => [...prevTags, newTag]); // Tambah tag baru + // setValue("tags", ""); // Kosongkan input + // } + // } + // }; + + const handleRemoveTag = (index: any) => { + setTags((prevTags) => prevTags.filter((_, i) => i !== index)); + }; + + const handleImageChange = (event: ChangeEvent) => { + if (event.target.files) { + const files = Array.from(event.target.files); + setSelectedFiles((prevImages: any) => [...prevImages, ...files]); + console.log("DATAFILE::", selectedFiles); + } + }; + + const handleRemoveImage = (index: number) => { + setSelectedFiles((prevImages) => prevImages.filter((_, i) => i !== index)); + }; + + // useEffect(() => { + // async function initState() { + // getCategories(); + // // setVideoActive(fileTypeId == '2'); + // // getRoles(); + // } + + // initState(); + // }, []); + + // const getCategories = async () => { + // try { + // const category = await listEnableCategory(fileTypeId); + // const resCategory: Category[] = category.data.data.content; + + // setCategories(resCategory); + // console.log("data category", resCategory); + + // if (scheduleId && scheduleType === "3") { + // const findCategory = resCategory.find((o) => + // o.name.toLowerCase().includes("pers rilis") + // ); + + // if (findCategory) { + // // setValue("categoryId", findCategory.id); + // setSelectedCategory(findCategory.id); // Set the selected category + // const response = await getTagsBySubCategoryId(findCategory.id); + // setTags(response?.data.data); + // } + // } + // } catch (error) { + // console.error("Failed to fetch categories:", error); + // } + // }; + + const save = async (data: TaskSchema) => { + const requestData = { + ...data, + title: data.title, + description: data.description, + categoryId: selectedTarget, + slug: data.slug, + metadata: data.meta, + // tags: data.tags, + isDraft, + }; + + const response = await postBlog(requestData); + console.log("Form Data Submitted:", requestData); + console.log("response", response); + + MySwal.fire({ + title: "Sukses", + text: "Data berhasil disimpan.", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then(() => { + router.push("/en/contributor/blog"); + }); + }; + + const onSubmit = (data: TaskSchema) => { + MySwal.fire({ + title: "Simpan Data", + text: "Apakah Anda yakin ingin menyimpan data ini?", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + }; + + const handlePublish = () => { + setIsDraft(false); + }; + + const handleSave = () => { + setIsDraft(true); + }; + + return ( +
+
+ +
+

Form Indeks

+
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.title?.message && ( +

{errors.title.message}

+ )} +
+ +
+ + ( + + )} + /> + {errors.description?.message && ( +

+ {errors.description.message} +

+ )} +
+
+
+ + ( + + )} + /> + {errors.slug?.message && ( +

+ {errors.slug.message} +

+ )} +
+
+
+
+ + ( + + )} + /> + {errors.meta?.message && ( +

+ {errors.meta.message} +

+ )} +
+
+
+
+
+
+ +
+ + { + // const file = e.target.files[0]; + // if (file) { + // console.log("Selected File:", file); + // // Tambahkan logika jika diperlukan, misalnya upload file ke server + // } + // }} + className="" + /> +
+
+ + +
+
+ + {/* ( + + )} + /> */} +
+ {tags.length === 0 && "Please add at least one tag."} +
+
+ {tags.map((tag, index) => ( +
+ {tag} + +
+ ))} +
+
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+ ); +} diff --git a/components/form/planning/mediahub-publish.tsx b/components/form/planning/mediahub-publish.tsx new file mode 100644 index 00000000..49060fa6 --- /dev/null +++ b/components/form/planning/mediahub-publish.tsx @@ -0,0 +1,352 @@ +"use client"; +import React, { useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Checkbox } from "@/components/ui/checkbox"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import JoditEditor from "jodit-react"; +import { createTask } from "@/service/task"; +import { cn } from "@/lib/utils"; +import { format } from "date-fns"; +import { CalendarIcon } from "lucide-react"; +import { id } from "date-fns/locale"; +import { getPlanningById } from "@/service/planning/planning"; + +const taskSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + naration: z.string().min(2, { + message: "Narasi Penugasan harus lebih dari 2 karakter.", + }), +}); + +export type mediahubDetail = { + id: number; + title: string; + fileTypeOutput: string; + assignedToTopLevel: string; + assignmentType: { + id: number; + name: string; + }; + date: string; + description: string; + is_active: string; +}; + +export default function PublishMediahub() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type TaskSchema = z.infer; + const { id } = useParams() as { id: string }; + console.log(id); + const [taskOutput, setTaskOutput] = useState({ + all: false, + video: false, + audio: false, + image: false, + text: false, + }); + const [mainType, setMainType] = useState(1); + const [taskType, setTaskType] = useState("atensi-khusus"); + const [broadcastType, setBroadcastType] = useState("all"); // untuk Tipe Penugasan + const [type, setType] = useState("1"); + const [selectedTarget, setSelectedTarget] = useState("all"); + const [startDate, setStartDate] = useState(new Date()); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + + const [platformTypeVisible, setPlatformTypeVisible] = useState(false); + const [unitSelection, setUnitSelection] = useState({ + allUnit: false, + mabes: false, + polda: false, + polres: false, + }); + + const { + control, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: zodResolver(taskSchema), + }); + + const handleRadioChange = (event: React.ChangeEvent) => { + const selectedValue = Number(event.target.value); + setMainType(selectedValue); + + setPlatformTypeVisible(selectedValue === 2); + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await getPlanningById(id); + const details = response.data?.data; + + setDetail(details); + if (details?.date) { + setStartDate(new Date(details.date)); // Konversi string tanggal ke objek Date + } + } + } + initState(); + }, [id, refresh]); + + useEffect(() => { + if (detail?.fileTypeOutput) { + const outputSet = new Set(detail.fileTypeOutput.split(",").map(Number)); // Membagi string ke dalam array dan mengonversi ke nomor + setTaskOutput({ + all: outputSet.has(0), + video: outputSet.has(2), + audio: outputSet.has(4), + image: outputSet.has(1), + text: outputSet.has(3), + }); + } + }, [detail?.fileTypeOutput]); + + useEffect(() => { + if (detail?.assignedToTopLevel) { + const outputSet = new Set( + detail.assignedToTopLevel.split(",").map(Number) + ); // Membagi string ke dalam array dan mengonversi ke nomor + setUnitSelection({ + allUnit: outputSet.has(0), + mabes: outputSet.has(1), + polda: outputSet.has(2), + polres: outputSet.has(3), + }); + } + }, [detail?.fileTypeOutput]); + + const save = async (data: TaskSchema) => { + const fileTypeMapping = { + all: "1", + video: "2", + audio: "3", + image: "4", + text: "5", + }; + + const selectedOutputs = Object.keys(taskOutput) + .filter((key) => taskOutput[key as keyof typeof taskOutput]) // Ambil hanya yang `true` + .map((key) => fileTypeMapping[key as keyof typeof fileTypeMapping]) // Konversi ke nilai string + .join(","); + + const requestData = { + ...data, + // assignmentType, + // assignmentCategory, + target: selectedTarget, + unitSelection, + assignedToRole: "3", + taskType: taskType, + broadcastType: broadcastType, + assignmentMainTypeId: mainType, + assignmentPurpose: "1", + assignmentTypeId: type, + fileTypeOutput: selectedOutputs, + id: null, + narration: data.naration, + platformType: "", + title: data.title, + }; + + const response = await createTask(requestData); + + console.log("Form Data Submitted:", requestData); + console.log("response", response); + + MySwal.fire({ + title: "Sukses", + text: "Data berhasil disimpan.", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then(() => { + router.push("/en/contributor/task"); + }); + }; + + const onSubmit = (data: TaskSchema) => { + MySwal.fire({ + title: "Simpan Data", + text: "Apakah Anda yakin ingin menyimpan data ini?", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + }; + + return ( + +
+

Perencanaan Mediahub

+ {detail !== undefined ? ( +
+
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.title?.message && ( +

{errors.title.message}

+ )} +
+
+ +
+ {Object.keys(taskOutput).map((key) => ( +
+ + setTaskOutput({ ...taskOutput, [key]: value }) + } + /> + +
+ ))} +
+
+
+
+ +
+ {Object.keys(unitSelection).map((key) => ( +
+ + setUnitSelection({ ...unitSelection, [key]: value }) + } + /> + +
+ ))} +
+
+
+
+ + setType(value)} // Mengubah nilai state ketika pilihan berubah + className="flex flex-wrap gap-3" + > +
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+ + ( + + )} + /> + {errors.naration?.message && ( +

+ {errors.naration.message} +

+ )} +
+
+ + {/* Submit Button */} +
+ +
+
+ ) : ( + "" + )} +
+
+ ); +} diff --git a/components/form/planning/medsos-publish.tsx b/components/form/planning/medsos-publish.tsx new file mode 100644 index 00000000..5124f4a4 --- /dev/null +++ b/components/form/planning/medsos-publish.tsx @@ -0,0 +1,352 @@ +"use client"; +import React, { useEffect, useRef, useState } from "react"; +import { useForm, Controller } from "react-hook-form"; +import { Input } from "@/components/ui/input"; +import { Button } from "@/components/ui/button"; +import { Label } from "@/components/ui/label"; +import { Card } from "@/components/ui/card"; +import { zodResolver } from "@hookform/resolvers/zod"; +import * as z from "zod"; +import Swal from "sweetalert2"; +import withReactContent from "sweetalert2-react-content"; +import { useParams, useRouter } from "next/navigation"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/ui/select"; +import { Checkbox } from "@/components/ui/checkbox"; +import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; +import JoditEditor from "jodit-react"; +import { createTask } from "@/service/task"; +import { cn } from "@/lib/utils"; +import { format } from "date-fns"; +import { CalendarIcon } from "lucide-react"; +import { id } from "date-fns/locale"; +import { getPlanningById } from "@/service/planning/planning"; + +const taskSchema = z.object({ + title: z.string().min(1, { message: "Judul diperlukan" }), + naration: z.string().min(2, { + message: "Narasi Penugasan harus lebih dari 2 karakter.", + }), +}); + +export type medsosDetail = { + id: number; + title: string; + fileTypeOutput: string; + assignedToTopLevel: string; + assignmentType: { + id: number; + name: string; + }; + date: string; + description: string; + is_active: string; +}; + +export default function PublishMedsos() { + const MySwal = withReactContent(Swal); + const router = useRouter(); + const editor = useRef(null); + type TaskSchema = z.infer; + const { id } = useParams() as { id: string }; + console.log(id); + const [taskOutput, setTaskOutput] = useState({ + all: false, + video: false, + audio: false, + image: false, + text: false, + }); + const [mainType, setMainType] = useState(1); + const [taskType, setTaskType] = useState("atensi-khusus"); + const [broadcastType, setBroadcastType] = useState("all"); // untuk Tipe Penugasan + const [type, setType] = useState("1"); + const [selectedTarget, setSelectedTarget] = useState("all"); + const [startDate, setStartDate] = useState(new Date()); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); + + const [platformTypeVisible, setPlatformTypeVisible] = useState(false); + const [unitSelection, setUnitSelection] = useState({ + allUnit: false, + mabes: false, + polda: false, + polres: false, + }); + + const { + control, + handleSubmit, + formState: { errors }, + } = useForm({ + resolver: zodResolver(taskSchema), + }); + + const handleRadioChange = (event: React.ChangeEvent) => { + const selectedValue = Number(event.target.value); + setMainType(selectedValue); + + setPlatformTypeVisible(selectedValue === 2); + }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await getPlanningById(id); + const details = response.data?.data; + + setDetail(details); + if (details?.date) { + setStartDate(new Date(details.date)); // Konversi string tanggal ke objek Date + } + } + } + initState(); + }, [id, refresh]); + + useEffect(() => { + if (detail?.fileTypeOutput) { + const outputSet = new Set(detail.fileTypeOutput.split(",").map(Number)); // Membagi string ke dalam array dan mengonversi ke nomor + setTaskOutput({ + all: outputSet.has(0), + video: outputSet.has(2), + audio: outputSet.has(4), + image: outputSet.has(1), + text: outputSet.has(3), + }); + } + }, [detail?.fileTypeOutput]); + + useEffect(() => { + if (detail?.assignedToTopLevel) { + const outputSet = new Set( + detail.assignedToTopLevel.split(",").map(Number) + ); // Membagi string ke dalam array dan mengonversi ke nomor + setUnitSelection({ + allUnit: outputSet.has(0), + mabes: outputSet.has(1), + polda: outputSet.has(2), + polres: outputSet.has(3), + }); + } + }, [detail?.fileTypeOutput]); + + const save = async (data: TaskSchema) => { + const fileTypeMapping = { + all: "1", + video: "2", + audio: "3", + image: "4", + text: "5", + }; + + const selectedOutputs = Object.keys(taskOutput) + .filter((key) => taskOutput[key as keyof typeof taskOutput]) // Ambil hanya yang `true` + .map((key) => fileTypeMapping[key as keyof typeof fileTypeMapping]) // Konversi ke nilai string + .join(","); + + const requestData = { + ...data, + // assignmentType, + // assignmentCategory, + target: selectedTarget, + unitSelection, + assignedToRole: "3", + taskType: taskType, + broadcastType: broadcastType, + assignmentMainTypeId: mainType, + assignmentPurpose: "1", + assignmentTypeId: type, + fileTypeOutput: selectedOutputs, + id: null, + narration: data.naration, + platformType: "", + title: data.title, + }; + + const response = await createTask(requestData); + + console.log("Form Data Submitted:", requestData); + console.log("response", response); + + MySwal.fire({ + title: "Sukses", + text: "Data berhasil disimpan.", + icon: "success", + confirmButtonColor: "#3085d6", + confirmButtonText: "OK", + }).then(() => { + router.push("/en/contributor/task"); + }); + }; + + const onSubmit = (data: TaskSchema) => { + MySwal.fire({ + title: "Simpan Data", + text: "Apakah Anda yakin ingin menyimpan data ini?", + icon: "warning", + showCancelButton: true, + cancelButtonColor: "#d33", + confirmButtonColor: "#3085d6", + confirmButtonText: "Simpan", + }).then((result) => { + if (result.isConfirmed) { + save(data); + } + }); + }; + + return ( + +
+

Perencanaan Mediahub

+ {detail !== undefined ? ( +
+
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.title?.message && ( +

{errors.title.message}

+ )} +
+
+ +
+ {Object.keys(taskOutput).map((key) => ( +
+ + setTaskOutput({ ...taskOutput, [key]: value }) + } + /> + +
+ ))} +
+
+
+
+ +
+ {Object.keys(unitSelection).map((key) => ( +
+ + setUnitSelection({ ...unitSelection, [key]: value }) + } + /> + +
+ ))} +
+
+
+
+ + setType(value)} // Mengubah nilai state ketika pilihan berubah + className="flex flex-wrap gap-3" + > +
+ + +
+
+ + +
+
+ + +
+
+
+
+
+ +
+ +
+
+
+
+ + ( + + )} + /> + {errors.naration?.message && ( +

+ {errors.naration.message} +

+ )} +
+
+ + {/* Submit Button */} +
+ +
+
+ ) : ( + "" + )} +
+
+ ); +} diff --git a/components/form/task/task-form.tsx b/components/form/task/task-form.tsx index 69b89bc3..37e5d9fa 100644 --- a/components/form/task/task-form.tsx +++ b/components/form/task/task-form.tsx @@ -1,5 +1,5 @@ "use client"; -import React, { useRef, useState } from "react"; +import React, { useEffect, useRef, useState } from "react"; import { useForm, Controller } from "react-hook-form"; import { Input } from "@/components/ui/input"; import { Button } from "@/components/ui/button"; @@ -9,7 +9,7 @@ import { zodResolver } from "@hookform/resolvers/zod"; import * as z from "zod"; import Swal from "sweetalert2"; import withReactContent from "sweetalert2-react-content"; -import { useRouter } from "next/navigation"; +import { useParams, useRouter } from "next/navigation"; import { Select, SelectContent, @@ -20,7 +20,7 @@ import { import { Checkbox } from "@/components/ui/checkbox"; import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"; import JoditEditor from "jodit-react"; -import { createTask } from "@/service/task"; +import { createTask, getTask } from "@/service/task"; const taskSchema = z.object({ title: z.string().min(1, { message: "Judul diperlukan" }), @@ -29,11 +29,32 @@ const taskSchema = z.object({ }), }); +export type taskDetail = { + id: number; + title: string; + fileTypeOutput: string; + assignedToTopLevel: string; + assignmentType: { + id: number; + name: string; + }; + assignmentMainType: { + id: number; + name: string; + }; + taskType: string; + broadcastType: string; + narration: string; + is_active: string; +}; + export default function FormTask() { const MySwal = withReactContent(Swal); const router = useRouter(); const editor = useRef(null); type TaskSchema = z.infer; + const { id } = useParams() as { id: string }; + console.log(id); // State for various form fields const [taskOutput, setTaskOutput] = useState({ @@ -46,9 +67,13 @@ export default function FormTask() { // const [assignmentType, setAssignmentType] = useState("mediahub"); // const [assignmentCategory, setAssignmentCategory] = useState("publication"); - const [mainType, setMainType] = useState(1); // untuk Tipe Penugasan + const [mainType, setMainType] = useState("1"); + const [taskType, setTaskType] = useState("atensi-khusus"); + const [broadcastType, setBroadcastType] = useState(""); // untuk Tipe Penugasan const [type, setType] = useState("1"); const [selectedTarget, setSelectedTarget] = useState("all"); + const [detail, setDetail] = useState(); + const [refresh] = useState(false); const [platformTypeVisible, setPlatformTypeVisible] = useState(false); const [unitSelection, setUnitSelection] = useState({ @@ -66,12 +91,57 @@ export default function FormTask() { resolver: zodResolver(taskSchema), }); - const handleRadioChange = (event: React.ChangeEvent) => { - const selectedValue = Number(event.target.value); - setMainType(selectedValue); + // const handleRadioChange = (event: React.ChangeEvent) => { + // const selectedValue = Number(event.target.value); + // setMainType(selectedValue); - setPlatformTypeVisible(selectedValue === 2); - }; + // setPlatformTypeVisible(selectedValue === 2); + // }; + + useEffect(() => { + async function initState() { + if (id) { + const response = await getTask(id); + const details = response.data?.data; + + setDetail(details); + } + } + initState(); + }, [id, refresh]); + + useEffect(() => { + if (detail?.broadcastType) { + setBroadcastType(detail.broadcastType); // Mengatur nilai broadcastType dari API + } + }, [detail?.broadcastType]); + + useEffect(() => { + if (detail?.fileTypeOutput) { + const outputSet = new Set(detail.fileTypeOutput.split(",").map(Number)); // Membagi string ke dalam array dan mengonversi ke nomor + setTaskOutput({ + all: outputSet.has(0), + video: outputSet.has(2), + audio: outputSet.has(4), + image: outputSet.has(1), + text: outputSet.has(3), + }); + } + }, [detail?.fileTypeOutput]); + + useEffect(() => { + if (detail?.assignedToTopLevel) { + const outputSet = new Set( + detail.assignedToTopLevel.split(",").map(Number) + ); + setUnitSelection({ + allUnit: outputSet.has(0), + mabes: outputSet.has(1), + polda: outputSet.has(2), + polres: outputSet.has(3), + }); + } + }, [detail?.fileTypeOutput]); const save = async (data: TaskSchema) => { const fileTypeMapping = { @@ -94,6 +164,8 @@ export default function FormTask() { target: selectedTarget, unitSelection, assignedToRole: "3", + taskType: taskType, + broadcastType: broadcastType, assignmentMainTypeId: mainType, assignmentPurpose: "1", assignmentTypeId: type, @@ -106,11 +178,6 @@ export default function FormTask() { const response = await createTask(requestData); - // if (response.error) { - // error(response.message); - // return false; - // } - console.log("Form Data Submitted:", requestData); console.log("response", response); @@ -121,7 +188,7 @@ export default function FormTask() { confirmButtonColor: "#3085d6", confirmButtonText: "OK", }).then(() => { - router.push("/contributor/task"); + router.push("/en/contributor/task"); }); }; @@ -145,144 +212,184 @@ export default function FormTask() {

Form Penugasan

-
-
- {/* Input Title */} -
- - ( - + {detail !== undefined ? ( + +
+ {/* Input Title */} +
+ + ( + + )} + /> + {errors.title?.message && ( +

{errors.title.message}

)} - /> - {errors.title?.message && ( -

{errors.title.message}

- )} -
-
+
+
+
+ + +
+
+ {Object.keys(unitSelection).map((key) => ( +
+ + setUnitSelection({ ...unitSelection, [key]: value }) + } + /> + +
+ ))} +
+
- - + + setMainType(value)} + // value={String(mainType)} + // onValueChange={(value) => setMainType(Number(value))} + className="flex flex-wrap gap-3" + > + + + + +
-
- {Object.keys(unitSelection).map((key) => ( -
- - setUnitSelection({ ...unitSelection, [key]: value }) - } - /> - +
+ + setTaskType(String(value))} + className="flex flex-wrap gap-3" + > + + + + + +
+ {/* RadioGroup Assignment Category */} +
+ + setType(value)} // Mengubah nilai state ketika pilihan berubah + className="flex flex-wrap gap-3" + > +
+ +
- ))} -
-
-
- - setMainType(Number(value))} - className="flex flex-wrap gap-6" - > - - - - - -
- - {/* RadioGroup Assignment Category */} -
- - setType(value)} // Mengubah nilai state ketika pilihan berubah - className="flex flex-wrap gap-6" - > -
- - -
-
- - -
-
- - -
-
-
- -
- -
- {Object.keys(taskOutput).map((key) => ( -
- - setTaskOutput({ ...taskOutput, [key]: value }) - } - /> - +
+ +
- ))} +
+ + +
+
-
-
- - ( - +
+ +
+ {Object.keys(taskOutput).map((key) => ( +
+ + setTaskOutput({ ...taskOutput, [key]: value }) + } + /> + +
+ ))} +
+
+
+ + setBroadcastType(value)} // Mengatur nilai saat radio berubah + className="flex flex-wrap gap-3" + > +
+ + +
+
+ + +
+
+ + +
+
+
+
+ + ( + + )} + /> + {errors.naration?.message && ( +

+ {errors.naration.message} +

)} - /> - {errors.naration?.message && ( -

- {errors.naration.message} -

- )} +
-
- {/* Submit Button */} -
- -
- + {/* Submit Button */} +
+ +
+ + ) : ( + "" + )}
); diff --git a/package-lock.json b/package-lock.json index 77de34a6..c46f2df8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -151,6 +151,7 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, "engines": { "node": ">=10" }, @@ -1216,6 +1217,7 @@ "version": "8.0.2", "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, "dependencies": { "string-width": "^5.1.2", "string-width-cjs": "npm:string-width@^4.2.0", @@ -1232,6 +1234,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, "engines": { "node": ">=12" }, @@ -1243,6 +1246,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -1773,6 +1777,7 @@ "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -1785,6 +1790,7 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, "engines": { "node": ">= 8" } @@ -1793,6 +1799,7 @@ "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -1822,6 +1829,7 @@ "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, "optional": true, "engines": { "node": ">=14" @@ -3731,7 +3739,7 @@ "version": "18.3.1", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", - "devOptional": true, + "dev": true, "dependencies": { "@types/react": "*" } @@ -4025,6 +4033,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -4038,6 +4047,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -4051,12 +4061,14 @@ "node_modules/any-promise": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -4101,7 +4113,8 @@ "node_modules/arg": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==" + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true }, "node_modules/argparse": { "version": "2.0.1", @@ -4392,12 +4405,14 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/binary-extensions": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, "engines": { "node": ">=8" }, @@ -4419,6 +4434,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "dependencies": { "fill-range": "^7.1.1" }, @@ -4478,6 +4494,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, "engines": { "node": ">= 6" } @@ -4577,6 +4594,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4600,6 +4618,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -4784,6 +4803,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", @@ -4807,6 +4827,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, "bin": { "cssesc": "bin/cssesc" }, @@ -5482,7 +5503,8 @@ "node_modules/didyoumean": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==" + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true }, "node_modules/diff": { "version": "5.2.0", @@ -5507,7 +5529,8 @@ "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true }, "node_modules/doctrine": { "version": "3.0.0", @@ -5608,7 +5631,8 @@ "node_modules/eastasianwidth": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true }, "node_modules/elkjs": { "version": "0.9.3", @@ -5656,7 +5680,8 @@ "node_modules/emoji-regex": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true }, "node_modules/enhanced-resolve": { "version": "5.17.1", @@ -6496,6 +6521,7 @@ "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -6511,6 +6537,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "dependencies": { "is-glob": "^4.0.1" }, @@ -6534,6 +6561,7 @@ "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, "dependencies": { "reusify": "^1.0.4" } @@ -6577,6 +6605,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6667,6 +6696,7 @@ "version": "3.3.0", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, "dependencies": { "cross-spawn": "^7.0.0", "signal-exit": "^4.0.1" @@ -6735,6 +6765,7 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, "hasInstallScript": true, "optional": true, "os": [ @@ -6890,6 +6921,7 @@ "version": "10.3.10", "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.3.5", @@ -6911,6 +6943,7 @@ "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, "dependencies": { "is-glob": "^4.0.3" }, @@ -6922,6 +6955,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0" } @@ -6930,6 +6964,7 @@ "version": "9.0.5", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, "dependencies": { "brace-expansion": "^2.0.1" }, @@ -7897,6 +7932,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, "dependencies": { "binary-extensions": "^2.0.0" }, @@ -8028,6 +8064,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -8051,6 +8088,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } @@ -8074,6 +8112,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, "dependencies": { "is-extglob": "^2.1.1" }, @@ -8118,6 +8157,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, "engines": { "node": ">=0.12.0" } @@ -8366,6 +8406,7 @@ "version": "2.3.6", "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, @@ -8383,6 +8424,7 @@ "version": "1.21.6", "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, "bin": { "jiti": "bin/jiti.js" } @@ -8646,6 +8688,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, "engines": { "node": ">=14" }, @@ -8754,7 +8797,8 @@ "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==" + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/lucide-react": { "version": "0.390.0", @@ -9468,6 +9512,7 @@ "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, "engines": { "node": ">= 8" } @@ -10255,6 +10300,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -10315,6 +10361,7 @@ "version": "7.1.2", "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "engines": { "node": ">=16 || 14 >=14.17" } @@ -10363,6 +10410,7 @@ "version": "2.7.0", "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, "dependencies": { "any-promise": "^1.0.0", "object-assign": "^4.0.1", @@ -10665,6 +10713,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -10719,6 +10768,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, "engines": { "node": ">= 6" } @@ -11017,6 +11067,7 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, "engines": { "node": ">=8" } @@ -11030,6 +11081,7 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" @@ -11068,6 +11120,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, "engines": { "node": ">=8.6" }, @@ -11079,6 +11132,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, "engines": { "node": ">=0.10.0" } @@ -11087,6 +11141,7 @@ "version": "4.0.6", "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, "engines": { "node": ">= 6" } @@ -11104,6 +11159,7 @@ "version": "8.4.49", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "dev": true, "funding": [ { "type": "opencollective", @@ -11131,6 +11187,7 @@ "version": "15.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", @@ -11147,6 +11204,7 @@ "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, "dependencies": { "camelcase-css": "^2.0.1" }, @@ -11165,6 +11223,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -11199,6 +11258,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.1.tgz", "integrity": "sha512-7r0XPzioN/Q9kXBro/XPnA6kznR73DHq+GXh5ON7ZozRO6aMjbmiBuKste2wslTFkC5d1dw0GooOCepZXJ2SAg==", + "dev": true, "bin": { "yaml": "bin.mjs" }, @@ -11210,6 +11270,7 @@ "version": "6.2.0", "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, "funding": [ { "type": "opencollective", @@ -11234,6 +11295,7 @@ "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" @@ -11245,7 +11307,8 @@ "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true }, "node_modules/preact": { "version": "10.12.1", @@ -11350,6 +11413,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, "funding": [ { "type": "github", @@ -11886,6 +11950,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, "dependencies": { "pify": "^2.3.0" } @@ -11894,6 +11959,7 @@ "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, "dependencies": { "picomatch": "^2.2.1" }, @@ -12316,6 +12382,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" @@ -12388,6 +12455,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, "funding": [ { "type": "github", @@ -12579,6 +12647,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, "dependencies": { "shebang-regex": "^3.0.0" }, @@ -12590,6 +12659,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, "engines": { "node": ">=8" } @@ -12626,6 +12696,7 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, "engines": { "node": ">=14" }, @@ -12755,6 +12826,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, "dependencies": { "eastasianwidth": "^0.2.0", "emoji-regex": "^9.2.2", @@ -12772,6 +12844,7 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -12784,12 +12857,14 @@ "node_modules/string-width-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/string-width/node_modules/ansi-regex": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, "engines": { "node": ">=12" }, @@ -12801,6 +12876,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, @@ -12936,6 +13012,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -12948,6 +13025,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -13052,6 +13130,7 @@ "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, "dependencies": { "@jridgewell/gen-mapping": "^0.3.2", "commander": "^4.0.0", @@ -13073,6 +13152,7 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, "engines": { "node": ">= 6" } @@ -13246,6 +13326,7 @@ "version": "3.4.16", "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.16.tgz", "integrity": "sha512-TI4Cyx7gDiZ6r44ewaJmt0o6BrMCT5aK5e0rmJ/G9Xq3w7CX/5VXl/zIPEJZFUK5VEqwByyhqNPycPlvcK4ZNw==", + "dev": true, "dependencies": { "@alloc/quick-lru": "^5.2.0", "arg": "^5.0.2", @@ -13305,6 +13386,7 @@ "version": "3.3.1", "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, "dependencies": { "any-promise": "^1.0.0" } @@ -13313,6 +13395,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, "dependencies": { "thenify": ">= 3.1.0 < 4" }, @@ -13420,6 +13503,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, "dependencies": { "is-number": "^7.0.0" }, @@ -13477,7 +13561,8 @@ "node_modules/ts-interface-checker": { "version": "0.1.13", "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==" + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true }, "node_modules/tsconfig-paths": { "version": "3.15.0", @@ -13955,7 +14040,8 @@ "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true }, "node_modules/uuid": { "version": "9.0.1", @@ -14194,6 +14280,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, "dependencies": { "isexe": "^2.0.0" }, @@ -14300,6 +14387,7 @@ "version": "8.1.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, "dependencies": { "ansi-styles": "^6.1.0", "string-width": "^5.0.1", @@ -14317,6 +14405,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -14332,12 +14421,14 @@ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/wrap-ansi-cjs/node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -14351,6 +14442,7 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, "engines": { "node": ">=12" }, @@ -14362,6 +14454,7 @@ "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, "engines": { "node": ">=12" }, @@ -14373,6 +14466,7 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, "dependencies": { "ansi-regex": "^6.0.1" }, diff --git a/service/blog/blog.ts b/service/blog/blog.ts index a3e5ecbd..88b48b30 100644 --- a/service/blog/blog.ts +++ b/service/blog/blog.ts @@ -1,5 +1,6 @@ import { title } from "process"; import { httpGetInterceptor } from "../http-config/http-interceptor-service"; +import { postAPIInterceptor } from "@/config/api"; export async function paginationBlog( size: number, @@ -10,3 +11,8 @@ export async function paginationBlog( `blog/pagination?enablePage=1&page=${page}&size=${size}&title=${title}` ); } + +export async function postBlog(data: any) { + const url = "blog"; + return postAPIInterceptor(url, data); +} diff --git a/service/content/content.ts b/service/content/content.ts index c7f4dbb7..70f0254b 100644 --- a/service/content/content.ts +++ b/service/content/content.ts @@ -1,6 +1,47 @@ import { getAPIInterceptor, postAPIInterceptor } from "@/config/api"; import { httpGetInterceptor } from "../http-config/http-interceptor-service"; +// export async function listDataAll( +// isForSelf, +// isApproval, +// page, +// limit, +// search, +// fileTypeFilter, +// statusFilter, +// startDate, +// endDate, +// needApprovalFromLevel +// ) { +// const name = search || ""; +// const url = `media/list?title=${name}&enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&isForSelf=${isForSelf}&isApproval=${isApproval}&typeId=${fileTypeFilter}&statusId=${statusFilter}&startDate=${ +// startDate == undefined ? "" : startDate +// }&endDate=${ +// endDate == undefined ? "" : endDate +// }&needApprovalFromLevel=${needApprovalFromLevel}`; +// return getAPIInterceptor({ url }); +// } + +export async function listDataAll( + isForSelf: any, + isApproval: any, + page: any, + limit: any, + search: any, + fileTypeFilter: any, + statusFilter: any, + needApprovalFromLevel: any, + creator: any, + source: any, + startDate: any, + endDate: any, + title: string = "" +) { + return await getAPIInterceptor( + `media/list?enablePage=1&sortBy=createdAt&sort=desc&size=${limit}&page=${page}&isForSelf=${isForSelf}&isApproval=${isApproval}&typeId=${fileTypeFilter}&statusId=${statusFilter}&needApprovalFromLevel=${needApprovalFromLevel}&title=${title}` + ); +} + export async function listDataImage( limit: any, page: any, diff --git a/service/contest/contest.ts b/service/contest/contest.ts index 7e94aa04..2dbf3d68 100644 --- a/service/contest/contest.ts +++ b/service/contest/contest.ts @@ -4,9 +4,9 @@ import { } from "../http-config/http-interceptor-service"; export async function listContest( + title: string = "", size: number, - page: number, - title: string = "" + page: number ) { return await httpGetInterceptor( `contest/pagination?enablePage=1&size=${size}&page=${page}&title=${title}` diff --git a/service/curated-content/curated-content.ts b/service/curated-content/curated-content.ts new file mode 100644 index 00000000..af1628f4 --- /dev/null +++ b/service/curated-content/curated-content.ts @@ -0,0 +1,6 @@ +import { getAPIInterceptor } from "@/config/api"; + +export async function detailMedia(id: any) { + const url = `media?id=${id}`; + return getAPIInterceptor(url); +} diff --git a/service/planning/planning.ts b/service/planning/planning.ts index 09419b25..c0010852 100644 --- a/service/planning/planning.ts +++ b/service/planning/planning.ts @@ -1,3 +1,4 @@ +import { getAPIInterceptor } from "@/config/api"; import { httpGetInterceptor } from "../http-config/http-interceptor-service"; export async function getPlanningSentPagination( @@ -10,3 +11,8 @@ export async function getPlanningSentPagination( `planning/pagination/sent?enablePage=1&size=${size}&page=${page}&typeId=${typeId}&title=${title}` ); } + +export async function getPlanningById(id: any) { + const url = `planning?id=${id}`; + return getAPIInterceptor(url); +} diff --git a/service/task.ts b/service/task.ts index c2afd1c6..4aca8bcd 100644 --- a/service/task.ts +++ b/service/task.ts @@ -38,7 +38,7 @@ export async function createTask(data: any) { export async function getTask(id: any) { const url = `/assignment?id=${id}`; - return getAPIInterceptor({ url }); + return getAPIInterceptor(url); } export async function forwardTask(data: any) {