471 lines
14 KiB
TypeScript
471 lines
14 KiB
TypeScript
"use client";
|
|
import dayjs from "dayjs";
|
|
import { useEffect, useRef, useState } from "react";
|
|
import utc from "dayjs/plugin/utc";
|
|
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
import { close, loading } from "@/config/swal";
|
|
import { useSearchParams } from "next/navigation";
|
|
import { Swiper, SwiperSlide } from "swiper/react";
|
|
import "swiper/css";
|
|
import "swiper/css/free-mode";
|
|
import "swiper/css/navigation";
|
|
import "swiper/css/thumbs";
|
|
|
|
import Image from "next/image";
|
|
import { FreeMode, Navigation, Thumbs } from "swiper/modules";
|
|
import { Swiper as SwiperType } from "swiper/types";
|
|
import {
|
|
getMonthlyPlanList,
|
|
getPlanningDailyByTypeId,
|
|
getPlanningDailyMedsosByPlatform,
|
|
getPlanningMonthlyPerSocmed,
|
|
getWeeklyPlanList,
|
|
getWeeklyPlanListByParentId,
|
|
} from "@/service/agenda-setting/agenda-setting";
|
|
import TaskPlanMediahubTable from "@/app/[locale]/(protected)/curator/task-plan/mediahub/components/table";
|
|
import weekday from "dayjs/plugin/weekday";
|
|
import { Icon } from "@iconify/react/dist/iconify.js";
|
|
import {
|
|
FacebookIcon,
|
|
InstagramIcon,
|
|
TiktokIcon,
|
|
XIcon,
|
|
YoutubeIcon,
|
|
} from "@/components/icon";
|
|
import {
|
|
Dialog,
|
|
DialogContent,
|
|
DialogHeader,
|
|
DialogTitle,
|
|
DialogTrigger,
|
|
} from "@/components/ui/dialog";
|
|
import TaskPlanningSocialMediaTable from "./social-media-modal/table";
|
|
|
|
const WEEKDAYS = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
|
const TODAY = dayjs().format("YYYY-MM-DD");
|
|
|
|
export default function SingleViewSocialMediaTable() {
|
|
const params = useSearchParams();
|
|
const [selectedMonthItem, setSelectedMonthItem] = useState<
|
|
string | undefined
|
|
>(undefined);
|
|
const [selectedWeekly, setSelectedWeekly] = useState<string | undefined>(
|
|
undefined
|
|
);
|
|
const [selectedDate, setSelectedDate] = useState<number>(
|
|
new Date(TODAY).getDate()
|
|
);
|
|
const [nowDate, setNowDate] = useState<string>(TODAY);
|
|
|
|
const INITIAL_YEAR = dayjs().format("YYYY");
|
|
const INITIAL_MONTH = dayjs().format("M");
|
|
const size = 20;
|
|
|
|
const page: string | undefined | null = params?.get("page");
|
|
const id: string | undefined | null = params?.get("id");
|
|
const pages = page ? Number(page) - 1 : 0;
|
|
const no = (size || 10) * pages;
|
|
|
|
const [selectedMonth, setSelectedMonth] = useState<any>(
|
|
dayjs(new Date(parseInt(INITIAL_YEAR), parseInt(INITIAL_MONTH) - 1, 1))
|
|
);
|
|
|
|
const [selectedMonthTitle, setSelectedMonthTitle] = useState<string>("");
|
|
const [days, setDays] = useState<any>([]);
|
|
|
|
const weekday = require("dayjs/plugin/weekday");
|
|
const weekOfYear = require("dayjs/plugin/weekOfYear");
|
|
|
|
const [planningData, setPlanningData] = useState<any>([]);
|
|
|
|
dayjs.extend(utc);
|
|
dayjs.extend(weekday);
|
|
dayjs.extend(weekOfYear);
|
|
|
|
let currentMonthDays: any;
|
|
let previousMonthDays: any;
|
|
let nextMonthDays: any;
|
|
|
|
const [monthlyList, setMonthlyList] = useState([]);
|
|
const [weeklyList, setWeeklyList] = useState([]);
|
|
const [getData, setGetData] = useState<any>([]);
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
const [selectedDateNow, setSelectedDateNow] = useState("");
|
|
const [selectedPlatform, setSelectedPlatform] = useState("");
|
|
|
|
useEffect(() => {
|
|
createCalendar("START");
|
|
}, []);
|
|
|
|
function createDaysForCurrentMonth(
|
|
year: string,
|
|
month: string,
|
|
daysInMonth: number
|
|
) {
|
|
const days: any = [];
|
|
for (let day = 1; day <= daysInMonth; day++) {
|
|
const date = dayjs(
|
|
new Date(parseInt(year), parseInt(month) - 1, day)
|
|
).format("YYYY-MM-DD");
|
|
days.push({
|
|
date,
|
|
isCurrentMonth: true,
|
|
isToday: date === TODAY,
|
|
});
|
|
}
|
|
return days;
|
|
}
|
|
|
|
async function getMonthlyPlanning(dates: number) {
|
|
const res = await getMonthlyPlanList(dates, 2);
|
|
setMonthlyList(res?.data?.data);
|
|
}
|
|
|
|
async function getWeeklyPlanning(
|
|
id: string | undefined,
|
|
date: number | undefined
|
|
) {
|
|
if (id) {
|
|
const res = await getWeeklyPlanListByParentId(id, 2);
|
|
setWeeklyList(res?.data?.data);
|
|
} else {
|
|
const res = await getWeeklyPlanList(date, 2, true);
|
|
setWeeklyList(res?.data?.data);
|
|
}
|
|
}
|
|
|
|
function createCalendar(
|
|
year: string = INITIAL_YEAR,
|
|
month: string = INITIAL_MONTH
|
|
) {
|
|
year = year === "START" ? INITIAL_YEAR : year;
|
|
|
|
fetchData(month, year);
|
|
|
|
setSelectedMonthTitle(
|
|
dayjs(new Date(parseInt(year), parseInt(month) - 1))
|
|
.utc()
|
|
.local()
|
|
.format("MMMM YYYY")
|
|
);
|
|
|
|
currentMonthDays = createDaysForCurrentMonth(
|
|
year,
|
|
month,
|
|
dayjs(`${year}-${month}-01`).daysInMonth()
|
|
);
|
|
|
|
getMonthlyPlanning(year ? currentMonthDays[0]?.date : TODAY);
|
|
getWeeklyPlanning(undefined, year ? currentMonthDays[0]?.date : TODAY);
|
|
|
|
previousMonthDays = createDaysForPreviousMonth(year, month);
|
|
nextMonthDays = createDaysForNextMonth(year, month);
|
|
const listDay = [
|
|
...previousMonthDays,
|
|
...currentMonthDays,
|
|
...nextMonthDays,
|
|
];
|
|
setDays(listDay);
|
|
}
|
|
|
|
function getWeekday(date: string | undefined) {
|
|
return dayjs(date).weekday();
|
|
}
|
|
|
|
function createDaysForPreviousMonth(year: string, month: string) {
|
|
const firstDayOfTheMonthWeekday = getWeekday(currentMonthDays[0]?.date);
|
|
|
|
const previousMonth = dayjs(`${year}-${month}-01`).subtract(1, "month");
|
|
|
|
// Cover first day of the month being sunday (firstDayOfTheMonthWeekday == 0)
|
|
const visibleNumberOfDaysFromPreviousMonth = firstDayOfTheMonthWeekday
|
|
? firstDayOfTheMonthWeekday - 1
|
|
: 6;
|
|
|
|
const previousMonthLastMondayDayOfMonth = dayjs(currentMonthDays[0].date)
|
|
.subtract(visibleNumberOfDaysFromPreviousMonth, "day")
|
|
.date();
|
|
|
|
return [...new Array(visibleNumberOfDaysFromPreviousMonth)].map(
|
|
(day, index) => ({
|
|
date: dayjs(
|
|
`${previousMonth.year()}-${previousMonth.month() + 1}-${
|
|
previousMonthLastMondayDayOfMonth + index
|
|
}`
|
|
).format("YYYY-MM-DD"),
|
|
dayOfMonth: previousMonthLastMondayDayOfMonth + index,
|
|
isCurrentMonth: false,
|
|
})
|
|
);
|
|
}
|
|
|
|
function createDaysForNextMonth(year: string, month: string) {
|
|
const lastDayOfTheMonthWeekday = getWeekday(
|
|
`${year}-${month}-${currentMonthDays.length}`
|
|
);
|
|
|
|
const nextMonth = dayjs(`${year}-${month}-01`).add(1, "month");
|
|
|
|
const visibleNumberOfDaysFromNextMonth = lastDayOfTheMonthWeekday
|
|
? 7 - lastDayOfTheMonthWeekday
|
|
: lastDayOfTheMonthWeekday;
|
|
|
|
return [...new Array(visibleNumberOfDaysFromNextMonth)].map(
|
|
(day, index) => ({
|
|
date: dayjs(
|
|
`${nextMonth.year()}-${nextMonth.month() + 1}-${index + 1}`
|
|
).format("YYYY-MM-DD"),
|
|
dayOfMonth: index + 1,
|
|
isCurrentMonth: false,
|
|
})
|
|
);
|
|
}
|
|
|
|
async function fetchData(
|
|
month: string,
|
|
year: string,
|
|
|
|
parentId?: string | undefined
|
|
) {
|
|
loading();
|
|
const res = await getPlanningMonthlyPerSocmed(month, year, 2, parentId);
|
|
close();
|
|
setPlanningData(res?.data?.data);
|
|
}
|
|
|
|
function getPrevMonth() {
|
|
const selectedMonthNew = dayjs(selectedMonth).subtract(1, "month");
|
|
|
|
createCalendar(
|
|
selectedMonthNew.format("YYYY"),
|
|
selectedMonthNew.format("M")
|
|
);
|
|
fetchData("", selectedMonthNew?.format("YYYY-MM-DD"));
|
|
setSelectedMonth(selectedMonthNew);
|
|
setSelectedDate(1);
|
|
}
|
|
|
|
function getPresentMonth() {
|
|
const selectedMonthNew = dayjs(
|
|
new Date(parseInt(INITIAL_YEAR), parseInt(INITIAL_MONTH) - 1, 1)
|
|
);
|
|
|
|
createCalendar(
|
|
selectedMonthNew.format("YYYY"),
|
|
selectedMonthNew.format("M")
|
|
);
|
|
fetchData("", TODAY);
|
|
setSelectedDate(Number(dayjs().format("D")));
|
|
setSelectedMonth(selectedMonthNew);
|
|
}
|
|
|
|
function getNextMonth() {
|
|
const selectedMonthNew = dayjs(selectedMonth).add(1, "month");
|
|
|
|
createCalendar(
|
|
selectedMonthNew.format("YYYY"),
|
|
selectedMonthNew.format("M")
|
|
);
|
|
fetchData("", selectedMonthNew?.format("YYYY-MM-DD"));
|
|
setSelectedMonth(selectedMonthNew);
|
|
setSelectedDate(1);
|
|
}
|
|
const onSelectedMonthItem = (id: string | undefined) => {
|
|
// fetchData(date)
|
|
setSelectedMonthItem(id);
|
|
getWeeklyPlanning(id, undefined);
|
|
};
|
|
|
|
const onSelectedWeekly = (id: string | undefined) => {
|
|
setSelectedWeekly(id);
|
|
fetchData("", String(id));
|
|
};
|
|
|
|
const removeSelection = () => {
|
|
setSelectedMonthItem(undefined);
|
|
setSelectedWeekly(undefined);
|
|
};
|
|
|
|
const onSelectedSocmed = async (date: string, platform: string) => {
|
|
setSelectedDateNow(date);
|
|
setSelectedPlatform(platform);
|
|
setIsOpen(true);
|
|
};
|
|
|
|
const getDataForThisDate = (day: number) => {
|
|
const todayData = planningData?.find((a: any) => a?.day == day);
|
|
|
|
if (todayData) {
|
|
return (
|
|
<div className="flex flex-col gap-1">
|
|
<a
|
|
onClick={() =>
|
|
onSelectedSocmed(todayData.planningList[0].date, "5")
|
|
}
|
|
className="flex flex-row gap-5 rounded-sm bg-[#0C0705] text-white px-3 py-1 justify-center cursor-pointer"
|
|
>
|
|
Total: {todayData.totalTwitter} <XIcon />
|
|
</a>
|
|
<a
|
|
onClick={() =>
|
|
onSelectedSocmed(todayData.planningList[0].date, "1")
|
|
}
|
|
className="flex flex-row gap-5 rounded-sm bg-[#1877F2] text-white px-3 py-1 justify-center cursor-pointer"
|
|
>
|
|
Total: {todayData.totalFacebook} <FacebookIcon />
|
|
</a>
|
|
<a
|
|
onClick={() =>
|
|
onSelectedSocmed(todayData.planningList[0].date, "2")
|
|
}
|
|
className="flex flex-row gap-5 rounded-sm bg-[#d62976] text-white px-3 py-1 justify-center cursor-pointer"
|
|
>
|
|
Total: {todayData.totalInstagram} <InstagramIcon />
|
|
</a>
|
|
<a
|
|
onClick={() =>
|
|
onSelectedSocmed(todayData.planningList[0].date, "3")
|
|
}
|
|
className="flex flex-row gap-5 rounded-sm bg-[#FF0000] text-white px-3 py-1 justify-center cursor-pointer"
|
|
>
|
|
Total: {todayData.totalYoutube} <YoutubeIcon />
|
|
</a>
|
|
<a
|
|
onClick={() =>
|
|
onSelectedSocmed(todayData.planningList[0].date, "4")
|
|
}
|
|
className="flex flex-row gap-5 rounded-sm bg-[#000000] text-white px-3 py-1 justify-center cursor-pointer"
|
|
>
|
|
Total: {todayData.totalTiktok} <TiktokIcon />
|
|
</a>
|
|
</div>
|
|
);
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="border-2 rounded-sm p-4 flex gap-3 flex-col">
|
|
<div className="flex justify-between">
|
|
<div className="flex flex-row gap-2">
|
|
<a onClick={getPrevMonth} className="cursor-pointer">
|
|
<ChevronLeft />
|
|
</a>
|
|
<a onClick={getPresentMonth} className="cursor-pointer">
|
|
Today
|
|
</a>
|
|
<a onClick={getNextMonth} className="cursor-pointer">
|
|
<ChevronRight />
|
|
</a>
|
|
</div>
|
|
<p className="text-xl font-semibold">{selectedMonthTitle}</p>
|
|
</div>
|
|
<div className="flex justify-end">
|
|
<a
|
|
className="border-2 border-primary px-2 py-1 rounded-full text-[10px] text-primary cursor-pointer"
|
|
onClick={() => removeSelection()}
|
|
>
|
|
Hapus Pilihan
|
|
</a>
|
|
</div>
|
|
<div className="px-8 flex flex-col gap-2 text-sm">
|
|
<p className="font-semibold">Rencana Bulanan</p>
|
|
{monthlyList?.length > 0 ? (
|
|
<div className="flex flex-nowrap gap-3 flex-row">
|
|
{monthlyList?.map((item: any) => (
|
|
<div
|
|
key={item.id}
|
|
className={`rounded-full px-8 py-3 cursor-pointer ${
|
|
selectedMonthItem === item.id
|
|
? "bg-sky-600 text-white "
|
|
: "bg-sky-300"
|
|
}`}
|
|
onClick={() => onSelectedMonthItem(item.id)}
|
|
>
|
|
<p>{item.title}</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<div className="flex justify-center bg-slate-200 rounded-full py-1">
|
|
Rencana Bulanan Belum Tersedia
|
|
</div>
|
|
)}
|
|
<p className="font-semibold">Rencana Mingguan</p>
|
|
{weeklyList?.length > 0 ? (
|
|
<div className="flex flex-nowrap gap-3 flex-row">
|
|
{weeklyList?.map((item: any) => (
|
|
<a
|
|
key={item.id}
|
|
className={`bg-sky-300 rounded-full px-8 py-3 cursor-pointer ${
|
|
selectedWeekly === item.id
|
|
? "bg-sky-600 text-white "
|
|
: "bg-sky-300"
|
|
}`}
|
|
onClick={() => onSelectedWeekly(item.id)}
|
|
>
|
|
<p>{item.title}</p>
|
|
</a>
|
|
))}
|
|
</div>
|
|
) : (
|
|
<div className="flex justify-center bg-slate-200 rounded-full py-1">
|
|
Rencana Mingguan Belum Tersedia
|
|
</div>
|
|
)}
|
|
</div>
|
|
<div>
|
|
<div className="w-full mb-2">
|
|
<div className="overflow-auto">
|
|
<ol
|
|
id="days-of-week"
|
|
className="grid grid-cols-7 gap-1 border-y-2 py-3"
|
|
>
|
|
{WEEKDAYS.map((weekday, index) => (
|
|
<li
|
|
key={`weekday-${index}`}
|
|
className="mr-1 text-sm font-medium text-end"
|
|
>
|
|
{weekday}
|
|
</li>
|
|
))}
|
|
</ol>
|
|
<ol id="calendar-days" className="grid grid-cols-7 gap-1">
|
|
{days?.map((day: any, index: number) => (
|
|
<li
|
|
key={`day-${index}`}
|
|
className={`p-2 text-end min-h-[100px] ${
|
|
day.isCurrentMonth ? "" : "bg-slate-200 text-slate-400"
|
|
}`}
|
|
>
|
|
<span
|
|
className={`block mb-1 ${
|
|
day.date == TODAY ? "font-semibold text-xl" : ""
|
|
}`}
|
|
>
|
|
{parseInt(day.date.split("-")[2])}
|
|
</span>
|
|
{day.isCurrentMonth &&
|
|
getDataForThisDate(parseInt(day.date.split("-")[2]))}
|
|
</li>
|
|
))}
|
|
</ol>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
|
<DialogContent size="lg" className="sm:max-w-md">
|
|
<DialogHeader>
|
|
<DialogTitle>Perencanaan Medsos Harian</DialogTitle>
|
|
</DialogHeader>
|
|
<div className="flex items-center space-x-2">
|
|
<TaskPlanningSocialMediaTable
|
|
date={selectedDateNow}
|
|
platform={selectedPlatform}
|
|
/>
|
|
</div>
|
|
</DialogContent>
|
|
</Dialog>
|
|
</div>
|
|
);
|
|
}
|