feat:update modal survey,fix ui

This commit is contained in:
Anang Yusman 2025-04-08 00:37:19 +08:00
parent da8fde5499
commit fea54bf883
19 changed files with 1181 additions and 260 deletions

View File

@ -581,7 +581,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
{roleId == 3 || roleId == 11 || roleId == 2 || roleId == 12 ? (
<Button
onClick={handleDateClick}
className="dark:bg-background dark:text-foreground w-[250px]"
className="dark:bg-background dark:text-foreground w-full"
>
<Plus className="w-4 h-4 me-1" />
{t("addEvent")}
@ -593,7 +593,7 @@ const CalendarView = ({ categories }: CalendarViewProps) => {
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
{roleId === 3 && userLevelId === 216 ? (
<Button className="dark:bg-background dark:text-foreground w-[250px]">
<Button className="dark:bg-background dark:text-foreground w-full">
<Book className="w-4 h-4" />
{t("bag-pa-monitoring-results")}
</Button>

View File

@ -775,7 +775,7 @@ const EventModal = ({
checked={wilayahPublish.semua}
onCheckedChange={() => toggleWilayah("semua")}
/>
<label htmlFor="semua" className="ml-2">
<label htmlFor="semua" className="ml-2 text-sm">
Semua
</label>
</div>
@ -785,7 +785,7 @@ const EventModal = ({
checked={wilayahPublish.nasional}
onCheckedChange={() => toggleWilayah("nasional")}
/>
<label htmlFor="nasional" className="ml-2">
<label htmlFor="nasional" className="ml-2 text-sm mr-2">
Nasional
</label>
</div>
@ -795,7 +795,7 @@ const EventModal = ({
checked={wilayahPublish.polda}
onCheckedChange={() => toggleWilayah("polda")}
/>
<label htmlFor="polda" className="mx-2">
<label htmlFor="polda" className="mx-2 text-sm mr-2">
Polda
</label>
{wilayahPublish.polda && (
@ -814,7 +814,7 @@ const EventModal = ({
checked={wilayahPublish.polres}
onCheckedChange={() => toggleWilayah("polres")}
/>
<label htmlFor="polres" className="ml-2">
<label htmlFor="polres" className="ml-2 text-sm mr-2">
Polres
</label>
{wilayahPublish.polres && (
@ -833,7 +833,7 @@ const EventModal = ({
checked={wilayahPublish.satker}
onCheckedChange={() => toggleWilayah("satker")}
/>
<label htmlFor="satker" className="mx-2">
<label htmlFor="satker" className="mx-2 text-sm mr-2">
Satker
</label>
{wilayahPublish.satker && (
@ -852,7 +852,10 @@ const EventModal = ({
checked={wilayahPublish.international}
onCheckedChange={() => toggleWilayah("international")}
/>
<label htmlFor="international" className="ml-2">
<label
htmlFor="international"
className="ml-2 text-sm mr-2"
>
Internasional
</label>
</div>

View File

@ -263,7 +263,7 @@ const TableAudio = () => {
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size="md" variant="outline">
1 - {showData} Data
{showData} Data
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56 text-sm">
@ -272,16 +272,16 @@ const TableAudio = () => {
onValueChange={setShowData}
>
<DropdownMenuRadioItem value="10">
1 - 10 Data
10 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="50">
1 - 50 Data
50 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="100">
1 - 100 Data
100 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="250">
1 - 250 Data
250 Data
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>

View File

@ -83,7 +83,7 @@ const TableImage = () => {
const [columnVisibility, setColumnVisibility] =
React.useState<VisibilityState>({});
const [rowSelection, setRowSelection] = React.useState({});
const [showData, setShowData] = React.useState("50");
const [showData, setShowData] = React.useState("10");
const [pagination, setPagination] = React.useState<PaginationState>({
pageIndex: 0,
pageSize: Number(showData),
@ -268,7 +268,7 @@ const TableImage = () => {
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size="md" variant="outline">
1 - {showData} Data
{showData} Data
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56 text-sm">
@ -277,16 +277,16 @@ const TableImage = () => {
onValueChange={setShowData}
>
<DropdownMenuRadioItem value="10">
1 - 10 Data
10 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="50">
1 - 50 Data
50 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="100">
1 - 100 Data
100 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="250">
1 - 250 Data
250 Data
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>

View File

@ -262,7 +262,7 @@ const TableTeks = () => {
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size="md" variant="outline">
1 - {showData} Data
{showData} Data
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56 text-sm">
@ -271,16 +271,16 @@ const TableTeks = () => {
onValueChange={setShowData}
>
<DropdownMenuRadioItem value="10">
1 - 10 Data
10 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="50">
1 - 50 Data
50 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="100">
1 - 100 Data
100 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="250">
1 - 250 Data
250 Data
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>

View File

@ -264,7 +264,7 @@ const TableVideo = () => {
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button size="md" variant="outline">
1 - {showData} Data
{showData} Data
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56 text-sm">
@ -273,16 +273,16 @@ const TableVideo = () => {
onValueChange={setShowData}
>
<DropdownMenuRadioItem value="10">
1 - 10 Data
10 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="50">
1 - 50 Data
50 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="100">
1 - 100 Data
100 Data
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="250">
1 - 250 Data
250 Data
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</DropdownMenuContent>

View File

@ -266,7 +266,6 @@ const PressReleaseTable = () => {
totalPage={totalPage}
/>
</div>
\{" "}
</div>
);
};

View File

@ -107,7 +107,7 @@ const DashboardPage = () => {
<Card>
<CardHeader className="flex flex-row items-center">
<CardTitle className="flex-1">{t("tabel")}</CardTitle>
<DashboardDropdown />
{/* <DashboardDropdown /> */}
</CardHeader>
<CardContent className="p-0">
<ContentTable />

View File

@ -626,15 +626,15 @@ const DetailInfo = () => {
onClick={() => doBookmark()}
className="flex flex-col mb-3 items-center justify-center cursor-pointer"
>
<Icon icon="material-symbols:bookmark-outline" width={40} />
<p className="text-base lg:text-lg">{t("save")}</p>
<Icon icon="material-symbols:bookmark-outline" width={25} />
<p className="text-base lg:text-sm">{t("save")}</p>
</a>
)}
{/* garis */}
<div className="border-t border-black my-4"></div>
<div className="flex flex-col justify-center items-center gap-3">
<div className="w-auto">
<div className="w-auto mb-3">
<Link
href={`/all/filter?title=polda&category=${detailDataImage?.category.id}`}
className="bg-red-600 text-white text-xs font-bold px-3 py-3 my-3 rounded w-auto"
@ -648,7 +648,7 @@ const DetailInfo = () => {
<a
onClick={() => router.push(`/all/filter?tag=${tag}`)}
key={tag}
className="bg-gray-200 text-gray-700 text-xs px-3 py-1 rounded-full cursor-pointer hover:bg-gray-500"
className="bg-gray-200 text-gray-700 text-xs px-3 py-3 font-semibold rounded-full cursor-pointer hover:bg-gray-500"
>
{tag}
</a>

View File

@ -2,9 +2,22 @@
import { Textarea } from "@/components/ui/textarea";
import { useParams, usePathname, useSearchParams } from "next/navigation";
import React, { useEffect, useState } from "react";
import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious } from "@/components/ui/carousel";
import {
Carousel,
CarouselContent,
CarouselItem,
CarouselNext,
CarouselPrevious,
} from "@/components/ui/carousel";
import { Link, useRouter } from "@/i18n/routing";
import { deleteBlogComments, getBlogComments, getDetailIndeks, getPublicSuggestionList, postBlogComments, publicDetailBlog } from "@/service/landing/landing";
import {
deleteBlogComments,
getBlogComments,
getDetailIndeks,
getPublicSuggestionList,
postBlogComments,
publicDetailBlog,
} from "@/service/landing/landing";
import { formatDateToIndonesian } from "@/utils/globals";
import { Icon } from "@iconify/react/dist/iconify.js";
import { getCookiesDecrypt } from "@/lib/utils";
@ -94,7 +107,9 @@ const IndeksDetail = () => {
// }
async function sendCommentChild(parentId: any) {
const inputMsg = document.querySelector(`#input-comment-${parentId}`) as HTMLInputElement;
const inputMsg = document.querySelector(
`#input-comment-${parentId}`
) as HTMLInputElement;
if (inputMsg && inputMsg.value.length > 3) {
loading();
@ -166,32 +181,54 @@ const IndeksDetail = () => {
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
</svg>`;
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
const toBase64 = (str: string) =>
typeof window === "undefined"
? Buffer.from(str).toString("base64")
: window.btoa(str);
return (
<>
<div className="p-4 lg:px-60 lg:p-12">
<div className="p-4 lg:px-28 lg:p-12">
{/* Judul */}
<div className="flex flex-col mb-5">
<h1 className="text-base lg:text-lg mb-2">Index / Detail</h1>
<h1 className="flex flex-row font-bold text-center text-lg lg:text-2xl">{indeksData?.title}</h1>
<h1 className="flex flex-row font-bold text-center text-lg lg:text-2xl">
{indeksData?.title}
</h1>
</div>
{/* Gambar Utama */}
<div className="flex items-center justify-center">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={2560} height={1440} src={indeksData?.thumbnailLink} alt="Main" className="h-fit lg:h-[550px] w-full rounded-lg" />
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
width={2560}
height={1440}
src={indeksData?.thumbnailLink}
alt="Main"
className="w-full max-h-[550px] object-contain rounded-xl "
/>
</div>
{/* Footer Informasi */}
<div className="text-gray-500 flex border-t mt-4">
<div className="flex mt-2">
<p className="text-xs lg:text-sm mb-2 ">
{t("by")}&nbsp;<span className="font-semibold text-gray-500">{indeksData?.uploaderName}</span>&nbsp; | &nbsp;{t("updatedOn")} {indeksData?.createdAt} WIB &nbsp;
{t("by")}&nbsp;
<span className="font-semibold text-gray-500">
{indeksData?.uploaderName}
</span>
&nbsp; | &nbsp;{t("updatedOn")} {indeksData?.createdAt} WIB &nbsp;
</p>
</div>
</div>
{/* Keterangan */}
<div className="w-auto">
<p className="font-light text-base lg:text-lg text-justify" dangerouslySetInnerHTML={{ __html: indeksData?.description }} />
<p
className="font-light text-base lg:text-lg text-justify"
dangerouslySetInnerHTML={{ __html: indeksData?.description }}
/>
</div>
</div>
@ -199,9 +236,19 @@ const IndeksDetail = () => {
<div className="w-full">
<div className="flex flex-col py-5 p-0 lg:p-10 bg-[#f7f7f7] dark:bg-slate-600">
<div className="gap-5 flex flex-col px-4 lg:px-16">
<p className="flex items-start text-bases lg:text-lg">{t("comment")}</p>
<Textarea placeholder="Type your comments here." className="flex w-full" onChange={getInputValue} value={message} />
<button className="flex items-start bg-[#bb3523] text-white rounded-lg text-sm lg:text-base w-fit px-3 lg:px-4 py-1" onClick={() => postData()}>
<p className="flex items-start text-bases lg:text-lg">
{t("comment")}
</p>
<Textarea
placeholder="Type your comments here."
className="flex w-full"
onChange={getInputValue}
value={message}
/>
<button
className="flex items-start bg-[#bb3523] text-white rounded-lg text-sm lg:text-base w-fit px-3 lg:px-4 py-1"
onClick={() => postData()}
>
{t("send")}
</button>
</div>
@ -212,15 +259,40 @@ const IndeksDetail = () => {
{listComments?.map((data: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:px-14">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={512} height={512} className="h-10 lg:h-20 w-10 lg:w-20" src="/assets/img/user-avatar-yellow.svg" alt="#" />
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
width={512}
height={512}
className="h-10 lg:h-20 w-10 lg:w-20"
src="/assets/img/user-avatar-yellow.svg"
alt="#"
/>
<div className="border border-slate-300 w-full p-4 bg-white gap-1">
<p className="flex justify-between text-sm text-slate-500 lg:text-base border-b-2 border-slate-200 mb-2">
<b>{Number(data.commentFrom?.roleId) == 2 || Number(data.commentFrom?.roleId) == 3 || Number(data.commentFrom?.roleId) == 4 ? "HUMAS POLRI" : data.commentFrom?.fullname}</b>
{`${new Date(data.createdAt).getDate()}/${new Date(data.createdAt).getMonth() + 1}/${new Date(data.createdAt).getFullYear()} ${new Date(data.createdAt).getHours()}:${new Date(data.createdAt).getMinutes()}`}
<b>
{Number(data.commentFrom?.roleId) == 2 ||
Number(data.commentFrom?.roleId) == 3 ||
Number(data.commentFrom?.roleId) == 4
? "HUMAS POLRI"
: data.commentFrom?.fullname}
</b>
{`${new Date(data.createdAt).getDate()}/${
new Date(data.createdAt).getMonth() + 1
}/${new Date(data.createdAt).getFullYear()} ${new Date(
data.createdAt
).getHours()}:${new Date(data.createdAt).getMinutes()}`}
</p>
<p className="text-slate-500 text-sm lg:text-base mb-4">
{data.message}
</p>
<p className="text-slate-500 text-sm lg:text-base mb-4">{data.message}</p>
<div className="gap-3">
<a href="javascript:void(0)" className="text-xs lg:text-sm mr-2 bg-blue-500 text-white py-1 px-2 hover:bg-blue-300 hover:text-black rounded-md" onClick={() => showInput(`comment-id-${data.id}`)}>
<a
href="javascript:void(0)"
className="text-xs lg:text-sm mr-2 bg-blue-500 text-white py-1 px-2 hover:bg-blue-300 hover:text-black rounded-md"
onClick={() => showInput(`comment-id-${data.id}`)}
>
{t("reply")}
</a>
<a
@ -240,9 +312,21 @@ const IndeksDetail = () => {
</div>
</div>
</div>
<div className="flex flex-row px-4 pl-[55px] lg:px-14 lg:pl-[135px] mt-2" id={`comment-id-${data.id}`}>
<Input type="text" id={`input-comment-${data.id}`} className="p-4 focus:outline-none focus:border-sky-500" placeholder={t("enterReply")} />
<a href="javascript:void(0)" className="flex py-1 px-2 rounded-md items-center ml-2 bg-[#f7b357] text-white text-sm lg:text-base" onClick={() => postDataChild(data.id)}>
<div
className="flex flex-row px-4 pl-[55px] lg:px-14 lg:pl-[135px] mt-2"
id={`comment-id-${data.id}`}
>
<Input
type="text"
id={`input-comment-${data.id}`}
className="p-4 focus:outline-none focus:border-sky-500"
placeholder={t("enterReply")}
/>
<a
href="javascript:void(0)"
className="flex py-1 px-2 rounded-md items-center ml-2 bg-[#f7b357] text-white text-sm lg:text-base"
onClick={() => postDataChild(data.id)}
>
{t("send")}
</a>
</div>
@ -250,24 +334,54 @@ const IndeksDetail = () => {
? data.children?.map((child1: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-12 lg:pl-32">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={512} height={512} className="h-10 lg:h-20 w-10 lg:w-20" src="/assets/img/user-avatar-yellow.svg" alt="#" />
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
width={512}
height={512}
className="h-10 lg:h-20 w-10 lg:w-20"
src="/assets/img/user-avatar-yellow.svg"
alt="#"
/>
<div className="border border-slate-300 w-full p-4 bg-white gap-1">
<p className="flex justify-between text-slate-500 text-sm lg:text-base border-b-2 border-slate-200 mb-2">
<b>{Number(child1.commentFrom?.roleId) == 2 || Number(child1.commentFrom?.roleId) == 3 || Number(child1.commentFrom?.roleId) == 4 ? "HUMAS POLRI" : child1.commentFrom?.fullname}</b>
{`${new Date(child1.createdAt).getDate()}/${new Date(child1.createdAt).getMonth() + 1}/${new Date(child1.createdAt).getFullYear()} ${new Date(child1.createdAt).getHours()}:${new Date(
<b>
{Number(child1.commentFrom?.roleId) == 2 ||
Number(child1.commentFrom?.roleId) == 3 ||
Number(child1.commentFrom?.roleId) == 4
? "HUMAS POLRI"
: child1.commentFrom?.fullname}
</b>
{`${new Date(child1.createdAt).getDate()}/${
new Date(child1.createdAt).getMonth() + 1
}/${new Date(
child1.createdAt
).getFullYear()} ${new Date(
child1.createdAt
).getHours()}:${new Date(
child1.createdAt
).getMinutes()}`}
</p>
<p className="text-slate-500 text-sm mb-4">{child1.message}</p>
<p className="text-slate-500 text-sm mb-4">
{child1.message}
</p>
<div className="gap-3">
<a href="javascript:void(0)" className="mr-2 text-xs lg:text-sm bg-blue-500 text-white py-1 px-2 hover:bg-blue-300 hover:text-black rounded-md" onClick={() => showInput(`comment-id-${child1.id}`)}>
<a
href="javascript:void(0)"
className="mr-2 text-xs lg:text-sm bg-blue-500 text-white py-1 px-2 hover:bg-blue-300 hover:text-black rounded-md"
onClick={() =>
showInput(`comment-id-${child1.id}`)
}
>
{t("reply")}
</a>
<a
href="javascript:void(0)"
className="text-xs lg:text-sm bg-red-500 text-white py-1 px-2 hover:bg-red-300 hover:text-black rounded-md"
style={
Number(child1.commentFrom?.id) == Number(userId)
Number(child1.commentFrom?.id) ==
Number(userId)
? {}
: {
display: "none",
@ -280,9 +394,21 @@ const IndeksDetail = () => {
</div>
</div>
</div>
<div className="flex flex-row justify-center px-4 pl-[87px] lg:px-14 lg:pl-[205px] mt-2" id={`comment-id-${child1.id}`}>
<Input type="text" id={`input-comment-${child1.id}`} className="p-4 focus:outline-none focus:border-sky-500" placeholder={t("enterReply")} />
<a href="javascript:void(0)" className="flex text-sm lg:text-base py-1 px-2 rounded-md items-center ml-2 bg-[#f7b357] text-white" onClick={() => postDataChild(child1.id)}>
<div
className="flex flex-row justify-center px-4 pl-[87px] lg:px-14 lg:pl-[205px] mt-2"
id={`comment-id-${child1.id}`}
>
<Input
type="text"
id={`input-comment-${child1.id}`}
className="p-4 focus:outline-none focus:border-sky-500"
placeholder={t("enterReply")}
/>
<a
href="javascript:void(0)"
className="flex text-sm lg:text-base py-1 px-2 rounded-md items-center ml-2 bg-[#f7b357] text-white"
onClick={() => postDataChild(child1.id)}
>
{t("send")}
</a>
</div>
@ -290,24 +416,59 @@ const IndeksDetail = () => {
? child1.children?.map((child2: any) => (
<div className="flex flex-col">
<div className="flex flex-row mt-2 px-4 lg:pr-14 pl-20 lg:pl-48">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={512} height={512} className="h-10 lg:h-20 w-10 lg:w-20" src="/assets/img/user-avatar-yellow.svg" alt="#" />
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
width={512}
height={512}
className="h-10 lg:h-20 w-10 lg:w-20"
src="/assets/img/user-avatar-yellow.svg"
alt="#"
/>
<div className="border border-slate-300 w-full p-4 bg-white gap-2">
<p className="flex justify-between text-slate-500 text-xs lg:text-base border-b-2 border-slate-200 mb-2">
<b>{Number(child2.commentFrom?.roleId) == 2 || Number(child2.commentFrom?.roleId) == 3 || Number(child2.commentFrom?.roleId) == 4 ? "HUMAS POLRI" : child2.commentFrom?.fullname}</b>
{`${new Date(child2.createdAt).getDate()}/${new Date(child2.createdAt).getMonth() + 1}/${new Date(child2.createdAt).getFullYear()} ${new Date(child2.createdAt).getHours()}:${new Date(
<b>
{Number(child2.commentFrom?.roleId) ==
2 ||
Number(child2.commentFrom?.roleId) ==
3 ||
Number(child2.commentFrom?.roleId) == 4
? "HUMAS POLRI"
: child2.commentFrom?.fullname}
</b>
{`${new Date(
child2.createdAt
).getDate()}/${
new Date(child2.createdAt).getMonth() +
1
}/${new Date(
child2.createdAt
).getFullYear()} ${new Date(
child2.createdAt
).getHours()}:${new Date(
child2.createdAt
).getMinutes()}`}
</p>
<p className="text-slate-500 text-sm mb-4">{child2.message}</p>
<p className="text-slate-500 text-sm mb-4">
{child2.message}
</p>
<div>
<a href="javascript:void(0)" className="mr-2 text-xs lg:text-sm bg-blue-500 text-white py-1 px-2 hover:bg-blue-300 hover:text-black rounded-md" onClick={() => showInput("comment-id-" + child2.id)}>
<a
href="javascript:void(0)"
className="mr-2 text-xs lg:text-sm bg-blue-500 text-white py-1 px-2 hover:bg-blue-300 hover:text-black rounded-md"
onClick={() =>
showInput("comment-id-" + child2.id)
}
>
{t("reply")}
</a>
<a
href="javascript:void(0)"
className="text-xs lg:text-sm bg-red-500 text-white py-1 px-2 hover:bg-red-300 hover:text-black rounded-md"
style={
Number(child2.commentFrom?.id) == Number(userId)
Number(child2.commentFrom?.id) ==
Number(userId)
? {}
: {
display: "none",
@ -320,9 +481,21 @@ const IndeksDetail = () => {
</div>
</div>
</div>
<div className="flex flex-row px-4 pl-[120px] lg:px-14 lg:pl-[270px] mt-2" id={`comment-id-${child2.id}`}>
<Input type="text" id={`comment-id-${child2.id}`} className="p-4 focus:outline-none focus:border-sky-500" placeholder={t("enterReply")} />
<a href="javascript:void(0)" className="flex text-sm lg:text-base py-1 px-2 rounded-md items-center ml-2 bg-[#f7b357] text-white" onClick={() => postDataChild(child1.id)}>
<div
className="flex flex-row px-4 pl-[120px] lg:px-14 lg:pl-[270px] mt-2"
id={`comment-id-${child2.id}`}
>
<Input
type="text"
id={`comment-id-${child2.id}`}
className="p-4 focus:outline-none focus:border-sky-500"
placeholder={t("enterReply")}
/>
<a
href="javascript:void(0)"
className="flex text-sm lg:text-base py-1 px-2 rounded-md items-center ml-2 bg-[#f7b357] text-white"
onClick={() => postDataChild(child1.id)}
>
{t("send")}
</a>
</div>
@ -339,14 +512,25 @@ const IndeksDetail = () => {
{/* Konten Serupa */}
<div className="space-x-5 flex flex-col px-4 lg:px-16 py-16 gap-5">
<h1 className="font-bold text-base lg:text-xl px-4 lg:px-8"> {t("relatedPosts")}</h1>
<h1 className="font-bold text-base lg:text-xl px-4 lg:px-8">
{" "}
{t("relatedPosts")}
</h1>
<Carousel>
<CarouselContent className="w-full max-w-7xl">
{indexData?.map((relate: any) => (
<CarouselItem key={relate?.id} className="md:basis-1/2 lg:basis-1/3">
<Link href={`/indeks/detail/${relate?.slug}`} className="relative group overflow-hidden shadow-md hover:shadow-lg">
<CarouselItem
key={relate?.id}
className="md:basis-1/2 lg:basis-1/3"
>
<Link
href={`/indeks/detail/${relate?.slug}`}
className="relative group overflow-hidden shadow-md hover:shadow-lg"
>
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`}
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
alt=""
width={2560}
height={1440}
@ -354,10 +538,17 @@ const IndeksDetail = () => {
className="w-full rounded-lg h-40 lg:h-60 object-cover group-hover:scale-100 transition-transform duration-300"
/>
<div className="absolute bottom-0 left-0 right-0 bg-gray-600 border-l-4 border-[#bb3523] rounded-lg backdrop-blur-sm text-white p-2">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-sm px-4 py-1">{relate?.categoryName}</span>
<h1 className="text-sm lg:text-lg mb-2 font-semibold h-5 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible">{relate?.title}</h1>
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-sm px-4 py-1">
{relate?.categoryName}
</span>
<h1 className="text-sm lg:text-lg mb-2 font-semibold h-5 hover:h-auto truncate hover:whitespace-normal hover:overflow-visible">
{relate?.title}
</h1>
<p className="flex flex-row items-center text-[10px] gap-2">
{formatDateToIndonesian(new Date(relate?.createdAt))} {relate?.timezone ? relate?.timezone : "WIB"} | <Icon icon="formkit:eye" width="15" height="15" /> {relate.clickCount}{" "}
{formatDateToIndonesian(new Date(relate?.createdAt))}{" "}
{relate?.timezone ? relate?.timezone : "WIB"} |{" "}
<Icon icon="formkit:eye" width="15" height="15" />{" "}
{relate.clickCount}{" "}
</p>
</div>
</Link>

View File

@ -3,7 +3,7 @@
import { Skeleton } from "@/components/ui/skeleton";
import { Link } from "@/i18n/routing";
import { getIndeksData } from "@/service/landing/landing";
import { formatDateToIndonesian } from "@/utils/globals";
import { formatDateToIndonesian, htmlToString } from "@/utils/globals";
import Image from "next/image";
import { usePathname } from "next/navigation";
import React, { useEffect, useState } from "react";
@ -54,8 +54,10 @@ const Indeks: React.FC = () => {
<animate xlink:href="#r" attributeName="x" from="-${w}" to="${w}" dur="1s" repeatCount="indefinite" />
</svg>`;
const toBase64 = (str: string) => (typeof window === "undefined" ? Buffer.from(str).toString("base64") : window.btoa(str));
const toBase64 = (str: string) =>
typeof window === "undefined"
? Buffer.from(str).toString("base64")
: window.btoa(str);
return (
<div className="px-4 lg:px-14">
@ -70,22 +72,44 @@ const Indeks: React.FC = () => {
{indeksData?.map(
(indeks: any, index: number) =>
index == count && (
<div key={indeks?.id} className="relative h-[310px] lg:h-[435px]">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={2560} height={1440} src={indeks?.thumbnailLink} alt="image" className="w-full h-[310px] lg:h-[435px] rounded-lg object-cover" />
<div className="absolute bottom-0 left-0 right-0 bg-transparent backdrop-blur-sm text-white p-4 rounded-b-lg">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-xs px-2 py-1">{indeks?.categoryName}</span>
<div
key={indeks?.id}
className="relative h-[310px] lg:h-[435px]"
>
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
width={2560}
height={1440}
src={indeks?.thumbnailLink}
alt="image"
className="w-full h-[310px] lg:h-[435px] rounded-lg object-cover"
/>
<div className="absolute bottom-0 left-0 right-0 bg-black/15 backdrop-brightness-50 text-white p-4 rounded-b-lg">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-xs px-2 py-1">
{indeks?.categoryName}
</span>
<Link href={`/indeks/detail/${indeks?.slug}`}>
<h2 className="text-2xl font-bold mt-2">{indeks?.title}</h2>
<h2 className="text-2xl font-bold mt-2">
{indeks?.title}
</h2>
</Link>
<p className="text-xs flex flex-row items-center gap-1 mt-1">
{formatDateToIndonesian(new Date(indeks?.createdAt))} {indeks?.timezone ? indeks?.timezone : "WIB"} |{" "}
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24">
{formatDateToIndonesian(new Date(indeks?.createdAt))}{" "}
{indeks?.timezone ? indeks?.timezone : "WIB"} |{" "}
{/* <svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
/>
</svg>{" "}
{indeks?.clickCount}
</svg>{" "} */}
{/* {indeks?.clickCount} */}
</p>
</div>
</div>
@ -108,22 +132,49 @@ const Indeks: React.FC = () => {
{indeksData?.map(
(indeksRight: any, index: number) =>
(index == count + 1 || index == count + 2) && (
<div key={indeksRight?.id} className="relative h-[310px] lg:h-[215px]">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={1920} height={1080} src={indeksRight?.thumbnailLink} alt="image" className="w-full h-[310px] lg:h-[215px] rounded-lg " />
<div className="absolute bottom-0 left-0 right-0 bg-transparent backdrop-blur-sm text-white p-4 rounded-b-lg">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-xs px-2 py-1">{indeksRight?.categoryName}</span>
<div
key={indeksRight?.id}
className="relative h-[310px] lg:h-[215px]"
>
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
width={1920}
height={1080}
src={indeksRight?.thumbnailLink}
alt="image"
className="w-full h-[310px] lg:h-[215px] rounded-lg "
/>
<div className="absolute bottom-0 left-0 right-0 bg-black/15 backdrop-brightness-50 text-white p-4 rounded-b-lg">
<span className="text-white bg-[#bb3523] rounded-md w-full h-full font-semibold uppercase text-xs px-2 py-1">
{indeksRight?.categoryName}
</span>
<Link href={`/indeks/detail/${indeksRight?.slug}`}>
<h2 className="text-xl font-bold mt-2">{indeksRight?.title}</h2>
<h2 className="text-xl font-bold mt-2">
{indeksRight?.title}
</h2>
</Link>
<p className="text-xs flex flex-row items-center gap-1 mt-1 ml-2">
{formatDateToIndonesian(new Date(indeksRight?.createdAt))} {indeksRight?.timezone ? indeksRight?.timezone : "WIB"}|{" "}
<svg xmlns="http://www.w3.org/2000/svg" width="1.2em" height="1.2em" viewBox="0 0 24 24">
{formatDateToIndonesian(
new Date(indeksRight?.createdAt)
)}{" "}
{indeksRight?.timezone
? indeksRight?.timezone
: "WIB"}
|{" "}
{/* <svg
xmlns="http://www.w3.org/2000/svg"
width="1.2em"
height="1.2em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M11.5 18c4 0 7.46-2.22 9.24-5.5C18.96 9.22 15.5 7 11.5 7s-7.46 2.22-9.24 5.5C4.04 15.78 7.5 18 11.5 18m0-12c4.56 0 8.5 2.65 10.36 6.5C20 16.35 16.06 19 11.5 19S3 16.35 1.14 12.5C3 8.65 6.94 6 11.5 6m0 2C14 8 16 10 16 12.5S14 17 11.5 17S7 15 7 12.5S9 8 11.5 8m0 1A3.5 3.5 0 0 0 8 12.5a3.5 3.5 0 0 0 3.5 3.5a3.5 3.5 0 0 0 3.5-3.5A3.5 3.5 0 0 0 11.5 9"
/>
</svg>{" "}
{indeksRight?.clickCount}
{indeksRight?.clickCount} */}
</p>
</div>
</div>
@ -165,14 +216,31 @@ const Indeks: React.FC = () => {
{indeksData?.map(
(indeksBottom: any, index: number) =>
index < 3 && (
<div key={indeksBottom?.id} className="flex flex-col md:flex-row items-start p-4 gap-4">
<Image placeholder={`data:image/svg+xml;base64,${toBase64(shimmer(700, 475))}`} width={2560} height={1440} src={indeksBottom?.thumbnailLink} alt="" className="h-40 object-cover rounded-lg w-full lg:w-full lg:h-[300px]" />
<div
key={indeksBottom?.id}
className="flex flex-col md:flex-row items-start p-4 gap-4"
>
<Image
placeholder={`data:image/svg+xml;base64,${toBase64(
shimmer(700, 475)
)}`}
width={500}
height={250}
src={indeksBottom?.thumbnailLink}
alt=""
className="h-40 object-cover rounded-lg w-full lg:w-[550px] lg:h-[200px]"
/>
<div className="flex flex-col justify-between w-full">
<p className="text-sm">{indeksBottom?.date}</p>
<Link href={`/indeks/detail/${indeksBottom?.slug}`} className="text-2xl font-semibold text-gray-800 dark:text-white">
<Link
href={`/indeks/detail/${indeksBottom?.slug}`}
className="text-2xl font-semibold text-gray-800 dark:text-white"
>
{indeksBottom?.title}
</Link>
<p className="text-sm text-gray-600 dark:text-white mt-2">{indeksBottom?.description}</p>
<p className="text-sm text-gray-600 dark:text-white mt-2">
{htmlToString(indeksBottom?.description)}
</p>
</div>
</div>
)

View File

@ -1,18 +1,50 @@
"use client";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { Popover, PopoverArrow, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import {
Popover,
PopoverArrow,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { CalendarIcon } from "lucide-react";
import React, { useEffect, useState } from "react";
import { format } from "date-fns";
import { cn } from "@/lib/utils";
import { Checkbox } from "@/components/ui/checkbox";
import { Icon } from "@iconify/react/dist/iconify.js";
import { detailSchedule, listSchedule, listScheduleNextPublic, listSchedulePrevPublic, listScheduleTodayPublic, searchSchedules } from "@/service/schedule/schedule";
import {
detailSchedule,
listSchedule,
listScheduleNextPublic,
listSchedulePrevPublic,
listScheduleTodayPublic,
searchSchedules,
} from "@/service/schedule/schedule";
import { usePathname, useRouter } from "@/i18n/routing";
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from "@/components/ui/alert-dialog";
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@/components/ui/accordion";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog";
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion";
import { close, loading } from "@/config/swal";
import { useTranslations } from "next-intl";
import { Input } from "@/components/ui/input";
@ -292,13 +324,21 @@ const Schedule = (props: any) => {
function getLastWeek(today: Date | undefined) {
if (today) {
return new Date(today.getFullYear(), today.getMonth(), today.getDate() - 7);
return new Date(
today.getFullYear(),
today.getMonth(),
today.getDate() - 7
);
}
}
function getNextWeek(today: Date | undefined) {
if (today) {
return new Date(today.getFullYear(), today.getMonth(), today.getDate() + 7);
return new Date(
today.getFullYear(),
today.getMonth(),
today.getDate() + 7
);
}
}
@ -423,13 +463,22 @@ const Schedule = (props: any) => {
};
function setItemSchedule(id: string, date: string) {
const itemFound: any = schedules?.filter((s: any) => s.dateInRange.includes(date) && s.timeIndex.split(",").includes(id));
const itemFound: any = schedules?.filter(
(s: any) =>
s.dateInRange.includes(date) && s.timeIndex.split(",").includes(id)
);
if (itemFound?.length > 0) {
if (itemFound?.length == 1) {
return (
<a
className={`cursor-pointer text-center ${Number(itemFound[0]?.uploaderLevelNumber) == 1 ? "bg-yellow-300" : Number(itemFound[0]?.uploaderLevelNumber) == 2 ? "bg-blue-400" : "bg-gray-500"}`}
className={`cursor-pointer text-center ${
Number(itemFound[0]?.uploaderLevelNumber) == 1
? "bg-yellow-300"
: Number(itemFound[0]?.uploaderLevelNumber) == 2
? "bg-blue-400"
: "bg-gray-500"
}`}
onClick={() => {
getItem(itemFound[0]);
}}
@ -452,7 +501,9 @@ const Schedule = (props: any) => {
<b>{`${itemFound?.length} Jadwal Bersamaan`}</b>
</p>
<DropdownMenu>
<DropdownMenuTrigger className="font-bold text-blue-300">Lihat Jadwal</DropdownMenuTrigger>
<DropdownMenuTrigger className="font-bold text-blue-300">
Lihat Jadwal
</DropdownMenuTrigger>
<DropdownMenuContent>
{itemFound?.map((list: any) => (
<DropdownMenuItem
@ -471,7 +522,10 @@ const Schedule = (props: any) => {
))}
</DropdownMenuContent>
</DropdownMenu>
<div className="border-0 dropdown-menu schedule-list" aria-labelledby="view-schedule"></div>
<div
className="border-0 dropdown-menu schedule-list"
aria-labelledby="view-schedule"
></div>
</div>
);
}
@ -480,73 +534,121 @@ const Schedule = (props: any) => {
return (
<>
{/* Awal Komponen Kiri */}
<div className="relative px-4 lg:px-10 lg:py-10 py-4 bg-[#f7f7f7] dark:bg-slate-800">
<Popover>
<PopoverTrigger asChild>
<Button variant={"outline"} className={cn("w-[240px] py-4 justify-start text-left font-normal", !startDate && "text-muted-foreground")}>
<CalendarIcon />
{startDate ? format(startDate, "MMM yyyy") : <span>Pick a date</span>}
</Button>
</PopoverTrigger>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={startDate}
onSelect={(e) => {
handleChangeDate(e);
}}
initialFocus
/>
</PopoverContent>
</Popover>
<div className="container relative py-4">
<div className="relative pl-4 lg:px-8 lg:py-10 py-4 bg-[#f7f7f7] dark:bg-slate-800">
<div className="flex flex-row items-center">
<Popover>
<PopoverTrigger asChild>
<a className="text-black dark:text-white flex flex-row w-fit gap-2 py-4 items-center cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="currentColor" d="M20 3H4a1 1 0 0 0-1 1v2.227l.008.223a3 3 0 0 0 .772 1.795L8 12.886V21a1 1 0 0 0 1.316.949l6-2l.108-.043A1 1 0 0 0 16 19v-6.586l4.121-4.12A3 3 0 0 0 21 6.171V4a1 1 0 0 0-1-1" />
</svg>
Filter
<svg className="flex items-center justify-center" xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<path fill="currentColor" fill-rule="evenodd" d="m6 7l6 6l6-6l2 2l-8 8l-8-8z" />
</svg>
</a>
<Button
variant={"outline"}
className={cn(
"w-[240px] py-3 justify-start text-left font-normal",
!startDate && "text-muted-foreground"
)}
>
<CalendarIcon />
{startDate ? (
format(startDate, "MMM yyyy")
) : (
<span>Pick a date</span>
)}
</Button>
</PopoverTrigger>
<PopoverContent align="start" className="flex p-0 rounded-md w-fit">
<div className="flex flex-col items-center justify-between gap-1.5 p-2 border-b text-default-600 rounded-none">
<div className="gap-6 flex flex-row justify-end">
<p className="font-semibold">Filter</p>
<button className="text-blue-400" onClick={doFilter}>
{t("save")}
</button>
</div>
<div className="border w-full border-t border-slate-500"></div>
<div className="overflow-y-auto flex flex-col gap-2 h-[200px] ">
<p className="text-center font-semibold">Region Filter</p>
{city?.map((list) => (
<div className="mt-2 gap-2 flex flex-row">
{" "}
<input type="checkbox" className="" id={`filterCategory-${list.key}`} value={list.id} checked={regionFilter?.includes(list.id)} onChange={handleRegionFilter} />
<p>{list?.name}</p>
</div>
))}
</div>
</div>
<PopoverContent className="w-auto p-0" align="start">
<Calendar
mode="single"
selected={startDate}
onSelect={(e) => {
handleChangeDate(e);
}}
initialFocus
/>
</PopoverContent>
</Popover>
<div className="flex flex-col lg:flex-row gap-3">
{regionName?.map((list: any) => (
<div className="text-left">
<button onClick={() => deleteFilterhandler(list.id)} key={list.key} id={list.id} className="text-black bg-yellow-300 w-fit p-3 flex justify-center items-center rounded-lg">
{list.name}&nbsp;
<Icon icon="icon-park-outline:delete-two" className="items-center" />
</button>
</div>
))}
<div className="container relative py-4 flex flex-row items-center gap-4">
<Popover>
<PopoverTrigger asChild>
<a className="text-black dark:text-white flex flex-row w-fit gap-3 py-2 px-3 items-center cursor-pointer border border-black rounded-md ">
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M20 3H4a1 1 0 0 0-1 1v2.227l.008.223a3 3 0 0 0 .772 1.795L8 12.886V21a1 1 0 0 0 1.316.949l6-2l.108-.043A1 1 0 0 0 16 19v-6.586l4.121-4.12A3 3 0 0 0 21 6.171V4a1 1 0 0 0-1-1"
/>
</svg>
Filter
<svg
className="flex items-center justify-center"
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
fill-rule="evenodd"
d="m6 7l6 6l6-6l2 2l-8 8l-8-8z"
/>
</svg>
</a>
</PopoverTrigger>
<PopoverContent
align="start"
className="flex p-0 rounded-md w-fit"
>
<div className="flex flex-col items-center justify-between gap-1.5 p-2 border-b text-default-600 rounded-none">
<div className="gap-6 flex flex-row justify-end">
<p className="font-semibold">Filter</p>
<button className="text-blue-400" onClick={doFilter}>
{t("save")}
</button>
</div>
<div className="border w-full border-t border-slate-500"></div>
<div className="overflow-y-auto flex flex-col gap-2 h-[200px] ">
<p className="text-center font-semibold">Region Filter</p>
{city?.map((list) => (
<div className="mt-2 gap-2 flex flex-row">
{" "}
<input
type="checkbox"
className=""
id={`filterCategory-${list.key}`}
value={list.id}
checked={regionFilter?.includes(list.id)}
onChange={handleRegionFilter}
/>
<p>{list?.name}</p>
</div>
))}
</div>
</div>
</PopoverContent>
</Popover>
<div className="flex flex-col lg:flex-row gap-3">
{regionName?.map((list: any) => (
<div className="text-left">
<button
onClick={() => deleteFilterhandler(list.id)}
key={list.key}
id={list.id}
className="text-black bg-yellow-300 w-fit p-3 flex justify-center items-center rounded-lg"
>
{list.name}&nbsp;
<Icon
icon="icon-park-outline:delete-two"
className="items-center"
/>
</button>
</div>
))}
</div>
</div>
</div>
<div className="flex flex-col lg:flex-row gap-6">
<div className="flex flex-col lg:flex-row gap-1">
<div className="h-[500px] overflow-y-auto md:overflow-y-auto w-full lg:w-3/4 ">
<div className="container-fluid relative">
<div className="grid grid-cols-1 mt-8">
@ -554,53 +656,125 @@ const Schedule = (props: any) => {
<table className="w-full text-sm text-start">
<thead className="text-md">
<tr className="h-full">
<th className="text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[120px]">{t("timeTable")}</th>
<th className="text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[210px]">
{t("timeTable")}
</th>
<th className="text-center border border-r-0 border-gray-100 dark:border-gray-700 py-6 w-[20px]">
<a onClick={() => changePrevWeek()} className="cursor-pointer h-fit self-center bottom-0">
<svg xmlns="http://www.w3.org/2000/svg" width="40px" height="40px" viewBox="0 0 24 24">
<path fill="currentColor" d="M12.29 8.71L9.7 11.3a.996.996 0 0 0 0 1.41l2.59 2.59c.63.63 1.71.18 1.71-.71V9.41c0-.89-1.08-1.33-1.71-.7" />
<a
onClick={() => changePrevWeek()}
className="cursor-pointer h-fit self-center bottom-0"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="40px"
height="40px"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="M12.29 8.71L9.7 11.3a.996.996 0 0 0 0 1.41l2.59 2.59c.63.63 1.71.18 1.71-.71V9.41c0-.89-1.08-1.33-1.71-.7"
/>
</svg>
</a>
</th>
<th className={`text-center cursor-pointer border border-l-0 h-full border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${new Date().toISOString().slice(0, 10) == dateAWeek[0] ? "bg-red-600 text-white" : ""}`}>
<th
className={`text-center cursor-pointer border border-l-0 h-full border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${
new Date().toISOString().slice(0, 10) ==
dateAWeek[0]
? "bg-red-600 text-white"
: ""
}`}
>
{/* <a className="cursor-pointer h-fit self-center bottom-0" >
<svg xmlns="http://www.w3.org/2000/svg" width="24px" height="24px" viewBox="0 0 24 24">
<path fill="currentColor" d="M12.29 8.71L9.7 11.3a.996.996 0 0 0 0 1.41l2.59 2.59c.63.63 1.71.18 1.71-.71V9.41c0-.89-1.08-1.33-1.71-.7" />
</svg>
</a>{" "} */}
<div className="flex flex-col ">
<p className="text-2xl">{dateAWeek[0]?.split("-")[2]}</p>
<p className="text-2xl">
{dateAWeek[0]?.split("-")[2]}
</p>
<p>{t("monday")}</p>
</div>
</th>
<th className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${new Date().toISOString().slice(0, 10) == dateAWeek[1] ? "bg-[#BE0106] text-white rounded-lg" : ""}`}>
<div className="text-2xl">{dateAWeek[1]?.split("-")[2]}</div>
<th
className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${
new Date().toISOString().slice(0, 10) ==
dateAWeek[1]
? "bg-[#BE0106] text-white rounded-lg"
: ""
}`}
>
<div className="text-2xl">
{dateAWeek[1]?.split("-")[2]}
</div>
{t("tuesday")}
</th>
<th className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${new Date().toISOString().slice(0, 10) == dateAWeek[2] ? "bg-[#BE0106] text-white rounded-lg" : ""}`}>
<div className="text-2xl">{dateAWeek[2]?.split("-")[2]}</div>
<th
className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${
new Date().toISOString().slice(0, 10) ==
dateAWeek[2]
? "bg-[#BE0106] text-white rounded-lg"
: ""
}`}
>
<div className="text-2xl">
{dateAWeek[2]?.split("-")[2]}
</div>
{t("wednesday")}
</th>
<th className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${new Date().toISOString().slice(0, 10) == dateAWeek[3] ? "bg-[#BE0106] text-white rounded-lg" : ""}`}>
<div className="text-2xl">{dateAWeek[3]?.split("-")[2]}</div>
<th
className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${
new Date().toISOString().slice(0, 10) ==
dateAWeek[3]
? "bg-[#BE0106] text-white rounded-lg"
: ""
}`}
>
<div className="text-2xl">
{dateAWeek[3]?.split("-")[2]}
</div>
{t("thursday")}
</th>
<th className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${new Date().toISOString().slice(0, 10) == dateAWeek[4] ? "bg-[#BE0106] text-white rounded-lg" : ""}`}>
<div className="text-2xl">{dateAWeek[4]?.split("-")[2]}</div>
<th
className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${
new Date().toISOString().slice(0, 10) ==
dateAWeek[4]
? "bg-[#BE0106] text-white rounded-lg"
: ""
}`}
>
<div className="text-2xl">
{dateAWeek[4]?.split("-")[2]}
</div>
{t("friday")}
</th>
<th className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${new Date().toISOString().slice(0, 10) == dateAWeek[5] ? "bg-[#BE0106] text-white rounded-lg" : ""}`}>
<div className="text-2xl">{dateAWeek[5]?.split("-")[2]}</div>
<th
className={`text-center border border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${
new Date().toISOString().slice(0, 10) ==
dateAWeek[5]
? "bg-[#BE0106] text-white rounded-lg"
: ""
}`}
>
<div className="text-2xl">
{dateAWeek[5]?.split("-")[2]}
</div>
{t("saturday")}
</th>
<th
onClick={() => changeNextWeek()}
className={`text-center border cursor-pointer border-r-0 border-gray-100 dark:border-gray-700 py-6 min-w-[100px] ${
new Date().toISOString().slice(0, 10) == dateAWeek[6] ? "bg-[#BE0106] text-white rounded-lg" : ""
new Date().toISOString().slice(0, 10) ==
dateAWeek[6]
? "bg-[#BE0106] text-white rounded-lg"
: ""
}`}
>
<div className="flex flex-col ">
<p className="text-2xl">{dateAWeek[6]?.split("-")[2]}</p>
<p className="text-2xl">
{dateAWeek[6]?.split("-")[2]}
</p>
<p>{t("sunday")}</p>
</div>
{/* <a className="cursor-pointer h-fit p-0 m-0 self-center">
@ -610,9 +784,20 @@ const Schedule = (props: any) => {
</a> */}
</th>
<th className="text-center border-l-0 border border-gray-100 dark:border-gray-700 py-6 w-[20px]">
<a onClick={() => changeNextWeek()} className="cursor-pointer">
<svg xmlns="http://www.w3.org/2000/svg" width="40px" height="40px" viewBox="0 0 24 24">
<path fill="currentColor" d="m11.71 15.29l2.59-2.59a.996.996 0 0 0 0-1.41L11.71 8.7c-.63-.62-1.71-.18-1.71.71v5.17c0 .9 1.08 1.34 1.71.71" />
<a
onClick={() => changeNextWeek()}
className="cursor-pointer"
>
<svg
xmlns="http://www.w3.org/2000/svg"
width="40px"
height="40px"
viewBox="0 0 24 24"
>
<path
fill="currentColor"
d="m11.71 15.29l2.59-2.59a.996.996 0 0 0 0-1.41L11.71 8.7c-.63-.62-1.71-.18-1.71.71v5.17c0 .9 1.08 1.34 1.71.71"
/>
</svg>
</a>
</th>
@ -621,16 +806,34 @@ const Schedule = (props: any) => {
<tbody>
{timeList.map((times) => (
<tr key={times.id}>
<th className="text-center border border-gray-100 dark:border-gray-700 py-5">{times.time}</th>
<td colSpan={2} className="p-3 border border-gray-100 dark:border-gray-700 ">
<th className="text-center border border-gray-100 dark:border-gray-700 py-5">
{times.time}
</th>
<td
colSpan={2}
className="p-3 border border-gray-100 dark:border-gray-700 "
>
{setItemSchedule(times.id, dateList[0])}
</td>
<td className="border border-gray-100 dark:border-gray-700">{setItemSchedule(times.id, dateList[1])}</td>
<td className="border border-gray-100 dark:border-gray-700">{setItemSchedule(times.id, dateList[2])}</td>
<td className="border border-gray-100 dark:border-gray-700">{setItemSchedule(times.id, dateList[3])}</td>
<td className="p-3 border border-gray-100 dark:border-gray-700">{setItemSchedule(times.id, dateList[4])}</td>
<td className="border border-gray-100 dark:border-gray-700">{setItemSchedule(times.id, dateList[5])}</td>
<td colSpan={2} className="border border-gray-100 dark:border-gray-700">
<td className="border border-gray-100 dark:border-gray-700">
{setItemSchedule(times.id, dateList[1])}
</td>
<td className="border border-gray-100 dark:border-gray-700">
{setItemSchedule(times.id, dateList[2])}
</td>
<td className="border border-gray-100 dark:border-gray-700">
{setItemSchedule(times.id, dateList[3])}
</td>
<td className="p-3 border border-gray-100 dark:border-gray-700">
{setItemSchedule(times.id, dateList[4])}
</td>
<td className="border border-gray-100 dark:border-gray-700">
{setItemSchedule(times.id, dateList[5])}
</td>
<td
colSpan={2}
className="border border-gray-100 dark:border-gray-700"
>
{setItemSchedule(times.id, dateList[6])}
</td>
</tr>
@ -654,10 +857,18 @@ const Schedule = (props: any) => {
className="pl-8 pr-4 py-1 w-full border rounded-full text-sm focus:outline-none"
/>
<span className="absolute left-2 top-1/2 transform -translate-y-1/2">
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 24 24">
<svg
xmlns="http://www.w3.org/2000/svg"
width="1em"
height="1em"
viewBox="0 0 24 24"
>
<g fill="none" fill-rule="evenodd">
<path d="m12.593 23.258l-.011.002l-.071.035l-.02.004l-.014-.004l-.071-.035q-.016-.005-.024.005l-.004.01l-.017.428l.005.02l.01.013l.104.074l.015.004l.012-.004l.104-.074l.012-.016l.004-.017l-.017-.427q-.004-.016-.017-.018m.265-.113l-.013.002l-.185.093l-.01.01l-.003.011l.018.43l.005.012l.008.007l.201.093q.019.005.029-.008l.004-.014l-.034-.614q-.005-.018-.02-.022m-.715.002a.02.02 0 0 0-.027.006l-.006.014l-.034.614q.001.018.017.024l.015-.002l.201-.093l.01-.008l.004-.011l.017-.43l-.003-.012l-.01-.01z" />
<path fill="currentColor" d="M10.5 2a8.5 8.5 0 1 0 5.262 15.176l3.652 3.652a1 1 0 0 0 1.414-1.414l-3.652-3.652A8.5 8.5 0 0 0 10.5 2M4 10.5a6.5 6.5 0 1 1 13 0a6.5 6.5 0 0 1-13 0" />
<path
fill="currentColor"
d="M10.5 2a8.5 8.5 0 1 0 5.262 15.176l3.652 3.652a1 1 0 0 0 1.414-1.414l-3.652-3.652A8.5 8.5 0 0 0 10.5 2M4 10.5a6.5 6.5 0 1 1 13 0a6.5 6.5 0 0 1-13 0"
/>
</g>
</svg>
</span>
@ -700,8 +911,13 @@ const Schedule = (props: any) => {
<AccordionItem value="item-1">
<AccordionTrigger>{t("todaySchedule")}</AccordionTrigger>
{todayList?.map((list: any) => (
<AccordionContent key={list?.id} className="flex flex-row gap-3">
<div className="border-l-4 border-red-700 pl-1 h-fit font-bold text-lg">{new Date(list.startDate).getDate()}</div>
<AccordionContent
key={list?.id}
className="flex flex-row gap-3"
>
<div className="border-l-4 border-red-700 pl-1 h-fit font-bold text-lg">
{new Date(list.startDate).getDate()}
</div>
<div className="flex flex-col gap-2">
<h3 className="font-bold">{list?.title}</h3>
<p className="flex flex-row items-center gap-2">
@ -725,8 +941,13 @@ const Schedule = (props: any) => {
<AccordionItem value="item-2">
<AccordionTrigger>{t("previousSchedule")}</AccordionTrigger>
{prevdayList?.map((list: any) => (
<AccordionContent key={list?.id} className="flex flex-row gap-3">
<div className="border-l-4 border-red-700 pl-1 h-fit font-bold text-lg">{new Date(list.startDate).getDate()}</div>
<AccordionContent
key={list?.id}
className="flex flex-row gap-3"
>
<div className="border-l-4 border-red-700 pl-1 h-fit font-bold text-lg">
{new Date(list.startDate).getDate()}
</div>
<div className="flex flex-col gap-2">
<h3 className="font-bold">{list?.title}</h3>
<p className="flex flex-row items-center gap-2">
@ -750,8 +971,13 @@ const Schedule = (props: any) => {
<AccordionItem value="item-3">
<AccordionTrigger>{t("nextSchedule")}</AccordionTrigger>
{nextdayList?.map((list: any) => (
<AccordionContent key={list?.id} className="flex flex-row gap-3">
<div className="border-l-4 border-red-700 pl-1 h-fit font-bold text-lg">{new Date(list.startDate).getDate()}</div>
<AccordionContent
key={list?.id}
className="flex flex-row gap-3"
>
<div className="border-l-4 border-red-700 pl-1 h-fit font-bold text-lg">
{new Date(list.startDate).getDate()}
</div>
<div className="flex flex-col gap-2">
<h3 className="font-bold">{list?.title}</h3>
<p className="flex flex-row items-center gap-2">
@ -846,13 +1072,17 @@ const Schedule = (props: any) => {
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>
<h1 className="my-4 font-light">JADWAL / {detail?.isYoutube == true ? "LIVE STREAMING" : "DETAIL"}</h1>
<h1 className="my-4 font-light">
JADWAL /{" "}
{detail?.isYoutube == true ? "LIVE STREAMING" : "DETAIL"}
</h1>
<p className="font-bold">{detail?.title}</p>
</AlertDialogTitle>
<AlertDialogDescription>
<p className="flex flex-row items-center gap-2">
<Icon icon="iconamoon:clock-thin" />
{detail?.date} {detail?.startTime} - {detail?.endTime} {detail?.timezone ? detail.timezone : "WIB"}
{detail?.date} {detail?.startTime} - {detail?.endTime}{" "}
{detail?.timezone ? detail.timezone : "WIB"}
</p>
</AlertDialogDescription>
<AlertDialogDescription>

View File

@ -27,6 +27,16 @@ import {
import { Label } from "../ui/label";
import { Input } from "../ui/input";
import { Button } from "../ui/button";
import { Textarea } from "../ui/textarea";
import { Checkbox } from "../ui/checkbox";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "../ui/dialog";
const HeroModal = ({ onClose }: { onClose: () => void }) => {
const [heroData, setHeroData] = useState<any>();
@ -85,7 +95,7 @@ const HeroModal = ({ onClose }: { onClose: () => void }) => {
className="w-full h-[310px] lg:h-[420px] rounded-lg object-cover"
/>
<div className="absolute bottom-0 left-0 right-0 bg-black/30 backdrop-blur-sm text-white pb-4 px-4 pt-8 rounded-bl-2xl rounded-tr-2xl mx-3 mb-2">
<div className="absolute bottom-0 left-0 right-0 bg-black/30 backdrop-brightness-50 text-white pb-4 px-4 pt-8 rounded-bl-2xl rounded-tr-2xl mx-3 mb-2">
<div className="absolute top-0 left-0 bottom-0 w-2 bg-[#bb3523] rounded-bl-lg"></div>
<span className="absolute top-0 left-0 mt-2 mb-3 mx-3 bg-[#bb3523] text-white text-xs font-semibold uppercase px-2 py-1 rounded">
{list?.categoryName || "Liputan Kegiatan"}
@ -125,6 +135,223 @@ const HeroModal = ({ onClose }: { onClose: () => void }) => {
);
};
const SurveyIntroModal = ({ onNext }: { onNext: () => void }) => {
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50">
<div className="relative bg-white rounded-xl p-6 w-[90%] max-w-md text-center">
<button
onClick={onNext}
className="absolute top-3 right-3 text-gray-500 hover:text-black"
>
</button>
<Image
src="/assets/survey.jpg"
alt="Survey Illustration"
width={300}
height={200}
className="mx-auto my-4"
/>
<button
onClick={onNext}
className="mt-4 bg-red-600 hover:bg-red-700 text-white font-semibold py-3 px-6 rounded w-full"
>
Lihat Selengkapnya
</button>
</div>
</div>
);
};
const options = {
q1: [
"Setiap hari",
"Beberapa kali seminggu",
"Beberapa kali dalam sebulan",
"Baru pertama kali",
],
q2a: ["Sangat baik", "Baik", "Cukup", "Kurang", "Buruk"],
q2b: ["Sangat mudah", "Mudah", "Cukup", "Sulit", "Sangat sulit"],
q2c: ["Sangat cepat", "Cepat", "Cukup", "Lambat", "Sangat lambat"],
q3a: ["Sangat puas", "Puas", "Cukup", "Kurang puas", "Tidak puas"],
q3b: [
"Sangat lengkap",
"Lengkap",
"Cukup",
"Kurang lengkap",
"Tidak lengkap",
],
q4: [
"Sangat membantu",
"Membantu",
"Cukup membantu",
"Kurang membantu",
"Tidak membantu",
],
};
const SurveyFormModal = ({ onClose }: { onClose: () => void }) => {
return (
<Dialog
open
onOpenChange={(open) => {
if (!open) onClose();
}}
>
<DialogContent className="w-[400px] h-[600px] overflow-y-auto">
<DialogHeader>
<DialogTitle className="text-lg font-bold">
SURVEI KEPUASAN PENGGUNA MEDIAHUB POLRI
</DialogTitle>
<DialogDescription className="text-sm">
Kami menghargai pendapat Anda! Survei ini bertujuan untuk
meningkatkan kualitas layanan MediaHub Polri. Mohon luangkan waktu
beberapa menit untuk mengisi survei ini.
</DialogDescription>
</DialogHeader>
<div className="space-y-4 mt-4">
{/* 1 */}
<div>
<p className="font-medium">
1. Seberapa sering Anda mengakses MediaHub Polri?
</p>
<div className="grid grid-cols-2 gap-2 mt-2">
{options.q1.map((item, i) => (
<label key={i} className="flex items-center space-x-2">
<Checkbox id={`q1-${i}`} />
<span>{item}</span>
</label>
))}
</div>
</div>
{/* 2 */}
<div>
<p className="font-medium">
2. Bagaimana pengalaman Anda dalam mengakses website ini?
</p>
<div className="mt-2 space-y-3">
<div>
<p className="text-sm font-medium">
a) Tampilan dan desain website
</p>
<div className="grid grid-cols-3 gap-2 mt-1">
{options.q2a.map((item, i) => (
<label key={i} className="flex items-center space-x-2">
<Checkbox id={`q2a-${i}`} />
<span>{item}</span>
</label>
))}
</div>
</div>
<div>
<p className="text-sm font-medium">
b) Kemudahan navigasi (pencarian informasi, menu, dll)
</p>
<div className="grid grid-cols-3 gap-2 mt-1">
{options.q2b.map((item, i) => (
<label key={i} className="flex items-center space-x-2">
<Checkbox id={`q2b-${i}`} />
<span>{item}</span>
</label>
))}
</div>
</div>
<div>
<p className="text-sm font-medium">
c) Kecepatan akses website
</p>
<div className="grid grid-cols-3 gap-2 mt-1">
{options.q2c.map((item, i) => (
<label key={i} className="flex items-center space-x-2">
<Checkbox id={`q2c-${i}`} />
<span>{item}</span>
</label>
))}
</div>
</div>
</div>
</div>
{/* 3 */}
<div>
<p className="font-medium">
3. Seberapa puas Anda dengan informasi yang tersedia di MediaHub
Polri?
</p>
<div className="mt-2 space-y-3">
<div>
<p className="text-sm font-medium">a) Akurat dan terpercaya</p>
<div className="grid grid-cols-3 gap-2 mt-1">
{options.q3a.map((item, i) => (
<label key={i} className="flex items-center space-x-2">
<Checkbox id={`q3a-${i}`} />
<span>{item}</span>
</label>
))}
</div>
</div>
<div>
<p className="text-sm font-medium">
b) Kelengkapan berita dan informasi
</p>
<div className="grid grid-cols-3 gap-2 mt-1">
{options.q3b.map((item, i) => (
<label key={i} className="flex items-center space-x-2">
<Checkbox id={`q3b-${i}`} />
<span>{item}</span>
</label>
))}
</div>
</div>
</div>
</div>
{/* 4 */}
<div>
<p className="font-medium">
5. Apakah Anda merasa website ini membantu dalam mendapatkan
informasi terkait Polri?
</p>
<div className="grid grid-cols-2 gap-2 mt-2">
{options.q4.map((item, i) => (
<label key={i} className="flex items-center space-x-2">
<Checkbox id={`q4-${i}`} />
<span>{item}</span>
</label>
))}
</div>
</div>
{/* 5 */}
<div>
<p className="font-medium">
6. Apa saran atau masukan Anda untuk meningkatkan layanan MediaHub
Polri?
</p>
<Textarea placeholder="Tulis pesan Anda" />
</div>
</div>
<div className="flex justify-end gap-2 mt-6">
<DialogClose asChild>
<Button variant="outline">Batal</Button>
</DialogClose>
<Button>Kirim</Button>
</div>
</DialogContent>
</Dialog>
);
};
const ONE_HOUR = 60 * 60 * 1000;
const Hero: React.FC = () => {
const router = useRouter();
const pathname = usePathname();
@ -133,6 +360,8 @@ const Hero: React.FC = () => {
const [isLoading, setIsLoading] = useState<any>(true);
const [heroData, setHeroData] = useState<any>();
const [showModal, setShowModal] = useState(false);
const [showSurveyModal, setShowSurveyModal] = useState(false);
const [showFormModal, setShowFormModal] = useState(false);
useEffect(() => {
const timer = setTimeout(() => {
@ -145,11 +374,25 @@ const Hero: React.FC = () => {
useEffect(() => {
const roleId = Cookies.get("urie");
if (!roleId) {
setShowModal(true); // hanya munculkan modal jika urie tidak ada
setShowModal(true);
}
initFetch();
}, []);
useEffect(() => {
const roleId = Cookies.get("urie");
const lastShown = Cookies.get("surveyLastShown");
const now = new Date().getTime();
if (roleId && (!lastShown || now - parseInt(lastShown) > ONE_HOUR)) {
setShowSurveyModal(true);
Cookies.set("surveyLastShown", now.toString(), { expires: 1 });
}
initFetch();
}, []);
useEffect(() => {
async function fetchCategories() {
const url = "https://netidhub.com/api/csrf";
@ -201,6 +444,18 @@ const Hero: React.FC = () => {
<div className="flex flex-col lg:flex-row items-start justify-center gap-8 px-4 lg:px-20 py-4 mx-auto w-auto mt-6">
<div className="relative">
{showModal && <HeroModal onClose={() => setShowModal(false)} />}
{showSurveyModal && !showFormModal && (
<SurveyIntroModal
onNext={() => {
setShowSurveyModal(false);
setShowFormModal(true);
}}
/>
)}
{showFormModal && (
<SurveyFormModal onClose={() => setShowFormModal(false)} />
)}
</div>
{isLoading ? (
<div className="flex flex-col space-y-3 mx-auto w-full lg:w-2/3">
@ -227,7 +482,7 @@ const Hero: React.FC = () => {
className="w-full h-[310px] lg:h-[420px] rounded-lg object-cover"
/>
<div className="absolute bottom-0 left-0 right-0 bg-black/30 backdrop-blur-sm text-white pb-4 px-4 pt-8 rounded-bl-2xl rounded-tr-2xl mx-3 mb-2">
<div className="absolute bottom-0 left-0 right-0 bg-black/30 backdrop-brightness-50 text-white pb-4 px-4 pt-8 rounded-bl-2xl rounded-tr-2xl mx-3 mb-2">
<div className="absolute top-0 left-0 bottom-0 w-2 bg-[#bb3523] rounded-bl-lg"></div>
<span className="absolute top-0 left-0 mt-2 mb-3 mx-3 bg-[#bb3523] text-white text-xs font-semibold uppercase px-2 py-1 rounded">
{list?.categoryName || "Liputan Kegiatan"}

View File

@ -11,7 +11,13 @@ import { zodResolver } from "@hookform/resolvers/zod";
import { z } from "zod";
import { cn, setCookiesEncrypt } from "@/lib/utils";
import { Loader2 } from "lucide-react";
import { getProfile, login, requestOTP } from "@/service/auth";
import {
getProfile,
login,
postEmailValidation,
postSetupEmail,
requestOTP,
} from "@/service/auth";
import { toast } from "sonner";
import { useRouter } from "@/components/navigation";
import { warning } from "@/lib/swal";
@ -45,16 +51,28 @@ const LoginForm = () => {
const [passwordType, setPasswordType] = React.useState("password");
const t = useTranslations("LandingPage");
const [isOtpStep, setIsOtpStep] = useState(false);
const [step, setStep] = useState<number>(1);
const [otpValue, setOtpValue] = useState("");
const [userIdentity] = useState();
const [email, setEmail] = useState();
const [category, setCategory] = useState("5");
const handleSignInClick = () => {
handleSendOTP();
setIsOtpStep(true);
};
// const handleSignInClick = () => {
// handleSendOTP();
// setIsOtpStep(true);
// };
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [oldEmail, setOldEmail] = useState("");
const [oldEmailValidate, setOldEmailValidate] = useState("");
const [newEmail, setNewEmail] = useState("");
const [newEmailValidate, setNewEmailValidate] = useState("");
// const handleSignInClick = () => {
// handleSendOTP();
// setIsOtpStep(true);
// };
const [otp1, setOtp1] = useState();
const [otp2, setOtp2] = useState();
@ -259,9 +277,57 @@ const LoginForm = () => {
// });
};
const handleEmailValidation = async () => {
const data = {
username: username,
password: password,
};
loading();
const response = await postEmailValidation(data);
close();
if (response.error) {
error(response.message);
return false;
}
const msg = response.data?.message;
if (msg == "Continue to setup email") {
setStep(2);
} else if (msg == "Email is valid and OTP has been sent") {
setStep(3);
} else if (msg == "Username & password valid") {
onSubmit(data);
} else {
error("Username / password incorrect");
}
};
const handleSetupEmail = async () => {
const data = {
username: username,
password: password,
oldEmail: oldEmail,
newEmail: newEmail,
};
loading();
const response = await postSetupEmail(data);
close();
if (response.error) {
error(response.message);
return false;
}
const msg = response.data?.message;
if (msg == "Email is valid and OTP has been sent") {
setStep(3);
} else if (msg == "The old email is not same") {
error("Email is invalid");
}
};
return (
<form onSubmit={handleSubmit(onSubmit)} className="mt-5 2xl:mt-7 space-y-4">
{!isOtpStep && (
{step === 1 ? (
<>
<div className="text-left 2xl:mb-10 mb-4 mt-10">
<h4 className="font-semibold text-3xl text-left">
@ -324,13 +390,75 @@ const LoginForm = () => {
{t("forgotPass")}
</Link>
</div>
<Button fullWidth onClick={handleSignInClick}>
<Button
type="submit"
fullWidth
onClick={handleEmailValidation}
disabled={isPending}
>
Selanjutnya
</Button>
</>
)}
{isOtpStep && (
) : step === 2 ? (
<>
<div className="text-left 2xl:mb-10 mb-4">
<h4 className="font-semibold text-3xl text-left">
Anda perlu memasukkan email baru untuk bisa Login.
</h4>
</div>
<div className="flex flex-col justify-center mb-6">
<div className="space-y-2">
<Label
htmlFor="username"
className="font-medium text-default-600"
>
Email Lama <span className="text-red-500">*</span>
</Label>
<Input
size="lg"
disabled={isPending}
onChange={(e) => setOldEmail(e.target.value)}
id="oldEmail"
type="email"
className={cn("", {
"border-destructive": errors.username,
})}
/>
{errors.username?.message && (
<div className="text-destructive mt-2 text-sm">
{errors.username.message}
</div>
)}
</div>
<div className="space-y-2">
<Label
htmlFor="username"
className="font-medium text-default-600"
>
Email Baru <span className="text-red-500">*</span>
</Label>
<Input
size="lg"
disabled={isPending}
onChange={(e) => setNewEmail(e.target.value)}
id="newEmail"
type="email"
className={cn("", {
"border-destructive": errors.username,
})}
/>
{errors.username?.message && (
<div className="text-destructive mt-2 text-sm">
{errors.username.message}
</div>
)}
</div>
</div>
<Button fullWidth className="bg-red-500">
Sign in
</Button>
</>
) : (
<>
<div className="text-left 2xl:mb-10 mb-4 mt-10">
<h4 className="font-semibold text-3xl text-left">

View File

@ -292,34 +292,34 @@ export function getMenuList(pathname: string, t: any): Group[] {
icon: "heroicons:arrow-trending-up",
children: [],
},
{
href: "/admin/settings/feedback",
label: "Feedback",
active: pathname === "/admin/settings/feedback",
icon: "heroicons:arrow-trending-up",
children: [],
},
{
href: "/admin/settings/faq",
label: "FAQ",
active: pathname === "/admin/settings/faq",
icon: "heroicons:arrow-trending-up",
children: [],
},
{
href: "https://nat-mediahub.polri.go.id/",
label: "Mediahub 2022",
active: pathname === "/admin/settings/mediahub-2022",
icon: "heroicons:arrow-trending-up",
children: [],
},
{
href: "/admin/settings/privacy",
label: t("privacy"),
active: pathname === "/admin/settings/privacy",
icon: "heroicons:arrow-trending-up",
children: [],
},
// {
// href: "/admin/settings/feedback",
// label: "Feedback",
// active: pathname === "/admin/settings/feedback",
// icon: "heroicons:arrow-trending-up",
// children: [],
// },
// {
// href: "/admin/settings/faq",
// label: "FAQ",
// active: pathname === "/admin/settings/faq",
// icon: "heroicons:arrow-trending-up",
// children: [],
// },
// {
// href: "https://nat-mediahub.polri.go.id/",
// label: "Mediahub 2022",
// active: pathname === "/admin/settings/mediahub-2022",
// icon: "heroicons:arrow-trending-up",
// children: [],
// },
// {
// href: "/admin/settings/privacy",
// label: t("privacy"),
// active: pathname === "/admin/settings/privacy",
// icon: "heroicons:arrow-trending-up",
// children: [],
// },
],
},
],

BIN
public/assets/survey.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 133 KiB

View File

@ -1,7 +1,12 @@
import qs from "qs";
import { getAPIDummy } from "./http-config/axiosCustom";
import { httpGet, httpPost } from "./http-config/http-base-service";
import { httpGetInterceptor, httpGetInterceptorWithToken, httpPostInterceptor } from "./http-config/http-interceptor-service";
import {
httpGetInterceptor,
httpGetInterceptorWithToken,
httpPostInterceptor,
postAPIWithJson,
} from "./http-config/http-interceptor-service";
export async function login(data: any) {
const pathUrl = "signin";
@ -63,9 +68,19 @@ export async function getProfile(token: any) {
return httpGetInterceptorWithToken(url, token);
}
export async function postEmailValidation(data: any) {
const url = "public/users/email-validation";
return postAPIWithJson(url, data);
}
export async function postSetupEmail(data: any) {
const url = "public/users/setup-email";
return httpGetInterceptorWithToken({ url, data });
}
export async function getSubjects() {
const url = 'inbox/subjects';
return httpGetInterceptor( url );
const url = "inbox/subjects";
return httpGetInterceptor(url);
}
export async function getInfoProfile() {

View File

@ -0,0 +1,12 @@
import axios from "axios";
const baseURL = "https://mediahub.polri.go.id/api/";
const axiosInstanceJson = axios.create({
baseURL,
headers: {
"content-type": "application/json",
},
});
export default axiosInstanceJson;

View File

@ -2,6 +2,8 @@ import { useRouter } from "next/navigation";
import axiosInterceptorInstance from "./axios-interceptor-instance";
import Cookies from "js-cookie";
import { getCsrfToken } from "../auth";
import axiosBaseInstance from "./axios-base-instance";
import axiosInstanceJson from "./axiosInstanceJson";
export async function httpGetInterceptor(pathUrl: any) {
const pathname = window.location.pathname;
@ -172,3 +174,21 @@ export async function httpGetInterceptorWithToken(pathUrl: any, headers?: any) {
};
}
}
export async function postAPIWithJson(url: any, data: any, headers?: any) {
const response = await axiosInstanceJson
.post(url, data, { headers })
.catch((error: any) => error.response);
if (response?.status > 300) {
return {
error: true,
message: response?.data?.message,
data: null,
};
}
return {
error: false,
message: "success",
data: response?.data,
};
}