feat:Language

This commit is contained in:
Anang Yusman 2025-03-06 00:37:57 +08:00
parent 35d828369a
commit 98ca40a43a
14 changed files with 117 additions and 78 deletions

View File

@ -14,9 +14,7 @@ export default function AdminBanner() {
<SiteBreadcrumb /> <SiteBreadcrumb />
<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 justify-between"> <div className="flex justify-between">
{selectedTab === "content" {selectedTab === "content" ? "List Media" : " List Banner"}
? "Daftar List Media"
: "Table List Banner"}
<div className="flex flex-row gap-1 border-2 rounded-md w-fit mb-5"> <div className="flex flex-row gap-1 border-2 rounded-md w-fit mb-5">
<Button <Button

View File

@ -39,6 +39,7 @@ 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";
const FormSchema = z.object({ const FormSchema = z.object({
title: z.string({ title: z.string({
@ -109,7 +110,7 @@ export default function CreateCategoryModal() {
const levelNumber = getCookiesDecrypt("ulne"); const levelNumber = getCookiesDecrypt("ulne");
const userLevelId = getCookiesDecrypt("ulie"); const userLevelId = getCookiesDecrypt("ulie");
const poldaState = Cookies.get("state"); const poldaState = Cookies.get("state");
const t = useTranslations("Menu");
const [files, setFiles] = useState<File[]>([]); const [files, setFiles] = useState<File[]>([]);
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [satkerData, setSatkerData] = useState<string[]>([]); const [satkerData, setSatkerData] = useState<string[]>([]);
@ -239,12 +240,12 @@ export default function CreateCategoryModal() {
<Dialog open={isOpen} onOpenChange={setIsOpen}> <Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button color="primary" size="md"> <Button color="primary" size="md">
Tambah Kategori {t("add-category")}
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent size="md"> <DialogContent size="md">
<DialogHeader> <DialogHeader>
<DialogTitle>Tambah Kategori</DialogTitle> <DialogTitle> {t("add-category")}</DialogTitle>
</DialogHeader> </DialogHeader>
<Form {...form}> <Form {...form}>
<form <form

View File

@ -44,10 +44,12 @@ import {
DialogTrigger, DialogTrigger,
} from "@/components/ui/dialog"; } from "@/components/ui/dialog";
import CreateCategoryModal from "./create"; import CreateCategoryModal from "./create";
import { useTranslations } from "next-intl";
const AdminCategoryTable = () => { const AdminCategoryTable = () => {
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const t = useTranslations("Menu");
const dataChange = searchParams?.get("dataChange"); const dataChange = searchParams?.get("dataChange");
const [openModal, setOpenModal] = React.useState(false); const [openModal, setOpenModal] = React.useState(false);
const [dataTable, setDataTable] = React.useState<any[]>([]); const [dataTable, setDataTable] = React.useState<any[]>([]);
@ -127,7 +129,7 @@ const AdminCategoryTable = () => {
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 justify-between mb-10 items-center"> <div className="flex justify-between mb-10 items-center">
<p className="text-xl font-medium text-default-900">Kategori</p> <p className="text-xl font-medium text-default-900">{t("category")}</p>
<CreateCategoryModal /> <CreateCategoryModal />
</div> </div>

View File

@ -40,6 +40,7 @@ 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 { useTranslations } from "next-intl";
const FormSchema = z.object({ const FormSchema = z.object({
answer: z.string({ answer: z.string({
@ -79,7 +80,7 @@ const publishToList = [
export default function CreateFAQModal() { export default function CreateFAQModal() {
const router = useRouter(); const router = useRouter();
const { toast } = useToast(); const { toast } = useToast();
const t = useTranslations("Menu");
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const [satkerData, setSatkerData] = useState<string[]>([]); const [satkerData, setSatkerData] = useState<string[]>([]);
const [unitData, setUnitData] = useState<string[]>([]); const [unitData, setUnitData] = useState<string[]>([]);
@ -120,12 +121,12 @@ export default function CreateFAQModal() {
<Dialog open={isOpen} onOpenChange={setIsOpen}> <Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button color="primary" size="md"> <Button color="primary" size="md">
Tambah FAQ {t("add")} FAQ
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent size="md"> <DialogContent size="md">
<DialogHeader> <DialogHeader>
<DialogTitle>Tambah FAQ</DialogTitle> <DialogTitle>{t("add")} FAQ</DialogTitle>
</DialogHeader> </DialogHeader>
<Form {...form}> <Form {...form}>
<form <form

View File

@ -41,6 +41,7 @@ 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 { useTranslations } from "next-intl";
const FormSchema = z.object({ const FormSchema = z.object({
question: z.string({ question: z.string({
@ -77,7 +78,7 @@ const publishToList = [
export default function CreateFAQModal() { export default function CreateFAQModal() {
const router = useRouter(); const router = useRouter();
const { toast } = useToast(); const { toast } = useToast();
const t = useTranslations("Menu");
const [isOpen, setIsOpen] = useState(false); const [isOpen, setIsOpen] = useState(false);
const form = useForm<z.infer<typeof FormSchema>>({ const form = useForm<z.infer<typeof FormSchema>>({
@ -110,12 +111,12 @@ export default function CreateFAQModal() {
<Dialog open={isOpen} onOpenChange={setIsOpen}> <Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button color="primary" size="md"> <Button color="primary" size="md">
Tambah Feedback {t("add")} Feedback
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent size="md"> <DialogContent size="md">
<DialogHeader> <DialogHeader>
<DialogTitle>Tambah Feedback</DialogTitle> <DialogTitle>{t("add")} Feedback</DialogTitle>
</DialogHeader> </DialogHeader>
<Form {...form}> <Form {...form}>
<form <form

View File

@ -41,11 +41,13 @@ import {
} from "@/service/settings/settings"; } from "@/service/settings/settings";
import CreateFAQModal from "./create"; import CreateFAQModal from "./create";
import { useTranslations } from "next-intl";
const AdminFeedbackTable = () => { const AdminFeedbackTable = () => {
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const dataChange = searchParams?.get("dataChange"); const dataChange = searchParams?.get("dataChange");
const [openModal, setOpenModal] = React.useState(false); const [openModal, setOpenModal] = React.useState(false);
const [dataTable, setDataTable] = React.useState<any[]>([]); const [dataTable, setDataTable] = React.useState<any[]>([]);
const [totalData, setTotalData] = React.useState<number>(1); const [totalData, setTotalData] = React.useState<number>(1);

View File

@ -42,6 +42,7 @@ import {
CommandList, CommandList,
} from "@/components/ui/command"; } from "@/components/ui/command";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useTranslations } from "next-intl";
const FormSchema = z.object({ const FormSchema = z.object({
name: z.string({ name: z.string({
@ -55,6 +56,7 @@ const FormSchema = z.object({
export default function CreateTagModal() { export default function CreateTagModal() {
const router = useRouter(); const router = useRouter();
const { toast } = useToast(); const { toast } = useToast();
const t = useTranslations("Menu");
const [categoryList, setCategoryList] = useState< const [categoryList, setCategoryList] = useState<
{ id: number; label: string; value: string }[] { id: number; label: string; value: string }[]
>([]); >([]);
@ -107,12 +109,12 @@ export default function CreateTagModal() {
<Dialog open={isOpen} onOpenChange={setIsOpen}> <Dialog open={isOpen} onOpenChange={setIsOpen}>
<DialogTrigger asChild> <DialogTrigger asChild>
<Button color="primary" size="md"> <Button color="primary" size="md">
Tambah Tag {t("add-tags")}
</Button> </Button>
</DialogTrigger> </DialogTrigger>
<DialogContent size="md"> <DialogContent size="md">
<DialogHeader> <DialogHeader>
<DialogTitle>Tambah Tag</DialogTitle> <DialogTitle> {t("add-tags")}</DialogTitle>
</DialogHeader> </DialogHeader>
<Form {...form}> <Form {...form}>
<form <form

View File

@ -42,10 +42,12 @@ import {
} from "@/service/settings/settings"; } from "@/service/settings/settings";
import CreateFAQModal from "./create"; import CreateFAQModal from "./create";
import { useTranslations } from "next-intl";
const AdminTagTable = () => { const AdminTagTable = () => {
const router = useRouter(); const router = useRouter();
const searchParams = useSearchParams(); const searchParams = useSearchParams();
const t = useTranslations("Menu");
const dataChange = searchParams?.get("dataChange"); const dataChange = searchParams?.get("dataChange");
const [openModal, setOpenModal] = React.useState(false); const [openModal, setOpenModal] = React.useState(false);
const [dataTable, setDataTable] = React.useState<any[]>([]); const [dataTable, setDataTable] = React.useState<any[]>([]);
@ -124,7 +126,7 @@ const AdminTagTable = () => {
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 justify-between mb-10 items-center"> <div className="flex justify-between mb-10 items-center">
<p className="text-xl font-medium text-default-900">Tag</p> <p className="text-xl font-medium text-default-900">{t("tags")}</p>
<CreateFAQModal /> <CreateFAQModal />
</div> </div>

View File

@ -250,35 +250,6 @@ export default function ExecutiveDashboard() {
return ( return (
<div> <div>
<SiteBreadcrumb /> <SiteBreadcrumb />
<Dialog>
<DialogTrigger asChild>
<Button variant="outline">Download Report</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Download Report</DialogTitle>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="w-full">
<Label>Date</Label>
<Input
type="date"
// value={dateFilter}
// onChange={(e) => setDateFilter(e.target.value)}
className="w-full"
/>
</div>
</div>
<DialogFooter>
<Button
type="submit"
// onClick={downloadReport}
>
Download
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
<div className="mt-3 flex flex-row gap-3 justify-center"> <div className="mt-3 flex flex-row gap-3 justify-center">
<Card className="rounded-sm w-4/12 p-3"> <Card className="rounded-sm w-4/12 p-3">
<div className="flex flex-row justify-between"> <div className="flex flex-row justify-between">

View File

@ -24,15 +24,19 @@ import AudioSliderPage from "./giat-routine/audio/audio";
import ImageSliderPage from "./giat-routine/image/image"; import ImageSliderPage from "./giat-routine/image/image";
import TeksSliderPage from "./giat-routine/document/teks"; import TeksSliderPage from "./giat-routine/document/teks";
import ContestTable from "../contest/components/contest-table"; import ContestTable from "../contest/components/contest-table";
import { useTranslations } from "next-intl";
const CuratedContentPage = () => { const CuratedContentPage = () => {
const t = useTranslations("Curation");
return ( return (
<div> <div>
<SiteBreadcrumb /> <SiteBreadcrumb />
<div className="my-3"> <div className="my-3">
<Tabs defaultValue="giat-routine" className="w-full"> <Tabs defaultValue="giat-routine" className="w-full">
<Card className="py-3 px-2 my-4"> <Card className="py-3 px-2 my-4">
<p className="text-lg font-semibold ml-2">Kurasi Konten</p> <p className="text-lg font-semibold ml-2">
{t("content-curation")}
</p>
<TabsList className="flex-wrap"> <TabsList className="flex-wrap">
<TabsTrigger <TabsTrigger
value="giat-routine" value="giat-routine"

View File

@ -3,6 +3,17 @@ import React, { useEffect } from "react";
import DateRangePicker from "@/components/date-range-picker"; import DateRangePicker from "@/components/date-range-picker";
import { usePathname } from "@/components/navigation"; import { usePathname } from "@/components/navigation";
import { cn, getCookiesDecrypt } from "@/lib/utils"; import { cn, getCookiesDecrypt } from "@/lib/utils";
import {
Dialog,
DialogContent,
DialogFooter,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "./ui/dialog";
import { Button } from "./ui/button";
import { Label } from "./ui/label";
import { Input } from "./ui/input";
const PageTitle = ({ const PageTitle = ({
title, title,
@ -30,7 +41,35 @@ const PageTitle = ({
<div className="text-2xl font-medium text-default-800 capitalize"> <div className="text-2xl font-medium text-default-800 capitalize">
Dashboard Dashboard
</div> </div>
<DateRangePicker /> <Dialog>
<DialogTrigger asChild>
<Button variant="outline">Download Report</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Download Report</DialogTitle>
</DialogHeader>
<div className="grid gap-4 py-4">
<div className="w-full">
<Label>Date</Label>
<Input
type="date"
// value={dateFilter}
// onChange={(e) => setDateFilter(e.target.value)}
className="w-full"
/>
</div>
</div>
<DialogFooter>
<Button
type="submit"
// onClick={downloadReport}
>
Download
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
</div> </div>
); );
}; };

View File

@ -1591,21 +1591,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
submenus: [ submenus: [
{ {
href: "/contributor/schedule/press-conference", href: "/contributor/schedule/press-conference",
label: "konferensi pers", label: t("press-conference"),
active: pathname.includes("/schedule/press-conference"), active: pathname.includes("/schedule/press-conference"),
icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
children: [], children: [],
}, },
{ {
href: "/contributor/schedule/event", href: "/contributor/schedule/event",
label: "event", label: t("event"),
active: pathname.includes("/schedule/event"), active: pathname.includes("/schedule/event"),
icon: "heroicons:shopping-cart", icon: "heroicons:shopping-cart",
children: [], children: [],
}, },
{ {
href: "/contributor/schedule/press-release", href: "/contributor/schedule/press-release",
label: "pers rilis", label: t("press-release"),
active: pathname.includes("/schedule/press-release"), active: pathname.includes("/schedule/press-release"),
icon: "heroicons:shopping-cart", icon: "heroicons:shopping-cart",
children: [], children: [],
@ -1789,21 +1789,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
submenus: [ submenus: [
{ {
href: "/contributor/schedule/press-conference", href: "/contributor/schedule/press-conference",
label: "konferensi pers", label: t("press-conference"),
active: pathname.includes("/schedule/press-conference"), active: pathname.includes("/schedule/press-conference"),
icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
children: [], children: [],
}, },
{ {
href: "/contributor/schedule/event", href: "/contributor/schedule/event",
label: "event", label: t("event"),
active: pathname.includes("/schedule/event"), active: pathname.includes("/schedule/event"),
icon: "heroicons:shopping-cart", icon: "heroicons:shopping-cart",
children: [], children: [],
}, },
{ {
href: "/contributor/schedule/press-release", href: "/contributor/schedule/press-release",
label: "pers rilis", label: t("press-release"),
active: pathname.includes("/schedule/press-release"), active: pathname.includes("/schedule/press-release"),
icon: "heroicons:shopping-cart", icon: "heroicons:shopping-cart",
children: [], children: [],
@ -2019,7 +2019,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
submenus: [ submenus: [
{ {
href: "/contributor/schedule/press-conference", href: "/contributor/schedule/press-conference",
label: "konferensi pers", label: t("press-conference"),
active: pathname.includes("/schedule/press-conference"), active: pathname.includes("/schedule/press-conference"),
icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
children: [], children: [],
@ -2033,7 +2033,7 @@ export function getMenuList(pathname: string, t: any): Group[] {
}, },
{ {
href: "/contributor/schedule/press-release", href: "/contributor/schedule/press-release",
label: "pers rilis", label: t("press-release"),
active: pathname.includes("/schedule/press-release"), active: pathname.includes("/schedule/press-release"),
icon: "heroicons:shopping-cart", icon: "heroicons:shopping-cart",
children: [], children: [],
@ -2233,21 +2233,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
submenus: [ submenus: [
{ {
href: "/contributor/schedule/press-conference", href: "/contributor/schedule/press-conference",
label: "konferensi pers", label: t("press-conference"),
active: pathname.includes("/schedule/press-conference"), active: pathname.includes("/schedule/press-conference"),
icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
children: [], children: [],
}, },
{ {
href: "/contributor/schedule/event", href: "/contributor/schedule/event",
label: "event", label: t("event"),
active: pathname.includes("/schedule/event"), active: pathname.includes("/schedule/event"),
icon: "heroicons:shopping-cart", icon: "heroicons:shopping-cart",
children: [], children: [],
}, },
{ {
href: "/contributor/schedule/press-release", href: "/contributor/schedule/press-release",
label: "pers rilis", label: t("press-release"),
active: pathname.includes("/schedule/press-release"), active: pathname.includes("/schedule/press-release"),
icon: "heroicons:shopping-cart", icon: "heroicons:shopping-cart",
children: [], children: [],
@ -2442,21 +2442,21 @@ export function getMenuList(pathname: string, t: any): Group[] {
submenus: [ submenus: [
{ {
href: "/contributor/schedule/press-conference", href: "/contributor/schedule/press-conference",
label: "konferensi pers", label: t("press-conference"),
active: pathname.includes("/schedule/press-conference"), active: pathname.includes("/schedule/press-conference"),
icon: "heroicons:arrow-trending-up", icon: "heroicons:arrow-trending-up",
children: [], children: [],
}, },
{ {
href: "/contributor/schedule/event", href: "/contributor/schedule/event",
label: "event", label: t("event"),
active: pathname.includes("/schedule/event"), active: pathname.includes("/schedule/event"),
icon: "heroicons:shopping-cart", icon: "heroicons:shopping-cart",
children: [], children: [],
}, },
{ {
href: "/contributor/schedule/press-release", href: "/contributor/schedule/press-release",
label: "pers rilis", label: t("press-release"),
active: pathname.includes("/schedule/press-release"), active: pathname.includes("/schedule/press-release"),
icon: "heroicons:shopping-cart", icon: "heroicons:shopping-cart",
children: [], children: [],
@ -3202,20 +3202,20 @@ export function getMenuList(pathname: string, t: any): Group[] {
}, },
], ],
}, },
{ // {
groupLabel: "", // groupLabel: "",
id: "agenda-setting", // id: "agenda-setting",
menus: [ // menus: [
{ // {
id: "agenda-setting", // id: "agenda-setting",
href: "/contributor/agenda-setting", // href: "/contributor/agenda-setting",
label: t("agenda-setting"), // label: t("agenda-setting"),
active: pathname.includes("/agenda-setting"), // active: pathname.includes("/agenda-setting"),
icon: "iconoir:journal-page", // icon: "iconoir:journal-page",
submenus: [], // submenus: [],
}, // },
], // ],
}, // },
{ {
groupLabel: "", groupLabel: "",
id: "performance-polres", id: "performance-polres",

View File

@ -329,6 +329,10 @@
"management-content": "Content Management ", "management-content": "Content Management ",
"add-experts": "Add Experts", "add-experts": "Add Experts",
"category": "Category", "category": "Category",
"add-category": "Add Category",
"tags": "Tags",
"add-tags": "Add Tags",
"add": "Add",
"privacy": "Privacy Policy" "privacy": "Privacy Policy"
}, },
"Changelog": { "Changelog": {
@ -580,7 +584,8 @@
"schedule": "Schedule", "schedule": "Schedule",
"press-conference": "Press Conference", "press-conference": "Press Conference",
"press-release": "Press Release", "press-release": "Press Release",
"create-schedule": "Create Schedule" "create-schedule": "Create Schedule",
"event": "event"
}, },
"Blog": { "Blog": {
"table": "Table", "table": "Table",
@ -599,5 +604,8 @@
"table": "Table", "table": "Table",
"contest": "Lomba", "contest": "Lomba",
"create-contest": "Create Contest" "create-contest": "Create Contest"
},
"Curation": {
"content-curation": "Content Curation"
} }
} }

View File

@ -330,6 +330,10 @@
"management-content": "Manajemen Konten", "management-content": "Manajemen Konten",
"add-experts": "Tambah Tenaga Ahli", "add-experts": "Tambah Tenaga Ahli",
"category": "Kategori", "category": "Kategori",
"add-category": "Tambah Kategori",
"tags": "Tag",
"add-tags": "Tambah Tag",
"add": "Tambah",
"privacy": "Kebijakan Privacy" "privacy": "Kebijakan Privacy"
}, },
"Changelog": { "Changelog": {
@ -581,7 +585,8 @@
"schedule": "Jadwal", "schedule": "Jadwal",
"press-conference": "Konferensi Pers", "press-conference": "Konferensi Pers",
"press-release": "Pers Rilis", "press-release": "Pers Rilis",
"create-schedule": "Buat Jadwal" "create-schedule": "Buat Jadwal",
"event": "event"
}, },
"Blog": { "Blog": {
"table": "Tabel", "table": "Tabel",
@ -600,5 +605,8 @@
"table": "Tabel", "table": "Tabel",
"contest": "Lomba", "contest": "Lomba",
"create-contest": "Buat Lomba" "create-contest": "Buat Lomba"
},
"Curation": {
"content-curation": "Kurasi Konten"
} }
} }