feat:emergency issue
This commit is contained in:
parent
c064026779
commit
d38bb005a1
|
|
@ -122,10 +122,22 @@ const useTableColumns = () => {
|
||||||
</Button>
|
</Button>
|
||||||
</DropdownMenuTrigger>
|
</DropdownMenuTrigger>
|
||||||
<DropdownMenuContent className="p-0" align="end">
|
<DropdownMenuContent className="p-0" align="end">
|
||||||
<DetailSettingTracking id={row.original.id} isDetail={true} />
|
<Link
|
||||||
|
href={`/admin/settings/setting-tracking/detail/${row.original.id}`}
|
||||||
<UpdateSettingTracking id={row.original.id} isUpdate={true} />
|
>
|
||||||
|
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||||
|
<Eye className="w-4 h-4 me-1.5" />
|
||||||
|
View
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href={`/admin/settings/setting-tracking/update/${row.original.id}`}
|
||||||
|
>
|
||||||
|
<DropdownMenuItem className="p-2 border-b text-default-700 group focus:bg-default focus:text-primary-foreground rounded-none">
|
||||||
|
<SquarePen className="w-4 h-4 me-1.5" />
|
||||||
|
Edit
|
||||||
|
</DropdownMenuItem>
|
||||||
|
</Link>
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
onClick={() => handleDeleteMedia(row.original.id)}
|
onClick={() => handleDeleteMedia(row.original.id)}
|
||||||
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
className="p-2 border-b text-destructive bg-destructive/30 focus:bg-destructive focus:text-destructive-foreground rounded-none"
|
||||||
|
|
|
||||||
|
|
@ -1,141 +1,141 @@
|
||||||
"use client";
|
// "use client";
|
||||||
|
|
||||||
import { Button } from "@/components/ui/button";
|
// import { Button } from "@/components/ui/button";
|
||||||
import {
|
// import {
|
||||||
Dialog,
|
// Dialog,
|
||||||
DialogContent,
|
// DialogContent,
|
||||||
DialogFooter,
|
// DialogFooter,
|
||||||
DialogHeader,
|
// DialogHeader,
|
||||||
DialogTitle,
|
// DialogTitle,
|
||||||
DialogTrigger,
|
// DialogTrigger,
|
||||||
} from "@/components/ui/dialog";
|
// } from "@/components/ui/dialog";
|
||||||
import { z } from "zod";
|
// import { z } from "zod";
|
||||||
import { useForm } from "react-hook-form";
|
// import { useForm } from "react-hook-form";
|
||||||
import { zodResolver } from "@hookform/resolvers/zod";
|
// import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
import {
|
// import {
|
||||||
Form,
|
// Form,
|
||||||
FormControl,
|
// FormControl,
|
||||||
FormDescription,
|
// FormDescription,
|
||||||
FormField,
|
// FormField,
|
||||||
FormItem,
|
// FormItem,
|
||||||
FormLabel,
|
// FormLabel,
|
||||||
FormMessage,
|
// FormMessage,
|
||||||
} from "@/components/ui/form";
|
// } from "@/components/ui/form";
|
||||||
import { useRouter } from "@/i18n/routing";
|
// import { useRouter } from "@/i18n/routing";
|
||||||
import { Input } from "@/components/ui/input";
|
// import { Input } from "@/components/ui/input";
|
||||||
import { Checkbox } from "@/components/ui/checkbox";
|
// import { Checkbox } from "@/components/ui/checkbox";
|
||||||
import { getUserRoles, postCategory } from "@/service/settings/settings";
|
// import { getUserRoles, postCategory } from "@/service/settings/settings";
|
||||||
import { Fragment, useEffect, useState } from "react";
|
// import { Fragment, useEffect, useState } from "react";
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
// import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||||
import { Icon } from "@iconify/react/dist/iconify.js";
|
// import { Icon } from "@iconify/react/dist/iconify.js";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
// import { Textarea } from "@/components/ui/textarea";
|
||||||
import { close, error, loading } from "@/config/swal";
|
// import { close, error, loading } from "@/config/swal";
|
||||||
import { useToast } from "@/components/ui/use-toast";
|
// import { useToast } from "@/components/ui/use-toast";
|
||||||
import { stringify } from "querystring";
|
// import { stringify } from "querystring";
|
||||||
import { useDropzone } from "react-dropzone";
|
// import { useDropzone } from "react-dropzone";
|
||||||
import { CloudUpload } from "lucide-react";
|
// import { CloudUpload } from "lucide-react";
|
||||||
import Image from "next/image";
|
// import Image from "next/image";
|
||||||
import { Upload } from "tus-js-client";
|
// import { Upload } from "tus-js-client";
|
||||||
import { getCookiesDecrypt } from "@/lib/utils";
|
// import { getCookiesDecrypt } from "@/lib/utils";
|
||||||
import Cookies from "js-cookie";
|
// import Cookies from "js-cookie";
|
||||||
import { useTranslations } from "next-intl";
|
// import { useTranslations } from "next-intl";
|
||||||
|
|
||||||
const wilayahList = [
|
// const wilayahList = [
|
||||||
{ id: "mabes", label: "Mabes" },
|
// { id: "mabes", label: "Mabes" },
|
||||||
{ id: "polda", label: "Polda" },
|
// { id: "polda", label: "Polda" },
|
||||||
{ id: "satker", label: "Satker" },
|
// { id: "satker", label: "Satker" },
|
||||||
];
|
// ];
|
||||||
|
|
||||||
const jumlahList = [5, 10, 15, 20, 25, 30];
|
// const jumlahList = [5, 10, 15, 20, 25, 30];
|
||||||
|
|
||||||
export default function CreateSettingTracking() {
|
// export default function CreateSettingTracking() {
|
||||||
const t = useTranslations("Menu");
|
// const t = useTranslations("Menu");
|
||||||
const [isOpen, setIsOpen] = useState(false);
|
// const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
const form = useForm({
|
// const form = useForm({
|
||||||
defaultValues: {
|
// defaultValues: {
|
||||||
wilayah: [] as string[],
|
// wilayah: [] as string[],
|
||||||
jumlah: [] as number[],
|
// jumlah: [] as number[],
|
||||||
},
|
// },
|
||||||
});
|
// });
|
||||||
|
|
||||||
const onSubmit = (values: any) => {
|
// const onSubmit = (values: any) => {
|
||||||
console.log("Submitted values:", values);
|
// console.log("Submitted values:", values);
|
||||||
setIsOpen(false);
|
// setIsOpen(false);
|
||||||
};
|
// };
|
||||||
|
|
||||||
return (
|
// return (
|
||||||
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
// <Dialog open={isOpen} onOpenChange={setIsOpen}>
|
||||||
<DialogTrigger asChild>
|
// <DialogTrigger asChild>
|
||||||
<Button onClick={() => setIsOpen(true)}>Tambah Setting Tracking</Button>
|
// <Button onClick={() => setIsOpen(true)}>Tambah Setting Tracking</Button>
|
||||||
</DialogTrigger>
|
// </DialogTrigger>
|
||||||
|
|
||||||
<DialogContent className="sm:max-w-md">
|
// <DialogContent className="sm:max-w-md">
|
||||||
<DialogHeader>
|
// <DialogHeader>
|
||||||
<DialogTitle>Add Setting Tracking Berita Harian</DialogTitle>
|
// <DialogTitle>Add Setting Tracking Berita Harian</DialogTitle>
|
||||||
</DialogHeader>
|
// </DialogHeader>
|
||||||
|
|
||||||
<Form {...form}>
|
// <Form {...form}>
|
||||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
// <form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||||
{/* Wilayah */}
|
// {/* Wilayah */}
|
||||||
<FormField
|
// <FormField
|
||||||
control={form.control}
|
// control={form.control}
|
||||||
name="wilayah"
|
// name="wilayah"
|
||||||
render={({ field }) => (
|
// render={({ field }) => (
|
||||||
<FormItem>
|
// <FormItem>
|
||||||
<FormLabel>Wilayah</FormLabel>
|
// <FormLabel>Wilayah</FormLabel>
|
||||||
<div className="flex gap-4">
|
// <div className="flex gap-4">
|
||||||
{wilayahList.map((item) => (
|
// {wilayahList.map((item) => (
|
||||||
<div key={item.id} className="flex items-center gap-2">
|
// <div key={item.id} className="flex items-center gap-2">
|
||||||
<Checkbox
|
// <Checkbox
|
||||||
checked={field.value.includes(item.id)}
|
// checked={field.value.includes(item.id)}
|
||||||
onCheckedChange={(checked) => {
|
// onCheckedChange={(checked) => {
|
||||||
const updated = checked
|
// const updated = checked
|
||||||
? [...field.value, item.id]
|
// ? [...field.value, item.id]
|
||||||
: field.value.filter((val) => val !== item.id);
|
// : field.value.filter((val) => val !== item.id);
|
||||||
field.onChange(updated);
|
// field.onChange(updated);
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
<label className="text-sm">{item.label}</label>
|
// <label className="text-sm">{item.label}</label>
|
||||||
</div>
|
// </div>
|
||||||
))}
|
// ))}
|
||||||
</div>
|
// </div>
|
||||||
</FormItem>
|
// </FormItem>
|
||||||
)}
|
// )}
|
||||||
/>
|
// />
|
||||||
|
|
||||||
<FormField
|
// <FormField
|
||||||
control={form.control}
|
// control={form.control}
|
||||||
name="jumlah"
|
// name="jumlah"
|
||||||
render={({ field }) => (
|
// render={({ field }) => (
|
||||||
<FormItem>
|
// <FormItem>
|
||||||
<FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
// <FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
||||||
<div className="flex gap-4 flex-wrap">
|
// <div className="flex gap-4 flex-wrap">
|
||||||
{jumlahList.map((num) => (
|
// {jumlahList.map((num) => (
|
||||||
<div key={num} className="flex items-center gap-2">
|
// <div key={num} className="flex items-center gap-2">
|
||||||
<Checkbox
|
// <Checkbox
|
||||||
checked={field.value.includes(num)}
|
// checked={field.value.includes(num)}
|
||||||
onCheckedChange={(checked) => {
|
// onCheckedChange={(checked) => {
|
||||||
const updated = checked
|
// const updated = checked
|
||||||
? [...field.value, num]
|
// ? [...field.value, num]
|
||||||
: field.value.filter((val) => val !== num);
|
// : field.value.filter((val) => val !== num);
|
||||||
field.onChange(updated);
|
// field.onChange(updated);
|
||||||
}}
|
// }}
|
||||||
/>
|
// />
|
||||||
<label className="text-sm">{num}</label>
|
// <label className="text-sm">{num}</label>
|
||||||
</div>
|
// </div>
|
||||||
))}
|
// ))}
|
||||||
</div>
|
// </div>
|
||||||
</FormItem>
|
// </FormItem>
|
||||||
)}
|
// )}
|
||||||
/>
|
// />
|
||||||
|
|
||||||
<DialogFooter>
|
// <DialogFooter>
|
||||||
<Button type="submit">Tambah Setting</Button>
|
// <Button type="submit">Tambah Setting</Button>
|
||||||
</DialogFooter>
|
// </DialogFooter>
|
||||||
</form>
|
// </form>
|
||||||
</Form>
|
// </Form>
|
||||||
</DialogContent>
|
// </DialogContent>
|
||||||
</Dialog>
|
// </Dialog>
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,8 @@ import {
|
||||||
PopoverContent,
|
PopoverContent,
|
||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import CreateSettingTracking from "./create";
|
|
||||||
import useTableColumns from "./column";
|
import useTableColumns from "./column";
|
||||||
|
import { UploadIcon } from "lucide-react";
|
||||||
|
|
||||||
const AdminSettingTrackingTable = () => {
|
const AdminSettingTrackingTable = () => {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
@ -190,7 +190,15 @@ const AdminSettingTrackingTable = () => {
|
||||||
return (
|
return (
|
||||||
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
<div className="w-full overflow-x-auto bg-white p-4 rounded-sm space-y-3">
|
||||||
<div className="flex items-end justify-between">
|
<div className="flex items-end justify-between">
|
||||||
<CreateSettingTracking />
|
{/* <CreateSettingTracking /> */}
|
||||||
|
<div className="flex-none">
|
||||||
|
<Link href={"/admin/settings/setting-tracking/create"}>
|
||||||
|
<Button color="primary" className="text-white" size="md">
|
||||||
|
<UploadIcon size={18} className="mr-2" />
|
||||||
|
Tambah Setting Tracking
|
||||||
|
</Button>
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
<Popover>
|
<Popover>
|
||||||
<PopoverTrigger asChild>
|
<PopoverTrigger asChild>
|
||||||
<Button size="md" variant="outline">
|
<Button size="md" variant="outline">
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import CreateSettingTracking from "@/components/form/media-tracking/setting-tracking-form";
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
|
||||||
|
const SettingTrackingCreatePage = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
<div className="space-y-4">
|
||||||
|
<CreateSettingTracking />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SettingTrackingCreatePage;
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import DetailSettingTracking from "@/components/form/media-tracking/setting-tracking-detail-form";
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
|
||||||
|
const SettingTrackingDetailPage = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
<div className="space-y-4">
|
||||||
|
<DetailSettingTracking />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SettingTrackingDetailPage;
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import UpdateSettingTracking from "@/components/form/media-tracking/setting-tracking-update-form";
|
||||||
|
import SiteBreadcrumb from "@/components/site-breadcrumb";
|
||||||
|
|
||||||
|
const SettingTrackingUpdatePage = () => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<SiteBreadcrumb />
|
||||||
|
<div className="space-y-4">
|
||||||
|
<UpdateSettingTracking />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SettingTrackingUpdatePage;
|
||||||
|
|
@ -51,10 +51,8 @@ import { ChevronDownIcon } from "lucide-react";
|
||||||
import { getOperatorUser } from "@/service/management-user/management-user";
|
import { getOperatorUser } from "@/service/management-user/management-user";
|
||||||
|
|
||||||
const taskSchema = z.object({
|
const taskSchema = z.object({
|
||||||
title: z.string().min(1, { message: "Judul diperlukan" }),
|
message: z.string().optional(),
|
||||||
description: z.string().min(2, {
|
description: z.string().optional(),
|
||||||
message: "Narasi Penugasan harus lebih dari 2 karakter.",
|
|
||||||
}),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export type taskDetail = {
|
export type taskDetail = {
|
||||||
|
|
@ -509,7 +507,7 @@ export default function FormQuestionsReply() {
|
||||||
<Label>Judul</Label>
|
<Label>Judul</Label>
|
||||||
<Controller
|
<Controller
|
||||||
control={control}
|
control={control}
|
||||||
name="title"
|
name="message"
|
||||||
render={({ field }) => (
|
render={({ field }) => (
|
||||||
<Input
|
<Input
|
||||||
size="md"
|
size="md"
|
||||||
|
|
@ -605,6 +603,7 @@ export default function FormQuestionsReply() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
|
disabled
|
||||||
/>
|
/>
|
||||||
<span>{op.label}</span>
|
<span>{op.label}</span>
|
||||||
</label>
|
</label>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
|
||||||
|
const wilayahList = [
|
||||||
|
{ id: "mabes", label: "Mabes" },
|
||||||
|
{ id: "polda", label: "Polda" },
|
||||||
|
{ id: "satker", label: "Satker" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const jumlahList = [5, 10, 15, 20, 25, 30];
|
||||||
|
|
||||||
|
export default function DetailSettingTracking() {
|
||||||
|
const t = useTranslations("Menu");
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
wilayah: [] as string[],
|
||||||
|
jumlah: [] as number[],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (values: any) => {
|
||||||
|
console.log("Submitted values:", values);
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card className="px-3 py-3">
|
||||||
|
<Form {...form}>
|
||||||
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||||
|
{/* Wilayah */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="wilayah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Wilayah</FormLabel>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
{wilayahList.map((item) => (
|
||||||
|
<div key={item.id} className="flex items-center gap-2">
|
||||||
|
<Checkbox
|
||||||
|
checked={field.value.includes(item.id)}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
const updated = checked
|
||||||
|
? [...field.value, item.id]
|
||||||
|
: field.value.filter((val) => val !== item.id);
|
||||||
|
field.onChange(updated);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label className="text-sm">{item.label}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="jumlah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
||||||
|
<div className="flex gap-4 flex-wrap">
|
||||||
|
<Input
|
||||||
|
size={"md"}
|
||||||
|
type="number"
|
||||||
|
placeholder="Masukan Nama Iklan"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-end justify-end">
|
||||||
|
<Button type="submit">Tambah Setting</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
|
||||||
|
const wilayahList = [
|
||||||
|
{ id: "mabes", label: "Mabes" },
|
||||||
|
{ id: "polda", label: "Polda" },
|
||||||
|
{ id: "satker", label: "Satker" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const jumlahList = [5, 10, 15, 20, 25, 30];
|
||||||
|
|
||||||
|
export default function CreateSettingTracking() {
|
||||||
|
const t = useTranslations("Menu");
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
wilayah: [] as string[],
|
||||||
|
jumlah: [] as number[],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (values: any) => {
|
||||||
|
console.log("Submitted values:", values);
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card className="px-3 py-3">
|
||||||
|
<Form {...form}>
|
||||||
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||||
|
{/* Wilayah */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="wilayah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Wilayah</FormLabel>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
{wilayahList.map((item) => (
|
||||||
|
<div key={item.id} className="flex items-center gap-2">
|
||||||
|
<Checkbox
|
||||||
|
checked={field.value.includes(item.id)}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
const updated = checked
|
||||||
|
? [...field.value, item.id]
|
||||||
|
: field.value.filter((val) => val !== item.id);
|
||||||
|
field.onChange(updated);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label className="text-sm">{item.label}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="jumlah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
||||||
|
<div className="flex gap-4 flex-wrap">
|
||||||
|
<Input
|
||||||
|
size={"md"}
|
||||||
|
type="number"
|
||||||
|
placeholder="Masukan Nama Iklan"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-end justify-end">
|
||||||
|
<Button type="submit">Tambah Setting</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import {
|
||||||
|
Dialog,
|
||||||
|
DialogContent,
|
||||||
|
DialogFooter,
|
||||||
|
DialogHeader,
|
||||||
|
DialogTitle,
|
||||||
|
DialogTrigger,
|
||||||
|
} from "@/components/ui/dialog";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { Controller, useForm } from "react-hook-form";
|
||||||
|
import { zodResolver } from "@hookform/resolvers/zod";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormControl,
|
||||||
|
FormDescription,
|
||||||
|
FormField,
|
||||||
|
FormItem,
|
||||||
|
FormLabel,
|
||||||
|
FormMessage,
|
||||||
|
} from "@/components/ui/form";
|
||||||
|
import { Input } from "@/components/ui/input";
|
||||||
|
import { Checkbox } from "@/components/ui/checkbox";
|
||||||
|
import { Fragment, useEffect, useState } from "react";
|
||||||
|
import { useTranslations } from "next-intl";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
|
||||||
|
const wilayahList = [
|
||||||
|
{ id: "mabes", label: "Mabes" },
|
||||||
|
{ id: "polda", label: "Polda" },
|
||||||
|
{ id: "satker", label: "Satker" },
|
||||||
|
];
|
||||||
|
|
||||||
|
const jumlahList = [5, 10, 15, 20, 25, 30];
|
||||||
|
|
||||||
|
export default function UpdateSettingTracking() {
|
||||||
|
const t = useTranslations("Menu");
|
||||||
|
const [isOpen, setIsOpen] = useState(false);
|
||||||
|
|
||||||
|
const form = useForm({
|
||||||
|
defaultValues: {
|
||||||
|
wilayah: [] as string[],
|
||||||
|
jumlah: [] as number[],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const onSubmit = (values: any) => {
|
||||||
|
console.log("Submitted values:", values);
|
||||||
|
setIsOpen(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Card className="px-3 py-3">
|
||||||
|
<Form {...form}>
|
||||||
|
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||||
|
{/* Wilayah */}
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="wilayah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Wilayah</FormLabel>
|
||||||
|
<div className="flex gap-4">
|
||||||
|
{wilayahList.map((item) => (
|
||||||
|
<div key={item.id} className="flex items-center gap-2">
|
||||||
|
<Checkbox
|
||||||
|
checked={field.value.includes(item.id)}
|
||||||
|
onCheckedChange={(checked) => {
|
||||||
|
const updated = checked
|
||||||
|
? [...field.value, item.id]
|
||||||
|
: field.value.filter((val) => val !== item.id);
|
||||||
|
field.onChange(updated);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<label className="text-sm">{item.label}</label>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormField
|
||||||
|
control={form.control}
|
||||||
|
name="jumlah"
|
||||||
|
render={({ field }) => (
|
||||||
|
<FormItem>
|
||||||
|
<FormLabel>Jumlah Tracking Berita Harian</FormLabel>
|
||||||
|
<div className="flex gap-4 flex-wrap">
|
||||||
|
<Input
|
||||||
|
size={"md"}
|
||||||
|
type="number"
|
||||||
|
placeholder="Masukan Nama Iklan"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</FormItem>
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
<div className="flex items-end justify-end">
|
||||||
|
<Button type="submit">Tambah Setting</Button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</Form>
|
||||||
|
</Card>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,4 +1,6 @@
|
||||||
export type DetailTicket = {
|
export type DetailTicket = {
|
||||||
|
title: string;
|
||||||
|
description: string;
|
||||||
commentFromUserId: string;
|
commentFromUserId: string;
|
||||||
assignedTeams: string;
|
assignedTeams: string;
|
||||||
message: string;
|
message: string;
|
||||||
|
|
@ -19,7 +21,10 @@ export type DetailTicket = {
|
||||||
feedUrl: string;
|
feedUrl: string;
|
||||||
recommendationName: string;
|
recommendationName: string;
|
||||||
link: string;
|
link: string;
|
||||||
uploadFiles?: string;
|
uploadFiles?: {
|
||||||
|
fileUrl: string;
|
||||||
|
fileName: string;
|
||||||
|
}[];
|
||||||
description: string;
|
description: string;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
// InfoLainnyaModal.tsx
|
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
|
|
@ -6,6 +5,7 @@ import {
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from "@/components/ui/dialog";
|
} from "@/components/ui/dialog";
|
||||||
import { DetailTicket } from "./info-lainnya-types";
|
import { DetailTicket } from "./info-lainnya-types";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
interface InfoLainnyaModalProps {
|
interface InfoLainnyaModalProps {
|
||||||
open: boolean;
|
open: boolean;
|
||||||
|
|
@ -18,6 +18,34 @@ export default function InfoLainnyaModal({
|
||||||
onClose,
|
onClose,
|
||||||
data,
|
data,
|
||||||
}: InfoLainnyaModalProps) {
|
}: InfoLainnyaModalProps) {
|
||||||
|
const files = data?.uploadFiles || [];
|
||||||
|
const [currentIndex, setCurrentIndex] = useState(0);
|
||||||
|
|
||||||
|
const handlePrev = () => {
|
||||||
|
setCurrentIndex((prev) => (prev > 0 ? prev - 1 : prev));
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleNext = () => {
|
||||||
|
setCurrentIndex((prev) => (prev < files.length - 1 ? prev + 1 : prev));
|
||||||
|
};
|
||||||
|
|
||||||
|
const currentFile = files[currentIndex];
|
||||||
|
const isImage = (fileUrl: string) =>
|
||||||
|
/\.(jpeg|jpg|png|gif|bmp|webp)$/i.test(fileUrl.toLowerCase());
|
||||||
|
|
||||||
|
const getIframeUrl = (fileUrl: string): string => {
|
||||||
|
const lower = fileUrl.toLowerCase();
|
||||||
|
|
||||||
|
// Dokumen ditampilkan melalui Google Docs Viewer
|
||||||
|
if (/\.(pdf|doc|docx|xls|xlsx|ppt|pptx)$/i.test(lower)) {
|
||||||
|
return `https://docs.google.com/viewer?url=${encodeURIComponent(
|
||||||
|
fileUrl
|
||||||
|
)}&embedded=true`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileUrl;
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog open={open} onOpenChange={onClose}>
|
<Dialog open={open} onOpenChange={onClose}>
|
||||||
<DialogContent size="md">
|
<DialogContent size="md">
|
||||||
|
|
@ -41,11 +69,11 @@ export default function InfoLainnyaModal({
|
||||||
<div>:{data?.recommendationName}</div>
|
<div>:{data?.recommendationName}</div>
|
||||||
|
|
||||||
<div className="font-medium">Link Pendukung</div>
|
<div className="font-medium">Link Pendukung</div>
|
||||||
<div>
|
<div className="flex">
|
||||||
:
|
:
|
||||||
<a
|
<a
|
||||||
href={data?.link}
|
href={data?.link}
|
||||||
className="text-blue-600"
|
className="text-blue-600 flex w-[100px]"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
>
|
>
|
||||||
|
|
@ -53,15 +81,43 @@ export default function InfoLainnyaModal({
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{data?.uploadFiles && (
|
{files.length > 0 && (
|
||||||
<>
|
<>
|
||||||
<div className="font-medium">Lampiran</div>
|
<div className="font-medium col-span-2">Lampiran</div>
|
||||||
<div>
|
<div className="col-span-2 flex flex-col items-center space-y-2 w-full">
|
||||||
<img
|
{isImage(currentFile?.fileUrl || "") ? (
|
||||||
src={data?.uploadFiles}
|
<img
|
||||||
alt="Lampiran"
|
src={currentFile?.fileUrl}
|
||||||
className="max-w-xs"
|
alt={`Lampiran ${currentIndex + 1}`}
|
||||||
/>
|
className="max-h-[300px] w-auto object-contain border rounded"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<iframe
|
||||||
|
src={getIframeUrl(currentFile?.fileUrl || "")}
|
||||||
|
title={`Lampiran ${currentIndex + 1}`}
|
||||||
|
className="w-full max-w-2xl h-[300px] border rounded"
|
||||||
|
onError={(e) => {
|
||||||
|
(e.target as HTMLIFrameElement).style.display = "none";
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className="flex gap-2">
|
||||||
|
<button
|
||||||
|
onClick={handlePrev}
|
||||||
|
disabled={currentIndex === 0}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
<
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleNext}
|
||||||
|
disabled={currentIndex === files.length - 1}
|
||||||
|
className="px-2 py-1 border rounded disabled:opacity-50"
|
||||||
|
>
|
||||||
|
>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue