mediahub-fe/components/form/broadcast/content-blast-form.tsx

668 lines
19 KiB
TypeScript

"use client";
import { z } from "zod";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import {
Form,
FormField,
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import withReactContent from "sweetalert2-react-content";
import Swal from "sweetalert2";
import { Input } from "@/components/ui/input";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
getLocaleTime,
getLocaleTimestamp,
textEllipsis,
} from "@/utils/globals";
import {
detailMediaSummary,
getMediaBlastCampaignList,
saveMediaBlastBroadcast,
} from "@/service/broadcast/broadcast";
import { error } from "@/config/swal";
import { Link, useRouter } from "@/i18n/routing";
import { useEffect, useRef, useState } from "react";
import { useParams } from "next/navigation";
import Select from "react-select";
import makeAnimated from "react-select/animated";
import { Textarea } from "@/components/ui/textarea";
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import dynamic from "next/dynamic";
const CustomEditor = dynamic(
() => import("@/components/editor/custom-editor"),
{ ssr: false }
);
const animatedComponent = makeAnimated();
// -------------------------
// ZOD SCHEMA (baru)
// -------------------------
const FormSchema = z.object({
selected: z
.array(
z.object({
id: z.number(),
label: z.string(),
value: z.string(),
})
)
.min(1, "Pilih minimal satu campaign"),
title: z.string().min(1, "Required"),
url: z.string().min(1, "Required"),
thumbnail: z.string().min(1, "Required"),
detail: z.string().min(1, "Required"),
messageType: z
.array(z.string())
.min(1, "Pilih minimal satu tipe pesan (WA / Email)"),
});
interface Campaign {
id: string;
name: string;
}
export default function ContentBlast(props: { type: string }) {
const editor = useRef(null);
const id = useParams()?.id;
const MySwal = withReactContent(Swal);
const router = useRouter();
const [dataSelectCampaign, setDataSelectCampaign] = useState<Campaign[]>([]);
const [openModal, setOpenModal] = useState(false);
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
defaultValues: {
selected: [],
detail: "",
messageType: [], // checkbox
},
});
const selectedTypes = form.watch("messageType");
const onSubmit = async (data: z.infer<typeof FormSchema>) => {
MySwal.fire({
title: "Kirim Broadcast?",
text: "Pesan akan dikirim ke semua campaign yang dipilih",
icon: "warning",
showCancelButton: true,
cancelButtonColor: "#d33",
confirmButtonColor: "#3085d6",
confirmButtonText: "Kirim",
}).then((result) => {
if (result.isConfirmed) save(data);
});
};
// -------------------------
// SAVE LOGIC (baru)
// -------------------------
const save = async (data: z.infer<typeof FormSchema>) => {
const selectedCampaign = data.selected;
for (let i = 0; i < selectedCampaign.length; i++) {
const campaignId = selectedCampaign[i].id;
// Loop WA / Email
for (let mt of data.messageType) {
const payload = {
mediaUploadId: id,
mediaBlastCampaignId: campaignId,
subject: mt === "wa" ? `*${data.title}*` : data.title,
body: data.detail.replace(/\n/g, ""),
type: mt, // <-- WA / email
isScheduled: false,
thumbnail: data.thumbnail,
sendDate: getLocaleTimestamp(new Date()),
sendTime: getLocaleTime(new Date()),
contentUrl: data.url,
};
console.log("REQ =>", payload);
await saveMediaBlastBroadcast(payload);
}
}
setOpenModal(true);
};
useEffect(() => {
async function init() {
const response = await detailMediaSummary(String(id));
const details = response?.data?.data;
if (!details) return;
form.setValue("thumbnail", details.smallThumbnailLink);
form.setValue("title", details.title);
form.setValue("url", details.pageUrl);
let pageUrl = details?.pageUrl || "";
if (pageUrl.includes("mediahub.polri.go.id")) {
pageUrl = pageUrl.replace(
/(\.id)(\/|$)/,
(match: any, p1: any, p2: any) => {
return p2.startsWith("/in") ? match : `${p1}/in${p2}`;
}
);
}
const body = `<div><p>Berita hari ini !!!</p>
<div style='margin-top:20px;border:1px solid;border-radius:10px;width:500px;background-color:#f7f7f7'>
<div>
<img style='width:500px;height:auto;border-radius:10px;object-fit:cover' src='${
details.smallThumbnailLink
}'>
</div>
<a style='padding:5px 20px;margin:0;text-decoration:none' href='${pageUrl}'>${pageUrl}</a>
<h3 style='padding:5px 20px;margin:0'>${details.title}</h3>
<p style='padding:0 20px;margin:0;margin-bottom:10px'>
${textEllipsis(details.description, 150)}
</p>
</div>
</div>`;
form.setValue("detail", body);
}
async function loadCampaign() {
const response = await getMediaBlastCampaignList();
const campaign = response?.data?.data?.content;
handleLabelCampaign(campaign);
}
init();
loadCampaign();
}, [id]);
function handleLabelCampaign(data: any) {
const arr = data.map((item: any) => ({
id: item.id,
label: item.title,
value: item.title,
}));
setDataSelectCampaign(arr);
}
return (
<Form {...form}>
<form
onSubmit={form.handleSubmit(onSubmit)}
className="space-y-3 bg-white rounded-sm p-4"
>
<p className="font-semibold">Broadcast</p>
{/* SELECT CAMPAIGN */}
<FormField
control={form.control}
name="selected"
render={({ field }) => (
<FormItem>
<FormLabel>Pilih Campaign</FormLabel>
<Select
options={dataSelectCampaign}
closeMenuOnSelect={false}
components={animatedComponent}
isMulti
onChange={field.onChange}
/>
<FormMessage />
</FormItem>
)}
/>
{/* CHECKBOX MESSAGE TYPE */}
<FormField
control={form.control}
name="messageType"
render={({ field }) => (
<FormItem>
<FormLabel>Kirim sebagai:</FormLabel>
<div className="flex gap-6">
<label className="flex items-center gap-2">
<Checkbox
checked={field.value.includes("wa")}
onCheckedChange={(checked) => {
checked
? field.onChange([...field.value, "wa"])
: field.onChange(field.value.filter((v) => v !== "wa"));
}}
/>
WhatsApp
</label>
<label className="flex items-center gap-2">
<Checkbox
checked={field.value.includes("email")}
onCheckedChange={(checked) => {
checked
? field.onChange([...field.value, "email"])
: field.onChange(
field.value.filter((v) => v !== "email")
);
}}
/>
Email
</label>
</div>
<FormMessage />
</FormItem>
)}
/>
{/* TITLE */}
<FormField
control={form.control}
name="title"
render={({ field }) => (
<FormItem>
<FormLabel>Judul</FormLabel>
<Input {...field} placeholder="Masukkan judul" />
<FormMessage />
</FormItem>
)}
/>
{/* DETAIL */}
<FormField
control={form.control}
name="detail"
render={({ field }) => (
<FormItem>
<FormLabel>Isi Pesan</FormLabel>
<CustomEditor
onChange={field.onChange}
initialData={field.value}
/>
<FormMessage />
</FormItem>
)}
/>
{/* BUTTONS */}
<div className="flex gap-2 mt-4">
<Button variant="outline" type="button">
Cancel
</Button>
<Button type="submit" color="primary">
Submit
</Button>
</div>
{/* MODAL SENT */}
<Dialog open={openModal}>
<DialogContent>
<DialogHeader>
<DialogTitle>Terkirim!</DialogTitle>
</DialogHeader>
<div className="flex flex-col items-center gap-3">
<img
src="/assets/img/illust-for-broadcast-sent.png"
className="w-[70%]"
/>
Pesan telah dikirim sesuai pilihan Anda.
</div>
<DialogFooter className="flex justify-center">
<Button onClick={() => router.push("/admin/broadcast")}>
OK
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</form>
</Form>
);
}
// "use client";
// import { z } from "zod";
// import { useForm } from "react-hook-form";
// import { zodResolver } from "@hookform/resolvers/zod";
// import {
// Form,
// FormField,
// FormItem,
// FormLabel,
// FormMessage,
// } from "@/components/ui/form";
// import withReactContent from "sweetalert2-react-content";
// import Swal from "sweetalert2";
// import { Input } from "@/components/ui/input";
// import { Button } from "@/components/ui/button";
// import {
// getLocaleTime,
// getLocaleTimestamp,
// textEllipsis,
// } from "@/utils/globals";
// import {
// detailMediaSummary,
// getMediaBlastCampaignList,
// saveMediaBlastBroadcast,
// saveMediaBlastCampaign,
// } from "@/service/broadcast/broadcast";
// import { error } from "@/config/swal";
// import { Link, useRouter } from "@/i18n/routing";
// import { useEffect, useRef, useState } from "react";
// import { useParams } from "next/navigation";
// import Select from "react-select";
// import makeAnimated from "react-select/animated";
// import { Textarea } from "@/components/ui/textarea";
// import {
// Dialog,
// DialogContent,
// DialogFooter,
// DialogHeader,
// DialogTitle,
// } from "@/components/ui/dialog";
// import dynamic from "next/dynamic";
// const CustomEditor = dynamic(
// () => {
// return import("@/components/editor/custom-editor");
// },
// { ssr: false }
// );
// const animatedComponent = makeAnimated();
// const FormSchema = z.object({
// title: z.string({
// required_error: "Required",
// }),
// url: z.string({
// required_error: "Required",
// }),
// thumbnail: z.string({
// required_error: "Required",
// }),
// detail: z.string({
// required_error: "Required",
// }),
// selected: z
// .array(
// z.object({
// id: z.number(),
// label: z.string(),
// value: z.string(),
// })
// )
// .refine((value) => value.length > 0, {
// message: "Required",
// }),
// });
// interface Campaign {
// id: string;
// name: string;
// }
// export default function ContentBlast(props: { type: string }) {
// const editor = useRef(null);
// const id = useParams()?.id;
// const MySwal = withReactContent(Swal);
// const router = useRouter();
// const { type } = props;
// const [dataSelectCampaign, setDataSelectCampaign] = useState<Campaign[]>([]);
// const [openModal, setOpenModal] = useState(false);
// const form = useForm<z.infer<typeof FormSchema>>({
// resolver: zodResolver(FormSchema),
// defaultValues: { selected: [], detail: "" },
// });
// const onSubmit = async (data: z.infer<typeof FormSchema>) => {
// if (form.getValues("detail") == "") {
// form.setError("detail", {
// type: "manual",
// message: "Required",
// });
// } else {
// 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 save = async (data: z.infer<typeof FormSchema>) => {
// const selectedCampaign = form.getValues("selected");
// for (let i = 0; i < selectedCampaign.length; i++) {
// const reqData = {
// mediaUploadId: id,
// mediaBlastCampaignId: selectedCampaign[i].id,
// subject: type == "wa" ? `*${data.title}*` : data.title,
// body: data.detail?.replace(/\n/g, ""),
// type: type,
// isScheduled: false,
// thumbnail: data?.thumbnail,
// sendDate: getLocaleTimestamp(new Date()),
// sendTime: getLocaleTime(new Date()),
// contentUrl: data.url,
// };
// console.log("req =>", reqData);
// const response = await saveMediaBlastBroadcast(reqData);
// }
// setOpenModal(true);
// };
// useEffect(() => {
// async function initState() {
// const response = await detailMediaSummary(String(id));
// const details = response?.data?.data;
// let pageUrl = details?.pageUrl || "";
// if (pageUrl.includes("mediahub.polri.go.id")) {
// pageUrl = pageUrl.replace(
// /(\.id)(\/|$)/,
// (match: any, p1: any, p2: any) => {
// return p2.startsWith("/in") ? match : `${p1}/in${p2}`;
// }
// );
// }
// if (details != undefined) {
// form.setValue("thumbnail", details.smallThumbnailLink);
// let body = `<div><p>Berita hari ini !!!</p>
// <div style='margin-top:20px;border:1px solid;border-radius:10px;width:500px;background-color:#f7f7f7'>
// <div>
// <img style='width:500px;height:auto;border-radius:10px;object-fit:cover' src='${
// details?.smallThumbnailLink
// }'>
// </div>
// <a style='padding:5px 20px;margin:0;text-decoration:none' href='${pageUrl}'>${pageUrl}</a>
// <h3 style='padding:5px 20px;margin:0'>${details?.title}</h3>
// <p style='padding:0 20px;margin:0;margin-bottom:10px'>
// ${textEllipsis(details?.description, 150)}
// </p>
// </div>
// </div>`;
// form.setValue("title", `${details?.title}`);
// form.setValue(
// "url",
// details?.pageUrl || "https://mediahub.polri.go.id"
// );
// if (type == "wa") {
// body = `${textEllipsis(details?.description, 150)}`;
// form.setValue("detail", body);
// } else {
// form.setValue("detail", body);
// }
// }
// }
// async function getCampaign() {
// const response = await getMediaBlastCampaignList();
// const campaign = response?.data?.data?.content;
// handleLabelCampaign(campaign);
// console.log(campaign);
// }
// initState();
// getCampaign();
// }, [id]);
// function handleLabelCampaign(data: any) {
// const optionArr: any = [];
// data.map((option: any) => {
// optionArr.push({
// id: option.id,
// label: option.title,
// value: option.title,
// });
// });
// console.log("option arr", optionArr);
// setDataSelectCampaign(optionArr);
// }
// return (
// <Form {...form}>
// <form
// onSubmit={form.handleSubmit(onSubmit)}
// className="space-y-3 bg-white rounded-sm p-4"
// >
// <p className="fonnt-semibold">Broadcast</p>
// <FormField
// control={form.control}
// name="selected"
// render={({ field }) => (
// <FormItem>
// <FormLabel>Subject</FormLabel>
// <Select
// className="z-50"
// options={dataSelectCampaign}
// closeMenuOnSelect={false}
// components={animatedComponent}
// onChange={field.onChange}
// isMulti
// />
// <FormMessage />
// </FormItem>
// )}
// />
// <FormField
// control={form.control}
// name="title"
// render={({ field }) => (
// <FormItem>
// <FormLabel>Subject</FormLabel>
// <Input
// value={field.value}
// placeholder="Masukkan Judul"
// onChange={field.onChange}
// />
// <FormMessage />
// </FormItem>
// )}
// />
// <FormField
// control={form.control}
// name="detail"
// render={({ field }) => (
// <FormItem>
// <FormLabel>Detail Perencanaan</FormLabel>
// {type === "wa" ? (
// <Textarea value={field.value} onChange={field.onChange} />
// ) : (
// <CustomEditor
// onChange={field.onChange}
// initialData={field.value}
// />
// )}
// <FormMessage />
// </FormItem>
// )}
// />
// <div className="flex flex-row gap-2 mt-4 pt-4">
// <Button
// size="md"
// type="button"
// variant="outline"
// color="destructive"
// className="text-xs"
// >
// Cancel
// </Button>
// <Button size="md" type="submit" color="primary" className="text-xs">
// Submit
// </Button>
// </div>
// <Dialog open={openModal}>
// <DialogContent>
// <DialogHeader>
// <DialogTitle>Terkirim !!</DialogTitle>
// </DialogHeader>
// <div className="flex flex-col justify-center items-center gap-3 mb-3 text-sm">
// <img
// src="/assets/img/illust-for-broadcast-sent.png"
// className="w-[70%]"
// />
// Untuk melihat Email Terkirim silahkan cek menu “Sent”!
// </div>
// <DialogFooter className="flex justify-center">
// {/* <Link
// href={`/admin/broadcast/campaign-list/detail/${
// form.getValues("selected")[0]?.id
// }`}
// >
// <Button type="button" color="success">
// Menu "Sent"
// </Button>
// </Link> */}
// <Button
// type="button"
// onClick={() => router.push("/admin/broadcast")}
// color="primary"
// >
// Okay
// </Button>
// </DialogFooter>
// </DialogContent>
// </Dialog>
// </form>
// </Form>
// );
// }