Compare commits

..

1 Commits

300 changed files with 4771 additions and 6891 deletions

BIN
bun.lockb

Binary file not shown.

View File

@@ -19,7 +19,6 @@
"@elysiajs/static": "^1.3.0",
"@elysiajs/stream": "^1.1.0",
"@elysiajs/swagger": "^1.2.0",
"@emotion/react": "^11.14.0",
"@mantine/carousel": "^7.16.2",
"@mantine/charts": "^7.17.1",
"@mantine/core": "^7.17.4",
@@ -27,7 +26,6 @@
"@mantine/dropzone": "^8.1.1",
"@mantine/form": "^8.1.0",
"@mantine/hooks": "^7.17.4",
"@mantine/modals": "^8.3.6",
"@mantine/tiptap": "^7.17.4",
"@paljs/types": "^8.1.0",
"@prisma/client": "^6.3.1",
@@ -57,9 +55,8 @@
"dayjs": "^1.11.13",
"dotenv": "^17.2.3",
"elysia": "^1.3.5",
"embla-carousel": "^8.6.0",
"embla-carousel-autoplay": "^8.6.0",
"embla-carousel-react": "^8.6.0",
"embla-carousel-autoplay": "^8.5.2",
"embla-carousel-react": "^7.1.0",
"extract-zip": "^2.0.1",
"form-data": "^4.0.2",
"framer-motion": "^12.23.5",
@@ -83,7 +80,6 @@
"prisma": "^6.3.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-exif-orientation-img": "^0.1.5",
"react-international-phone": "^4.6.0",
"react-leaflet": "^5.0.0",
"react-simple-toasts": "^6.1.0",

View File

@@ -6,9 +6,9 @@ import { proxy } from "valtio";
import { z } from "zod";
const templateForm = z.object({
name: z.string().min(5, "Nama minimal 5 karakter"),
deskripsi: z.string().min(5, "Deskripsi minimal 5 karakter"),
slug: z.string().min(5, "Deskripsi singkat minimal 5 karakter"),
name: z.string().min(1, "Nama minimal 1 karakter"),
deskripsi: z.string().min(1, "Deskripsi minimal 1 karakter"),
slug: z.string().min(1, "Deskripsi singkat minimal 1 karakter"),
icon: z.string().min(1, "Icon minimal 1 karakter"),
});
@@ -29,33 +29,26 @@ const programKreatifState = proxy({
const err = `[${cek.error.issues
.map((v) => `${v.path.join(".")}`)
.join("\n")}] required`;
toast.error(err);
return false; // ⬅️ ini penting
return toast.error(err);
}
try {
programKreatifState.create.loading = true;
const res = await ApiFetch.api.inovasi.programkreatif["create"].post(
programKreatifState.create.form
);
if (res.status === 200) {
programKreatifState.findMany.load();
toast.success("success create");
return true;
return toast.success("success create");
}
toast.error("failed create");
return false;
console.log(res);
return toast.error("failed create");
} catch (error) {
console.error((error as Error).message);
toast.error("Terjadi kesalahan saat create");
return false;
console.log((error as Error).message);
} finally {
programKreatifState.create.loading = false;
}
}
},
},
findMany: {
data: null as any[] | null,

View File

@@ -1,10 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
import { IconBuildingStore, IconFileText, IconSparkles, IconUsers, IconUsersPlus } from '@tabler/icons-react';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
import { usePathname, useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
import { IconFileText, IconBuildingStore, IconSparkles, IconUsers, IconUsersPlus } from '@tabler/icons-react';
function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
const router = useRouter()
@@ -14,31 +14,36 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
label: "Pelayanan Surat Keterangan",
value: "pelayanansuratketerangan",
href: "/admin/desa/layanan/pelayanan_surat_keterangan",
icon: <IconFileText size={18} stroke={1.8} />
icon: <IconFileText size={18} stroke={1.8} />,
tooltip: "Layanan terkait surat keterangan resmi desa"
},
{
label: "Pelayanan Perizinan Berusaha",
value: "pelayananperizinanusaha",
href: "/admin/desa/layanan/pelayanan_perizinan_berusaha",
icon: <IconBuildingStore size={18} stroke={1.8} />
icon: <IconBuildingStore size={18} stroke={1.8} />,
tooltip: "Layanan untuk izin usaha masyarakat"
},
{
label: "Pelayanan Telunjuk Sakti Desa",
value: "pelayanantelunjuksaktidesa",
href: "/admin/desa/layanan/pelayanan_telunjuk_sakti_desa",
icon: <IconSparkles size={18} stroke={1.8} />
icon: <IconSparkles size={18} stroke={1.8} />,
tooltip: "Layanan inovasi khusus desa"
},
{
label: "Pelayanan Penduduk Non-Permanent",
value: "pelayanannonpermanent",
href: "/admin/desa/layanan/pelayanan_penduduk_non_permanent",
icon: <IconUsers size={18} stroke={1.8} />
icon: <IconUsers size={18} stroke={1.8} />,
tooltip: "Pendataan penduduk non-permanent"
},
{
label: "Ajukan Permohonan",
value: "ajukanpermohonan",
href: "/admin/desa/layanan/ajukan_permohonan",
icon: <IconUsersPlus size={18} stroke={1.8} />
icon: <IconUsersPlus size={18} stroke={1.8} />,
tooltip: "Ajukan permohonan"
}
];
@@ -86,8 +91,14 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
}}
>
{tabs.map((tab, i) => (
<TabsTab
<Tooltip
key={i}
label={tab.tooltip}
position="bottom"
withArrow
transitionProps={{ transition: 'pop', duration: 200 }}
>
<TabsTab
value={tab.value}
leftSection={tab.icon}
style={{
@@ -98,6 +109,7 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
>
{tab.label}
</TabsTab>
</Tooltip>
))}
</TabsList>
</ScrollArea>

View File

@@ -1,10 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
import { IconCategory, IconNews } from '@tabler/icons-react';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
import { usePathname, useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
import { IconNews, IconCategory } from '@tabler/icons-react';
function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
const router = useRouter();
@@ -15,13 +15,15 @@ function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
label: "List Berita",
value: "list_berita",
href: "/admin/desa/berita/list-berita",
icon: <IconNews size={18} stroke={1.8} />
icon: <IconNews size={18} stroke={1.8} />,
tooltip: "Lihat dan kelola semua berita desa"
},
{
label: "Kategori Berita",
value: "kategori_berita",
href: "/admin/desa/berita/kategori-berita",
icon: <IconCategory size={18} stroke={1.8} />
icon: <IconCategory size={18} stroke={1.8} />,
tooltip: "Kelola kategori berita desa"
},
];
@@ -69,39 +71,46 @@ function LayoutTabsBerita({ children }: { children: React.ReactNode }) {
}}
>
{tabs.map((tab, i) => (
<TabsTab
<Tooltip
key={i}
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
label={tab.tooltip}
position="bottom"
withArrow
transitionProps={{ transition: 'pop', duration: 200 }}
>
{tab.label}
</TabsTab>
<TabsTab
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
</Tooltip>
))}
</TabsList>
</ScrollArea>
</TabsList>
</ScrollArea>
{tabs.map((tab, i) => (
<TabsPanel
key={i}
value={tab.value}
style={{
padding: "1.5rem",
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
borderRadius: "1rem",
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
}}
>
{/* Konten dummy, bisa diganti sesuai routing */}
<>{children}</>
</TabsPanel>
))}
</Tabs>
</Stack >
{tabs.map((tab, i) => (
<TabsPanel
key={i}
value={tab.value}
style={{
padding: "1.5rem",
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
borderRadius: "1rem",
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
}}
>
{/* Konten dummy, bisa diganti sesuai routing */}
<>{children}</>
</TabsPanel>
))}
</Tabs>
</Stack>
);
}

View File

@@ -10,7 +10,8 @@ import {
Paper,
Stack,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -76,6 +77,7 @@ function EditKategoriBerita() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Back Button + Title */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -84,6 +86,7 @@ function EditKategoriBerita() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Kategori Berita
</Title>

View File

@@ -8,7 +8,8 @@ import {
Paper,
Stack,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -34,6 +35,7 @@ function CreateKategoriBerita() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header dengan back button */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -42,6 +44,7 @@ function CreateKategoriBerita() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Kategori Berita
</Title>

View File

@@ -17,7 +17,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -85,6 +86,7 @@ function ListKategoriBerita({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Kategori Berita</Title>
<Tooltip label="Tambah Kategori Berita" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
@@ -95,6 +97,7 @@ function ListKategoriBerita({ search }: { search: string }) {
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: 'auto' }}>
@@ -120,6 +123,7 @@ function ListKategoriBerita({ search }: { search: string }) {
</Text>
</TableTd>
<TableTd>
<Tooltip label="Edit Kategori Berita" withArrow>
<Button
variant="light"
color="green"
@@ -131,8 +135,10 @@ function ListKategoriBerita({ search }: { search: string }) {
>
<IconEdit size={18} />
</Button>
</Tooltip>
</TableTd>
<TableTd>
<Tooltip label="Hapus Kategori Berita" withArrow>
<Button
variant="light"
color="red"
@@ -144,6 +150,7 @@ function ListKategoriBerita({ search }: { search: string }) {
>
<IconTrash size={18} />
</Button>
</Tooltip>
</TableTd>
</TableTr>
))

View File

@@ -15,7 +15,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from "@mantine/core";
import { Dropzone } from "@mantine/dropzone";
import {
@@ -115,6 +116,7 @@ function EditBerita() {
<Box px={{ base: "sm", md: "lg" }} py="md">
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -123,6 +125,7 @@ function EditBerita() {
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Berita
</Title>

View File

@@ -1,14 +1,14 @@
'use client'
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import colors from '@/con/colors';
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import stateDashboardBerita from '@/app/admin/(dashboard)/_state/desa/berita';
import colors from '@/con/colors';
function DetailBerita() {
const beritaState = useProxy(stateDashboardBerita);
@@ -111,6 +111,7 @@ function DetailBerita() {
{/* Action Button */}
<Group gap="sm">
<Tooltip label="Hapus Berita" withArrow position="top">
<Button
color="red"
onClick={() => {
@@ -123,7 +124,9 @@ function DetailBerita() {
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Berita" withArrow position="top">
<Button
color="green"
onClick={() => router.push(`/admin/desa/berita/list-berita/${data.id}/edit`)}
@@ -133,6 +136,7 @@ function DetailBerita() {
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -13,7 +13,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { useShallowEffect } from '@mantine/hooks';
@@ -72,6 +73,7 @@ export default function CreateBerita() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header dengan tombol kembali */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -80,6 +82,7 @@ export default function CreateBerita() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Berita
</Title>

View File

@@ -16,7 +16,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
@@ -67,6 +68,7 @@ function ListBerita({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Berita</Title>
<Tooltip label="Tambah Berita" withArrow>
<Button
leftSection={<IconCircleDashedPlus size={18} />}
color="blue"
@@ -75,6 +77,7 @@ function ListBerita({ search }: { search: string }) {
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: 'auto' }}>

View File

@@ -13,7 +13,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from "@mantine/core";
import { useShallowEffect } from "@mantine/hooks";
import { IconSearch, IconTrash, IconX } from "@tabler/icons-react";
@@ -102,6 +103,7 @@ export default function ListImage() {
</Box>
<Group justify="space-between" align="center" pt="xs">
<Tooltip label="Hapus foto" withArrow>
<ActionIcon
variant="subtle"
color="red"
@@ -114,6 +116,7 @@ export default function ListImage() {
>
<IconTrash size={18} />
</ActionIcon>
</Tooltip>
</Group>
</Stack>
</Card>

View File

@@ -1,10 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
import { IconPhoto, IconVideo } from '@tabler/icons-react';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
import { usePathname, useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
import { IconPhoto, IconVideo } from '@tabler/icons-react';
function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
const router = useRouter()
@@ -14,13 +14,15 @@ function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
label: "Foto",
value: "foto",
href: "/admin/desa/gallery/foto",
icon: <IconPhoto size={18} stroke={1.8} />
icon: <IconPhoto size={18} stroke={1.8} />,
tooltip: "Kelola foto-foto galeri desa"
},
{
label: "Video",
value: "video",
href: "/admin/desa/gallery/video",
icon: <IconVideo size={18} stroke={1.8} />
icon: <IconVideo size={18} stroke={1.8} />,
tooltip: "Kelola video galeri desa"
},
];
@@ -68,18 +70,25 @@ function LayoutTabsGallery({ children }: { children: React.ReactNode }) {
}}
>
{tabs.map((tab, i) => (
<TabsTab
<Tooltip
key={i}
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
label={tab.tooltip}
position="bottom"
withArrow
transitionProps={{ transition: 'pop', duration: 200 }}
>
{tab.label}
</TabsTab>
<TabsTab
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
</Tooltip>
))}
</TabsList>
</ScrollArea>

View File

@@ -10,11 +10,12 @@ import {
Paper,
Stack,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useCallback, useEffect, useState } from 'react';
import { useEffect, useState, useCallback } from 'react';
import { toast } from 'react-toastify';
import { useProxy } from 'valtio/utils';
import { convertYoutubeUrlToEmbed } from '../../../lib/youtube-utils';
@@ -88,6 +89,7 @@ function EditVideo() {
return (
<Box px={{ base: 'sm', md: 'lg' }} py="md">
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -96,6 +98,7 @@ function EditVideo() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Video
</Title>

View File

@@ -2,7 +2,7 @@
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import stateGallery from '@/app/admin/(dashboard)/_state/desa/gallery';
import colors from '@/con/colors';
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -111,6 +111,7 @@ function DetailVideo() {
{/* Tombol Aksi */}
<Group gap="sm">
<Tooltip label="Hapus Video" withArrow position="top">
<Button
color="red"
onClick={() => {
@@ -123,7 +124,9 @@ function DetailVideo() {
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Video" withArrow position="top">
<Button
color="green"
onClick={() =>
@@ -135,6 +138,7 @@ function DetailVideo() {
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -10,7 +10,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -50,6 +51,7 @@ function CreateVideo() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header Back Button + Title */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -58,6 +60,7 @@ function CreateVideo() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Video
</Title>

View File

@@ -16,7 +16,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImac, IconPlus, IconSearch } from '@tabler/icons-react';
@@ -73,6 +74,7 @@ function ListVideo({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Video</Title>
<Tooltip label="Tambah Video Baru" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
@@ -81,6 +83,7 @@ function ListVideo({ search }: { search: string }) {
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: "auto" }}>
<Table highlightOnHover>

View File

@@ -10,7 +10,8 @@ import {
Select,
Stack,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -86,9 +87,11 @@ function EditAjukanPermohonan() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Back Button */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Ajukan Permohonan
</Title>

View File

@@ -9,7 +9,8 @@ import {
Paper,
Skeleton,
Stack,
Text
Text,
Tooltip
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
@@ -120,6 +121,7 @@ function DetailAjukanPermohonan() {
</Box>
<Group gap="sm">
<Tooltip label="Hapus Surat" withArrow position="top">
<Button
color="red"
onClick={() => {
@@ -133,7 +135,9 @@ function DetailAjukanPermohonan() {
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Surat" withArrow position="top">
<Button
color="green"
onClick={() =>
@@ -147,6 +151,7 @@ function DetailAjukanPermohonan() {
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -12,7 +12,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -82,6 +83,7 @@ function EditPelayananPendudukNonPermanent() {
<Box>
<Stack gap="xs">
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -90,6 +92,7 @@ function EditPelayananPendudukNonPermanent() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Pelayanan Penduduk Non Permanent
</Title>

View File

@@ -11,7 +11,8 @@ import {
Skeleton,
Stack,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconEdit } from '@tabler/icons-react';
@@ -50,6 +51,7 @@ function PelayananPendudukNonPermanent() {
</Title>
</GridCol>
<GridCol span={{ base: 12, md: 1 }}>
<Tooltip label="Edit Data Pelayanan" withArrow>
<Button
c="green"
variant="light"
@@ -63,6 +65,7 @@ function PelayananPendudukNonPermanent() {
>
Edit
</Button>
</Tooltip>
</GridCol>
</Grid>

View File

@@ -12,7 +12,8 @@ import {
Skeleton,
Stack,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -99,6 +100,7 @@ function EditPelayananPerizinanBerusaha() {
<Stack gap="xs">
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -107,6 +109,7 @@ function EditPelayananPerizinanBerusaha() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Pelayanan Perizinan Berusaha
</Title>

View File

@@ -16,13 +16,14 @@ import {
StepperCompleted,
StepperStep,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconEdit } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { useProxy } from 'valtio/utils';
import stateLayananDesa from '../../../_state/desa/layananDesa';
import { useProxy } from 'valtio/utils';
import { useRouter } from 'next/navigation';
function PerizinanBerusaha() {
const router = useRouter();
@@ -84,6 +85,7 @@ function PerizinanBerusaha() {
</Title>
</GridCol>
<GridCol span={{ base: 12, md: 1 }}>
<Tooltip label="Edit Data Perizinan" withArrow>
<Button
c="green"
variant="light"
@@ -97,6 +99,7 @@ function PerizinanBerusaha() {
>
Edit
</Button>
</Tooltip>
</GridCol>
</Grid>

View File

@@ -12,12 +12,13 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useCallback, useEffect, useState } from 'react';
import { useEffect, useState, useCallback } from 'react';
import { toast } from 'react-toastify';
import { useProxy } from 'valtio/utils';
@@ -111,9 +112,11 @@ function EditSuratKeterangan() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Back Button */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Surat Keterangan
</Title>

View File

@@ -10,7 +10,8 @@ import {
Paper,
Skeleton,
Stack,
Text
Text,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
@@ -141,6 +142,7 @@ function DetailSuratKeterangan() {
</Box>
<Group gap="sm">
<Tooltip label="Hapus Surat" withArrow position="top">
<Button
color="red"
onClick={() => {
@@ -154,7 +156,9 @@ function DetailSuratKeterangan() {
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Surat" withArrow position="top">
<Button
color="green"
onClick={() =>
@@ -168,6 +172,7 @@ function DetailSuratKeterangan() {
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -13,7 +13,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
@@ -84,9 +85,11 @@ function CreateSuratKeterangan() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Surat Keterangan
</Title>

View File

@@ -17,7 +17,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -81,6 +82,7 @@ function ListSuratKeterangan({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>List Surat Keterangan</Title>
<Tooltip label="Tambah Surat Keterangan" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
@@ -91,6 +93,7 @@ function ListSuratKeterangan({ search }: { search: string }) {
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: "auto" }}>
<Table highlightOnHover>

View File

@@ -9,7 +9,8 @@ import {
Paper,
Stack,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -80,9 +81,11 @@ function EditPelayananTelunjukSakti() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Back Button + Title */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Pelayanan Telunjuk Sakti Desa
</Title>

View File

@@ -9,7 +9,8 @@ import {
Paper,
Skeleton,
Stack,
Text
Text,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
@@ -129,6 +130,7 @@ function DetailPelayananTelunjukSakti() {
</Box>
<Group gap="sm">
<Tooltip label="Hapus Layanan" withArrow position="top">
<Button
color="red"
onClick={() => {
@@ -142,7 +144,9 @@ function DetailPelayananTelunjukSakti() {
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Layanan" withArrow position="top">
<Button
color="green"
onClick={() =>
@@ -156,6 +160,7 @@ function DetailPelayananTelunjukSakti() {
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -9,7 +9,8 @@ import {
Paper,
Stack,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -44,9 +45,11 @@ function CreatePelayananTelunjukDesa() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Pelayanan Telunjuk Sakti Desa
</Title>

View File

@@ -1,3 +1,159 @@
// /* eslint-disable react-hooks/exhaustive-deps */
// 'use client'
// import colors from '@/con/colors';
// import { Box, Button, Center, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
// import { IconDeviceImac, IconSearch } from '@tabler/icons-react';
// import { useRouter } from 'next/navigation';
// import { useEffect, useMemo, useState } from 'react';
// import { useProxy } from 'valtio/utils';
// import HeaderSearch from '../../../_com/header';
// import JudulList from '../../../_com/judulList';
// import stateLayananDesa from '../../../_state/desa/layananDesa';
// function PelayananTelunjukSakti() {
// const [search, setSearch] = useState("");
// return (
// <Box>
// <HeaderSearch
// title='Posisi Organisasi'
// placeholder='pencarian'
// searchIcon={<IconSearch size={20} />}
// value={search}
// onChange={(e) => setSearch(e.currentTarget.value)}
// />
// <ListPelayananTelunjukSakti search={search} />
// </Box>
// );
// }
// function ListPelayananTelunjukSakti({ search }: { search: string }) {
// const telunjukSaktiState = useProxy(stateLayananDesa.pelayananTelunjukSaktiDesa)
// const router = useRouter()
// const {
// data,
// page,
// totalPages,
// loading,
// load,
// } = telunjukSaktiState.findMany;
// useEffect(() => {
// load(page, 10)
// }, [])
// const filteredData = useMemo(() => {
// if (!data) return [];
// return data.filter(item => {
// const keyword = search.toLowerCase();
// return (
// item.name?.toLowerCase().includes(keyword) ||
// item.link?.toLowerCase().includes(keyword) ||
// item.deskripsi?.toLowerCase().includes(keyword)
// );
// })
// .sort((a, b) => a.posisi?.hierarki - b.posisi?.hierarki);
// }, [data, search]);
// if (loading || !data) {
// return (
// <Stack py={10}>
// <Skeleton height={300} />
// </Stack>
// );
// }
// if (data.length === 0) {
// return (
// <Box py={10}>
// <Paper bg={colors['white-1']} p={'md'}>
// <JudulList
// title='List Pelayanan Telunjuk Sakti Desa'
// href='/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/create'
// />
// <Table striped withTableBorder withRowBorders>
// <TableThead>
// <TableTr>
// <TableTh>Nama</TableTh>
// <TableTh>Link</TableTh>
// <TableTh>Detail</TableTh>
// </TableTr>
// </TableThead>
// <TableTbody>
// <TableTr>
// <TableTd colSpan={3}>
// <Text fz={"sm"} color="gray.5">
// Tidak ada data
// </Text>
// </TableTd>
// </TableTr>
// </TableTbody>
// </Table>
// </Paper>
// </Box>
// );
// }
// return (
// <Box py={10}>
// <Paper bg={colors['white-1']} p={'md'}>
// <JudulList
// title='List Pelayanan Telunjuk Sakti Desa'
// href='/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/create'
// />
// <Table striped withTableBorder withRowBorders>
// <TableThead>
// <TableTr>
// <TableTh>Nama</TableTh>
// <TableTh>Link</TableTh>
// <TableTh>Detail</TableTh>
// </TableTr>
// </TableThead>
// <TableTbody>
// {filteredData.map((item) => (
// <TableTr key={item.id}>
// <TableTd>
// <Box w={100}>
// <Text truncate="end" lineClamp={1} fz={"sm"} dangerouslySetInnerHTML={{ __html: item.name }} />
// </Box>
// </TableTd>
// <TableTd>
// <Box w={100}>
// <a href={item.link} target="_blank" rel="noopener noreferrer">
// <Text dangerouslySetInnerHTML={{ __html: item.deskripsi }} truncate="end" fz={"sm"} />
// </a>
// </Box>
// </TableTd>
// <TableTd>
// <Text>
// <Button onClick={() => router.push(`/admin/desa/layanan/pelayanan_telunjuk_sakti_desa/${item.id}`)}>
// <IconDeviceImac size={20} />
// </Button>
// </Text>
// </TableTd>
// </TableTr>
// ))}
// </TableTbody>
// </Table>
// </Paper>
// <Center>
// <Pagination
// value={page}
// onChange={(newPage) => {
// load(newPage, 10);
// window.scrollTo(0, 0);
// }}
// total={totalPages}
// mt="md"
// mb="md"
// />
// </Center>
// </Box>
// );
// }
// export default PelayananTelunjukSakti;
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
@@ -18,7 +174,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -68,6 +225,7 @@ function ListPelayananTelunjukSakti({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Pelayanan Telunjuk Sakti</Title>
<Tooltip label="Tambah Layanan" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
@@ -78,6 +236,7 @@ function ListPelayananTelunjukSakti({ search }: { search: string }) {
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: 'auto' }}>
<Table highlightOnHover style={{ minWidth: '700px' }}>

View File

@@ -13,7 +13,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
@@ -101,9 +102,11 @@ function EditPenghargaan() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Tombol Back + Title */}
<Group mb="md">
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Penghargaan
</Title>

View File

@@ -1,5 +1,9 @@
'use client'
import colors from '@/con/colors';
import React, { useState } from 'react';
import penghargaanState from '../../../_state/desa/penghargaan';
import { useProxy } from 'valtio/utils';
import { useParams, useRouter } from 'next/navigation';
import { useShallowEffect } from '@mantine/hooks';
import {
Box,
Button,
@@ -8,15 +12,12 @@ import {
Paper,
Skeleton,
Stack,
Text
Text,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import colors from '@/con/colors';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
import penghargaanState from '../../../_state/desa/penghargaan';
function DetailPenghargaan() {
const statePenghargaan = useProxy(penghargaanState);
@@ -126,30 +127,34 @@ function DetailPenghargaan() {
</Box>
<Group gap="sm" mt={10}>
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
<Tooltip label="Hapus Penghargaan" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Button
color="green"
onClick={() =>
router.push(`/admin/desa/penghargaan/${data.id}/edit`)
}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
<Tooltip label="Edit Penghargaan" withArrow position="top">
<Button
color="green"
onClick={() =>
router.push(`/admin/desa/penghargaan/${data.id}/edit`)
}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -10,7 +10,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
@@ -65,9 +66,11 @@ function CreatePenghargaan() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Penghargaan
</Title>

View File

@@ -18,7 +18,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -68,6 +69,7 @@ function ListPenghargaan({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>List Penghargaan</Title>
<Tooltip label="Tambah Penghargaan" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
@@ -76,6 +78,7 @@ function ListPenghargaan({ search }: { search: string }) {
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: 'auto' }}>
<Table highlightOnHover>

View File

@@ -1,10 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
import { IconCategory, IconListDetails } from '@tabler/icons-react';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
import { usePathname, useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
import { IconListDetails, IconCategory } from '@tabler/icons-react';
function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
const router = useRouter()
@@ -14,13 +14,15 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
label: "List Pengumuman",
value: "listpengumuman",
href: "/admin/desa/pengumuman/list-pengumuman",
icon: <IconListDetails size={18} stroke={1.8} />
icon: <IconListDetails size={18} stroke={1.8} />,
tooltip: "Lihat semua daftar pengumuman"
},
{
label: "Kategori Pengumuman",
value: "kategoripengumuman",
href: "/admin/desa/pengumuman/kategori-pengumuman",
icon: <IconCategory size={18} stroke={1.8} />
icon: <IconCategory size={18} stroke={1.8} />,
tooltip: "Kelola kategori pengumuman"
},
];
@@ -68,18 +70,19 @@ function LayoutTabsLayanan({ children }: { children: React.ReactNode }) {
}}
>
{tabs.map((tab, i) => (
<TabsTab
key={i}
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
<TabsTab
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
</Tooltip>
))}
</TabsList>
</ScrollArea>

View File

@@ -10,7 +10,8 @@ import {
Paper,
Stack,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -73,6 +74,7 @@ function EditKategoriPengumuman() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -81,6 +83,7 @@ function EditKategoriPengumuman() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Kategori Pengumuman
</Title>

View File

@@ -8,7 +8,8 @@ import {
Paper,
Stack,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -34,6 +35,7 @@ function CreateKategoriPengumuman() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header dengan back button */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -42,6 +44,7 @@ function CreateKategoriPengumuman() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Kategori Pengumuman
</Title>

View File

@@ -2,13 +2,11 @@
'use client'
import colors from '@/con/colors';
import {
Box, Button, Center,
Pagination,
Paper, Skeleton, Stack,
Box, Button, Center, Paper, Skeleton, Stack,
Table, TableTbody, TableTd, TableTh, TableThead, TableTr,
Text, Title
Text, Title, Tooltip, Pagination
} from '@mantine/core';
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
import { IconEdit, IconSearch, IconTrash, IconPlus } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { useProxy } from 'valtio/utils';
@@ -68,14 +66,16 @@ function ListKategoriPengumuman({ search }: { search: string }) {
<Stack>
<Box style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 15 }}>
<Title order={4}>List Kategori Pengumuman</Title>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/desa/pengumuman/kategori-pengumuman/create')}
>
Tambah Baru
</Button>
<Tooltip label="Tambah Kategori Pengumuman" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/desa/pengumuman/kategori-pengumuman/create')}
>
Tambah Baru
</Button>
</Tooltip>
</Box>
<Box style={{ overflowX: 'auto' }}>
@@ -99,25 +99,29 @@ function ListKategoriPengumuman({ search }: { search: string }) {
<Text truncate lineClamp={1}>{item.name}</Text>
</TableTd>
<TableTd>
<Button
variant='light'
color='green'
onClick={() => router.push(`/admin/desa/pengumuman/kategori-pengumuman/${item.id}`)}
>
<IconEdit size={20} />
</Button>
<Tooltip label="Edit Kategori Pengumuman" withArrow>
<Button
variant='light'
color='green'
onClick={() => router.push(`/admin/desa/pengumuman/kategori-pengumuman/${item.id}`)}
>
<IconEdit size={20} />
</Button>
</Tooltip>
</TableTd>
<TableTd>
<Button
variant='light'
color='red'
disabled={listDataState.delete.loading}
onClick={() => {
setSelectedId(item.id)
setModalHapus(true)
}}>
<IconTrash size={20} />
</Button>
<Tooltip label="Hapus Kategori Pengumuman" withArrow>
<Button
variant='light'
color='red'
disabled={listDataState.delete.loading}
onClick={() => {
setSelectedId(item.id)
setModalHapus(true)
}}>
<IconTrash size={20} />
</Button>
</Tooltip>
</TableTd>
</TableTr>
))

View File

@@ -13,7 +13,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from "@mantine/core";
import { IconArrowBack } from "@tabler/icons-react";
import { useParams, useRouter } from "next/navigation";
@@ -84,14 +85,16 @@ function EditPengumuman() {
return (
<Box px={{ base: "sm", md: "lg" }} py="md">
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Pengumuman
</Title>

View File

@@ -1,7 +1,5 @@
'use client'
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import stateDesaPengumuman from '@/app/admin/(dashboard)/_state/desa/pengumuman';
import colors from '@/con/colors';
import {
Box,
@@ -10,13 +8,16 @@ import {
Paper,
Skeleton,
Stack,
Text
Text,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useRouter, useParams } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import { useShallowEffect } from '@mantine/hooks';
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import stateDesaPengumuman from '@/app/admin/(dashboard)/_state/desa/pengumuman';
export default function DetailPengumuman() {
const pengumumanState = useProxy(stateDesaPengumuman);
@@ -116,6 +117,7 @@ export default function DetailPengumuman() {
</Box>
<Group gap="sm">
<Tooltip label="Hapus Pengumuman" withArrow position="top">
<Button
color="red"
onClick={() => {
@@ -128,7 +130,9 @@ export default function DetailPengumuman() {
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Pengumuman" withArrow position="top">
<Button
color="green"
onClick={() =>
@@ -142,6 +146,7 @@ export default function DetailPengumuman() {
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -12,7 +12,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack } from '@tabler/icons-react';
@@ -46,9 +47,11 @@ function CreatePengumuman() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Pengumuman
</Title>

View File

@@ -17,7 +17,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconCircleDashedPlus, IconDeviceImacCog, IconSearch } from '@tabler/icons-react';
@@ -68,14 +69,16 @@ function ListPengumuman({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Pengumuman</Title>
<Button
leftSection={<IconCircleDashedPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/desa/pengumuman/list-pengumuman/create')}
>
Tambah Baru
</Button>
<Tooltip label="Tambah Pengumuman" withArrow>
<Button
leftSection={<IconCircleDashedPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/desa/pengumuman/list-pengumuman/create')}
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: 'auto' }}>
<Table highlightOnHover style={{ minWidth: '700px' }}>

View File

@@ -1,7 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
import { IconCategory, IconListCheck } from '@tabler/icons-react';
import { usePathname, useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
@@ -14,13 +14,15 @@ function LayoutTabsPotensi({ children }: { children: React.ReactNode }) {
label: "List Potensi",
value: "list_potensi",
href: "/admin/desa/potensi/list-potensi",
icon: <IconListCheck size={18} stroke={1.8} />
icon: <IconListCheck size={18} stroke={1.8} />,
tooltip: "Lihat semua potensi desa"
},
{
label: "Kategori Potensi",
value: "kategori_potensi",
href: "/admin/desa/potensi/kategori-potensi",
icon: <IconCategory size={18} stroke={1.8} />
icon: <IconCategory size={18} stroke={1.8} />,
tooltip: "Kelola kategori potensi"
},
];
@@ -68,18 +70,19 @@ function LayoutTabsPotensi({ children }: { children: React.ReactNode }) {
}}
>
{tabs.map((tab, i) => (
<TabsTab
key={i}
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
<TabsTab
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
</Tooltip>
))}
</TabsList>
</ScrollArea>

View File

@@ -9,7 +9,8 @@ import {
Paper,
Stack,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -75,6 +76,7 @@ function EditKategoriPotensi() {
return (
<Box px={{ base: 'sm', md: 'lg' }} py="md">
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -83,6 +85,7 @@ function EditKategoriPotensi() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Kategori Potensi
</Title>

View File

@@ -8,7 +8,8 @@ import {
Paper,
Stack,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -34,6 +35,7 @@ function CreateKategoriPotensi() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header dengan back button */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -42,6 +44,7 @@ function CreateKategoriPotensi() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Kategori Potensi
</Title>

View File

@@ -1,14 +1,14 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
import { Box, Button, Center, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title, Tooltip, Pagination, Group } from '@mantine/core';
import { IconEdit, IconSearch, IconTrash, IconPlus } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../../_com/header';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
import potensiDesaState from '../../../_state/desa/potensi';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
function KategoriPotensi() {
const [search, setSearch] = useState('');
@@ -62,6 +62,7 @@ function ListKategoriPotensi({ search }: { search: string }) {
<Stack>
<Group justify="space-between">
<Title order={4}>List Kategori Potensi</Title>
<Tooltip label="Tambah Kategori Potensi" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
@@ -70,6 +71,7 @@ function ListKategoriPotensi({ search }: { search: string }) {
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: 'auto' }}>

View File

@@ -15,7 +15,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from "@mantine/core";
import { Dropzone } from "@mantine/dropzone";
import { IconArrowBack, IconPhoto, IconUpload, IconX } from "@tabler/icons-react";
@@ -121,6 +122,7 @@ function EditPotensi() {
return (
<Box px={{ base: "sm", md: "lg" }} py="md">
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -129,6 +131,7 @@ function EditPotensi() {
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Potensi Desa
</Title>

View File

@@ -1,13 +1,13 @@
'use client'
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import potensiDesaState from '@/app/admin/(dashboard)/_state/desa/potensi';
import colors from '@/con/colors';
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useRouter, useParams } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import { useShallowEffect } from '@mantine/hooks';
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import potensiDesaState from '@/app/admin/(dashboard)/_state/desa/potensi';
export default function DetailPotensi() {
const router = useRouter();
@@ -108,6 +108,7 @@ export default function DetailPotensi() {
</Box>
<Group gap="sm">
<Tooltip label="Hapus Potensi" withArrow position="top">
<Button
color="red"
onClick={() => {
@@ -120,7 +121,9 @@ export default function DetailPotensi() {
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Potensi" withArrow position="top">
<Button
color="green"
onClick={() =>
@@ -132,6 +135,7 @@ export default function DetailPotensi() {
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -14,7 +14,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
@@ -71,9 +72,11 @@ function CreatePotensi() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Potensi Desa
</Title>

View File

@@ -18,7 +18,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -75,6 +76,7 @@ function ListPotensi({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Potensi Desa</Title>
<Tooltip label="Tambah Potensi" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
@@ -83,6 +85,7 @@ function ListPotensi({ search }: { search: string }) {
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: "auto" }}>
<Table highlightOnHover style={{ minWidth: '700px' }}>

View File

@@ -1,10 +1,10 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
import { IconCalendar, IconUser, IconUsers } from '@tabler/icons-react';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
import { usePathname, useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
import { IconUser, IconUsers, IconCalendar } from '@tabler/icons-react';
function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
const router = useRouter()
@@ -14,19 +14,22 @@ function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
label: "Profile Desa",
value: "profiledesa",
href: "/admin/desa/profile/profile-desa",
icon: <IconUser size={18} stroke={1.8} />
icon: <IconUser size={18} stroke={1.8} />,
tooltip: "Lihat dan kelola profil desa"
},
{
label: "Profile Perbekel",
value: "profileperbekel",
href: "/admin/desa/profile/profile-perbekel",
icon: <IconUsers size={18} stroke={1.8} />
icon: <IconUsers size={18} stroke={1.8} />,
tooltip: "Kelola data Perbekel"
},
{
label: "Profile Perbekel Dari Masa Ke Masa",
value: "profile-perbekel-dari-masa-ke-masa",
href: "/admin/desa/profile/profile-perbekel-dari-masa-ke-masa",
icon: <IconCalendar size={18} stroke={1.8} />
icon: <IconCalendar size={18} stroke={1.8} />,
tooltip: "Riwayat Perbekel dari masa ke masa"
}
];
@@ -73,41 +76,42 @@ function LayoutTabsDetail({ children }: { children: React.ReactNode }) {
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
}}
>
{tabs.map((tab, i) => (
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
<TabsTab
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
</Tooltip>
))}
</TabsList>
</ScrollArea>
{tabs.map((tab, i) => (
<TabsTab
<TabsPanel
key={i}
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
padding: "1.5rem",
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
borderRadius: "1rem",
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
}}
>
{tab.label}
</TabsTab>
{/* Konten dummy, bisa diganti sesuai routing */}
<>{children}</>
</TabsPanel>
))}
</TabsList>
</ScrollArea>
{tabs.map((tab, i) => (
<TabsPanel
key={i}
value={tab.value}
style={{
padding: "1.5rem",
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
borderRadius: "1rem",
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
}}
>
{/* Konten dummy, bisa diganti sesuai routing */}
<>{children}</>
</TabsPanel>
))}
</Tabs>
</Stack>
);
</Tabs>
</Stack>
);
}
export default LayoutTabsDetail;
export default LayoutTabsDetail;

View File

@@ -3,7 +3,7 @@
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import colors from '@/con/colors';
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
@@ -99,9 +99,11 @@ function Page() {
<Box>
<Stack gap="xs">
<Group mb="md">
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">Edit Lambang Desa</Title>
</Group>

View File

@@ -5,9 +5,9 @@ import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import colors from '@/con/colors';
import ApiFetch from '@/lib/api-fetch';
import { Alert, Box, Button, Center, Group, Image, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
import { Box, Button, Group, Image, Paper, SimpleGrid, Stack, Text, TextInput, Title, Tooltip, Center, Alert } from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconAlertCircle, IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
import { IconArrowBack, IconPhoto, IconUpload, IconX, IconAlertCircle } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
@@ -161,9 +161,11 @@ function Page() {
<Box>
<Stack gap="xs">
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">Edit Maskot Desa</Title>
</Group>

View File

@@ -3,7 +3,7 @@
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import colors from '@/con/colors';
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
@@ -100,9 +100,11 @@ function Page() {
<Box>
<Stack gap="xs">
<Group mb="md">
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">Edit Sejarah Desa</Title>
</Group>

View File

@@ -3,7 +3,7 @@
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import colors from '@/con/colors';
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, Title } from '@mantine/core';
import { Alert, Box, Button, Center, Group, Paper, Stack, Text, Title, Tooltip } from '@mantine/core';
import { IconAlertCircle, IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
@@ -100,11 +100,11 @@ function Page() {
<Box>
<Stack gap="xs">
<Group mb="md">
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">Edit Visi Misi Desa</Title>
</Group>

View File

@@ -1,12 +1,12 @@
'use client'
import colors from '@/con/colors';
import { Box, Button, Card, Center, Divider, Grid, GridCol, Image, Paper, SimpleGrid, Stack, Text, Title } from '@mantine/core';
import { IconEdit } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
import { Box, Button, Card, Center, Divider, Grid, GridCol, Image, Paper, SimpleGrid, Stack, Text, Title, Tooltip } from '@mantine/core';
import { useSnapshot } from 'valtio';
import stateProfileDesa from '../../../_state/desa/profile';
import { useEffect } from 'react';
import { IconEdit } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
function Page() {
const router = useRouter();
@@ -37,6 +37,7 @@ function Page() {
<Title order={3} c={colors['blue-button']}>Preview Sejarah Desa</Title>
</GridCol>
<GridCol span={{ base: 12, md: 1 }}>
<Tooltip label="Edit Sejarah Desa" withArrow>
<Button
c="green"
variant="light"
@@ -46,6 +47,7 @@ function Page() {
>
Edit
</Button>
</Tooltip>
</GridCol>
</Grid>
@@ -82,6 +84,7 @@ function Page() {
<Title order={3} c={colors['blue-button']}>Preview Visi Misi Desa</Title>
</GridCol>
<GridCol span={{ base: 12, md: 1 }}>
<Tooltip label="Edit Visi Misi Desa" withArrow>
<Button
c="green"
variant="light"
@@ -91,6 +94,7 @@ function Page() {
>
Edit
</Button>
</Tooltip>
</GridCol>
</Grid>
@@ -130,6 +134,7 @@ function Page() {
<Title order={3} c={colors['blue-button']}>Preview Lambang Desa</Title>
</GridCol>
<GridCol span={{ base: 12, md: 1 }}>
<Tooltip label="Edit Lambang Desa" withArrow>
<Button
c="green"
variant="light"
@@ -139,6 +144,7 @@ function Page() {
>
Edit
</Button>
</Tooltip>
</GridCol>
</Grid>
@@ -175,6 +181,7 @@ function Page() {
<Title order={3} c={colors['blue-button']}>Preview Maskot Desa</Title>
</GridCol>
<GridCol span={{ base: 12, md: 1 }}>
<Tooltip label="Edit Maskot Desa" withArrow>
<Button
c="green"
variant="light"
@@ -184,6 +191,7 @@ function Page() {
>
Edit
</Button>
</Tooltip>
</GridCol>
</Grid>

View File

@@ -12,7 +12,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
@@ -96,9 +97,11 @@ function EditPerbekelDariMasaKeMasa() {
return (
<Box px={{ base: 'sm', md: 'lg' }} py="md">
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Perbekel Dari Masa Ke Masa
</Title>

View File

@@ -2,7 +2,7 @@
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import colors from '@/con/colors';
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconX } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -98,6 +98,7 @@ function DetailPerbekelDariMasa() {
</Box>
<Group gap="sm">
<Tooltip label="Hapus Perbekel" withArrow position="top">
<Button
color="red"
onClick={() => {
@@ -110,7 +111,9 @@ function DetailPerbekelDariMasa() {
>
<IconX size={20} />
</Button>
</Tooltip>
<Tooltip label="Edit Perbekel" withArrow position="top">
<Button
color="green"
onClick={() => router.push(`/admin/desa/profile/profile-perbekel-dari-masa-ke-masa/${data.id}/edit`)}
@@ -120,6 +123,7 @@ function DetailPerbekelDariMasa() {
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -2,7 +2,7 @@
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import colors from '@/con/colors';
import ApiFetch from '@/lib/api-fetch';
import { Box, Button, Group, Image, Paper, Stack, Text, TextInput, Title } from '@mantine/core';
import { Box, Button, Group, Image, Paper, Stack, Text, TextInput, Title, Tooltip } from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -50,9 +50,11 @@ function CreatePerbekelDariMasaKeMasa() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Back button + Title */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Create Perbekel Dari Masa Ke Masa
</Title>

View File

@@ -1,6 +1,6 @@
'use client'
import colors from '@/con/colors';
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
import { Box, Button, Center, Group, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -49,6 +49,7 @@ function ListPerbekelDariMasaKeMasa({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
<Group justify='space-between' mb="md">
<Title order={4}>List Perbekel Dari Masa Ke Masa</Title>
<Tooltip label="Tambah Perbekel Baru" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
@@ -57,6 +58,7 @@ function ListPerbekelDariMasaKeMasa({ search }: { search: string }) {
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: "auto" }}>

View File

@@ -4,9 +4,9 @@ import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
import stateProfileDesa from '@/app/admin/(dashboard)/_state/desa/profile';
import colors from '@/con/colors';
import ApiFetch from '@/lib/api-fetch';
import { Box, Button, Center, Group, Image, Paper, Stack, Text, Title } from '@mantine/core';
import { Box, Button, Center, Group, Image, Paper, Stack, Text, Title, Tooltip } from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconImageInPicture, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
import { IconArrowBack, IconPhoto, IconUpload, IconX, IconImageInPicture } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
@@ -101,9 +101,11 @@ function ProfilePerbekel() {
<Stack gap="xs">
{/* Header */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Profil Perbekel
</Title>

View File

@@ -1,7 +1,7 @@
'use client'
import colors from '@/con/colors';
import { Box, Button, Center, Divider, Grid, GridCol, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
import { Box, Button, Center, Divider, Grid, GridCol, Image, Paper, Skeleton, Stack, Text, Title, Tooltip } from '@mantine/core';
import { IconEdit } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useEffect } from 'react';
@@ -36,6 +36,7 @@ function Page() {
<Title order={3} c={colors['blue-button']}>Preview Profil PPID</Title>
</GridCol>
<GridCol span={{ base: 12, md: 1 }}>
<Tooltip label="Edit Profil Perbekel" withArrow>
<Button
c="green"
variant="light"
@@ -45,6 +46,7 @@ function Page() {
>
Edit
</Button>
</Tooltip>
</GridCol>
</Grid>

View File

@@ -24,7 +24,8 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
label: "Produk Pasar Desa",
value: "produkpasardesa",
href: "/admin/ekonomi/pasar-desa/produk-pasar-desa",
icon: <IconShoppingBag size={18} stroke={1.8} />
icon: <IconShoppingBag size={18} stroke={1.8} />,
tooltip: "Kelola data produk yang ada di pasar desa",
},
{
label: "Kategori Produk",

View File

@@ -5,6 +5,7 @@ import {
Box,
Button,
Group,
Image,
Paper,
Stack,
Text,
@@ -20,7 +21,6 @@ import { useProxy } from 'valtio/utils';
import CreateEditor from '../../../_com/createEditor';
import desaDigitalState from '../../../_state/inovasi/desa-digital';
import { Dropzone } from '@mantine/dropzone';
import ExifOrientationImg from 'react-exif-orientation-img';
export default function CreateDesaDigital() {
const stateDesaDigital = useProxy(desaDigitalState);
@@ -173,16 +173,17 @@ export default function CreateDesaDigital() {
overflow: 'hidden',
}}
>
<ExifOrientationImg
src={previewImage}
alt="Preview"
style={{
maxHeight: 220,
objectFit: 'cover',
border: '1px solid #e0e0e0',
borderRadius: 12,
}}
/>
<Image
src={previewImage}
alt="Preview"
radius="md"
style={{
maxHeight: 220,
objectFit: 'cover',
border: '1px solid #e0e0e0',
}}
loading="lazy"
/>
</Box>
)}
</Box>

View File

@@ -54,8 +54,8 @@ function DetailInfoTeknologiTepatGuna() {
{/* Card Utama */}
<Paper
withBorder
w={{ base: "100%", md: "50%" }}
bg={colors['white-1']}
w={{ base: "100%", md: "70%", lg: "60%" }}
bg="#ECEEF8"
p="lg"
radius="md"
shadow="sm"
@@ -65,7 +65,7 @@ function DetailInfoTeknologiTepatGuna() {
Detail Info Teknologi Tepat Guna
</Text>
<Paper bg="#ECEEF8" p="md" radius="md" shadow="xs">
<Paper bg={colors['BG-trans']} p="md" radius="md" shadow="xs">
<Stack gap="sm">
<Box>
<Text fz="lg" fw="bold">Judul</Text>

View File

@@ -1,7 +1,6 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
import { IconKey } from '@/app/admin/(dashboard)/_com/iconMap';
import programKreatifState from '@/app/admin/(dashboard)/_state/inovasi/program-kreatif';
import colors from '@/con/colors';
import {
@@ -12,7 +11,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -20,6 +20,7 @@ import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
import { useProxy } from 'valtio/utils';
import SelectIconProgramEdit from '../../../../_com/selectIconEdit';
import { IconKey } from '@/app/admin/(dashboard)/_com/iconMap';
interface FormProgramKreatif {
name: string;
@@ -40,15 +41,6 @@ function EditProgramKreatifDesa() {
icon: '',
});
const [originalData, setOriginalData] = useState<FormProgramKreatif>({
name: '',
deskripsi: '',
slug: '',
icon: '',
});
const [isDataChanged, setIsDataChanged] = useState(false);
// Load data hanya sekali berdasarkan params.id
useEffect(() => {
const loadProgramKreatif = async () => {
@@ -59,14 +51,12 @@ function EditProgramKreatifDesa() {
const data = await stateProgramKreatif.update.load(id);
if (data) {
stateProgramKreatif.update.id = id;
const loadedData = {
setFormData({
name: data.name || '',
slug: data.slug || '',
deskripsi: data.deskripsi || '',
icon: data.icon || '',
};
setFormData(loadedData);
setOriginalData(loadedData);
});
}
} catch (error) {
console.error('Error loading program kreatif:', error);
@@ -77,49 +67,12 @@ function EditProgramKreatifDesa() {
loadProgramKreatif();
}, [params?.id]);
// Deteksi perubahan data
useEffect(() => {
const hasChanged =
formData.name !== originalData.name ||
formData.slug !== originalData.slug ||
formData.deskripsi !== originalData.deskripsi ||
formData.icon !== originalData.icon;
setIsDataChanged(hasChanged);
}, [formData, originalData]);
// Prevent browser back/refresh jika ada perubahan
useEffect(() => {
const handleBeforeUnload = (e: BeforeUnloadEvent) => {
if (isDataChanged) {
e.preventDefault();
e.returnValue = '';
}
};
window.addEventListener('beforeunload', handleBeforeUnload);
return () => window.removeEventListener('beforeunload', handleBeforeUnload);
}, [isDataChanged]);
const handleChange =
(field: keyof FormProgramKreatif) =>
(value: string) => {
setFormData((prev) => ({ ...prev, [field]: value }));
};
const handleBackClick = () => {
if (isDataChanged) {
const confirmed = window.confirm(
'Anda memiliki perubahan yang belum disimpan. Apakah Anda yakin ingin keluar dari halaman ini? Semua perubahan akan hilang.'
);
if (confirmed) {
router.back();
}
} else {
router.back();
}
};
const handleSubmit = async () => {
try {
stateProgramKreatif.update.form = {
@@ -129,11 +82,6 @@ function EditProgramKreatifDesa() {
icon: formData.icon.trim(),
};
await stateProgramKreatif.update.submit();
// Reset isDataChanged agar tidak muncul konfirmasi setelah save
setOriginalData(formData);
setIsDataChanged(false);
router.push('/admin/inovasi/program-kreatif-desa');
} catch (error) {
console.error('Error updating program kreatif:', error);
@@ -144,14 +92,16 @@ function EditProgramKreatifDesa() {
return (
<Box px={{ base: 'sm', md: 'lg' }} py="md">
<Group mb="md">
<Button
variant="subtle"
onClick={handleBackClick}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Program Kreatif Desa
</Title>
@@ -222,4 +172,4 @@ function EditProgramKreatifDesa() {
);
}
export default EditProgramKreatifDesa;
export default EditProgramKreatifDesa;

View File

@@ -32,14 +32,10 @@ function CreateProgramKreatifDesa() {
};
const handleSubmit = async () => {
const success = await stateCreate.create.create();
if (success) {
resetForm();
router.push("/admin/inovasi/program-kreatif-desa");
}
await stateCreate.create.create();
resetForm();
router.push("/admin/inovasi/program-kreatif-desa");
};
return (
<Box px={{ base: 'sm', md: 'lg' }} py="md">

View File

@@ -10,7 +10,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from "@mantine/core";
import {
IconArrowBack,
@@ -115,14 +116,16 @@ function EditKeamananLingkungan() {
<Box px={{ base: "sm", md: "lg" }} py="md">
{/* Header */}
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Keamanan Lingkungan
</Title>

View File

@@ -1,7 +1,7 @@
'use client'
import { useProxy } from 'valtio/utils';
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -93,32 +93,36 @@ function DetailKeamananLingkungan() {
{/* Aksi */}
<Group gap="sm">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
<Tooltip label="Hapus Data" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Button
color="green"
onClick={() =>
router.push(
`/admin/keamanan/keamanan-lingkungan-pecalang-patwal/${data.id}/edit`
)
}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
<Tooltip label="Edit Data" withArrow position="top">
<Button
color="green"
onClick={() =>
router.push(
`/admin/keamanan/keamanan-lingkungan-pecalang-patwal/${data.id}/edit`
)
}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -10,7 +10,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import {
@@ -70,14 +71,16 @@ function CreateKeamananLingkungan() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Data Keamanan Lingkungan
</Title>

View File

@@ -16,7 +16,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
@@ -77,16 +78,18 @@ function ListKeamananLingkungan({ search }: { search: string }) {
{/* Judul + Tombol Tambah */}
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Keamanan Lingkungan</Title>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() =>
router.push('/admin/keamanan/keamanan-lingkungan-pecalang-patwal/create')
}
>
Tambah Baru
</Button>
<Tooltip label="Tambah Data Keamanan" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() =>
router.push('/admin/keamanan/keamanan-lingkungan-pecalang-patwal/create')
}
>
Tambah Baru
</Button>
</Tooltip>
</Group>
{/* Tabel */}

View File

@@ -1,7 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
import { IconPhone, IconTag } from '@tabler/icons-react';
import { usePathname, useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
@@ -15,13 +15,15 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
label: "Kontak Darurat Keamanan",
value: "kontak-darurat-keamanan",
href: "/admin/keamanan/kontak-darurat/kontak-darurat-keamanan",
icon: <IconPhone size={18} stroke={1.8} />
icon: <IconPhone size={18} stroke={1.8} />,
tooltip: "Lihat dan kelola kontak darurat keamanan",
},
{
label: "Kontak Darurat Item",
value: "kontak-darurat-item",
href: "/admin/keamanan/kontak-darurat/kontak-darurat-item",
icon: <IconTag size={18} stroke={1.8} />
icon: <IconTag size={18} stroke={1.8} />,
tooltip: "Kelola data kontak darurat item",
}
];
@@ -71,18 +73,19 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
}}
>
{tabs.map((tab, i) => (
<TabsTab
key={i}
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
<Tooltip key={i} label={tab.tooltip} position="bottom" withArrow transitionProps={{ transition: 'pop', duration: 200 }}>
<TabsTab
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
</Tooltip>
))}
</TabsList>
</ScrollArea>

View File

@@ -12,7 +12,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -85,9 +86,11 @@ function EditKontakItem() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Kontak Darurat Item
</Title>

View File

@@ -3,7 +3,7 @@ import { IconKey, IconMapper } from '@/app/admin/(dashboard)/_com/iconMap';
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import kontakDarurat from '@/app/admin/(dashboard)/_state/keamanan/kontak-darurat-keamanan';
import colors from '@/con/colors';
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -92,28 +92,32 @@ function DetailKontakDarurat() {
{/* Aksi */}
<Group gap="sm">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
<Tooltip label="Hapus Data" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/kontak-darurat/kontak-darurat-item/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
<Tooltip label="Edit Data" withArrow position="top">
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/kontak-darurat/kontak-darurat-item/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -10,7 +10,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
@@ -37,14 +38,16 @@ function CreateKontakItem() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Kontak Darurat Item
</Title>

View File

@@ -16,7 +16,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
@@ -78,14 +79,16 @@ function ListKontakItem({ search }: { search: string }) {
{/* Judul + Tombol Tambah */}
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Kontak Darurat Item</Title>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/kontak-darurat/kontak-darurat-item/create')}
>
Tambah Baru
</Button>
<Tooltip label="Tambah Kontak Item" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/kontak-darurat/kontak-darurat-item/create')}
>
Tambah Baru
</Button>
</Tooltip>
</Group>
{/* Tabel */}

View File

@@ -14,7 +14,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from "@mantine/core";
import { IconArrowBack } from "@tabler/icons-react";
import { useParams, useRouter } from "next/navigation";
@@ -41,7 +42,7 @@ function EditKontakDaruratKeamanan() {
try {
setIsLoading(true);
await kontakDarurat.kontakDaruratItem.findMany.load();
const id = params?.id as string;
if (id) {
const data = await kontakState.update.load(id);
@@ -87,14 +88,16 @@ function EditKontakDaruratKeamanan() {
<Box px={{ base: "sm", md: "lg" }} py="md">
{/* Header */}
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Kontak Darurat Keamanan
</Title>

View File

@@ -3,7 +3,7 @@ import { IconKey, IconMapper } from '@/app/admin/(dashboard)/_com/iconMap';
import { ModalKonfirmasiHapus } from '@/app/admin/(dashboard)/_com/modalKonfirmasiHapus';
import kontakDarurat from '@/app/admin/(dashboard)/_state/keamanan/kontak-darurat-keamanan';
import colors from '@/con/colors';
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -108,28 +108,32 @@ function DetailKontakDaruratKeamanan() {
{/* Aksi */}
<Group gap="sm">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
<Tooltip label="Hapus Data" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/kontak-darurat/kontak-darurat-keamanan/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
<Tooltip label="Edit Data" withArrow position="top">
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/kontak-darurat/kontak-darurat-keamanan/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -11,7 +11,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack } from '@tabler/icons-react';
@@ -44,14 +45,16 @@ function CreateKontakDaruratKeamanan() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Kontak Darurat Keamanan
</Title>

View File

@@ -16,7 +16,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
@@ -78,14 +79,16 @@ function ListKontakDaruratKeamanan({ search }: { search: string }) {
{/* Judul + Tombol Tambah */}
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Kontak Darurat Keamanan</Title>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/kontak-darurat/kontak-darurat-keamanan/create')}
>
Tambah Baru
</Button>
<Tooltip label="Tambah Kontak Darurat Keamanan" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/kontak-darurat/kontak-darurat-keamanan/create')}
>
Tambah Baru
</Button>
</Tooltip>
</Group>
{/* Tabel */}

View File

@@ -1,4 +1,3 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import EditEditor from '@/app/admin/(dashboard)/_com/editEditor';
import laporanPublikState from '@/app/admin/(dashboard)/_state/keamanan/laporan-publik';
@@ -12,7 +11,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { DateTimePicker } from '@mantine/dates';
import { IconArrowBack } from '@tabler/icons-react';
@@ -48,29 +48,29 @@ function EditLaporanPublik() {
const loadLaporanPublik = async () => {
const id = params?.id as string;
if (!id) return;
try {
const data = await stateLaporan.edit.load(id);
if (data) {
setFormData({
judul: data.judul ?? '',
lokasi: data.lokasi ?? '',
tanggalWaktu: data.tanggalWaktu ?? '',
status: (data.status as Status) ?? 'Proses',
penanganan: data.penanganan?.[0]?.deskripsi ?? '',
kronologi: data.kronologi ?? '',
});
setFormData((prev) => ({
...prev,
judul: data.judul ?? prev.judul,
lokasi: data.lokasi ?? prev.lokasi,
tanggalWaktu: data.tanggalWaktu ?? prev.tanggalWaktu,
status: (data.status as Status) ?? prev.status,
penanganan: data.penanganan?.[0]?.deskripsi ?? prev.penanganan,
kronologi: data.kronologi ?? prev.kronologi,
}));
}
} catch (error) {
console.error("Error loading laporan publik:", error);
toast.error("Gagal mengambil data laporan publik");
}
};
loadLaporanPublik();
}, [params?.id]);
}, [params?.id, stateLaporan.edit]);
const handleChange = (field: string, value: string | Status) => {
setFormData((prev) => ({ ...prev, [field]: value }));
@@ -96,9 +96,11 @@ function EditLaporanPublik() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Laporan Publik
</Title>

View File

@@ -7,15 +7,16 @@ import {
Paper,
Skeleton,
Stack,
Text
Text,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
import laporanPublikState from '../../../_state/keamanan/laporan-publik';
import { useState } from 'react';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
function DetailLaporanPublik() {
const [modalHapus, setModalHapus] = useState(false);
@@ -101,12 +102,12 @@ function DetailLaporanPublik() {
padding: '4px 12px',
borderRadius: '16px',
backgroundColor:
data.status === 'Selesai' ? '#94EF95FF' :
data.status === 'Proses' ? '#F1D295FF' :
data.status === 'Selesai' ? '#94EF95FF' :
data.status === 'Proses' ? '#F1D295FF' :
'#F38E8EFF',
color:
data.status === 'Selesai' ? '#01BA01FF' :
data.status === 'Proses' ? '#B67A00FF' :
data.status === 'Selesai' ? '#01BA01FF' :
data.status === 'Proses' ? '#B67A00FF' :
'#AE1700FF',
fontWeight: 900,
fontSize: '0.75rem',
@@ -145,31 +146,35 @@ function DetailLaporanPublik() {
{/* Tombol Aksi */}
<Group gap="sm" mt="sm">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
disabled={stateLaporan.delete.loading}
>
<IconTrash size={20} />
</Button>
<Tooltip label="Hapus Laporan Publik" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
disabled={stateLaporan.delete.loading}
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Button
color="green"
onClick={() =>
router.push(`/admin/keamanan/laporan-publik/${data.id}/edit`)
}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
<Tooltip label="Edit Laporan Publik" withArrow position="top">
<Button
color="green"
onClick={() =>
router.push(`/admin/keamanan/laporan-publik/${data.id}/edit`)
}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -8,7 +8,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip
} from '@mantine/core';
import { DateTimePicker } from '@mantine/dates';
import { IconArrowBack } from '@tabler/icons-react';
@@ -41,9 +42,11 @@ function CreateLaporanPublik() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header with Back Button */}
<Group mb="md">
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Laporan Publik
</Title>

View File

@@ -5,8 +5,8 @@ import {
Button,
Center,
Group,
Pagination,
Paper,
Pagination,
Skeleton,
Stack,
Table,
@@ -16,15 +16,16 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImac, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../_com/header';
import { useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
import laporanPublikState from '../../_state/keamanan/laporan-publik';
import { useShallowEffect } from '@mantine/hooks';
import { useState } from 'react';
function LaporanPublik() {
const [search, setSearch] = useState("");
@@ -73,14 +74,16 @@ function ListLaporanPublik({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Laporan Publik</Title>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/laporan-publik/create')}
>
Tambah Baru
</Button>
<Tooltip label="Tambah Laporan Publik" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/laporan-publik/create')}
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: "auto" }}>
<Table highlightOnHover>

View File

@@ -12,7 +12,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
@@ -95,14 +96,16 @@ function EditPencegahanKriminalitas() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Back button + Title */}
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Pencegahan Kriminalitas
</Title>

View File

@@ -1,10 +1,10 @@
'use client'
import colors from '@/con/colors';
import { Box, Button, Flex, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { Box, Button, Flex, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useRouter, useParams } from 'next/navigation';
import { useState } from 'react';
import { useShallowEffect } from '@mantine/hooks';
import { useProxy } from 'valtio/utils';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
import pencegahanKriminalitasState from '../../../_state/keamanan/pencegahan-kriminalitas';
@@ -108,28 +108,32 @@ function DetailPencegahanKriminalitas() {
{/* Tombol Aksi */}
<Flex gap="sm" mt="sm">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
<Tooltip label="Hapus" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/pencegahan-kriminalitas/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
<Tooltip label="Edit" withArrow position="top">
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/pencegahan-kriminalitas/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Flex>
</Stack>
</Paper>

View File

@@ -9,16 +9,17 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { toast } from 'react-toastify';
import { useProxy } from 'valtio/utils';
import CreateEditor from '../../../_com/createEditor';
import pencegahanKriminalitasState from '../../../_state/keamanan/pencegahan-kriminalitas';
import { useState } from 'react';
import { convertYoutubeUrlToEmbed } from '../../../desa/gallery/lib/youtube-utils';
import { toast } from 'react-toastify';
function CreatePencegahanKriminalitas() {
const router = useRouter();
@@ -52,6 +53,7 @@ function CreatePencegahanKriminalitas() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header Back Button + Title */}
<Group mb="md">
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
@@ -60,6 +62,7 @@ function CreatePencegahanKriminalitas() {
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Pencegahan Kriminalitas
</Title>

View File

@@ -16,15 +16,16 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../_com/header';
import { useRouter } from 'next/navigation';
import { useProxy } from 'valtio/utils';
import pencegahanKriminalitasState from '../../_state/keamanan/pencegahan-kriminalitas';
import { useShallowEffect } from '@mantine/hooks';
import { useState } from 'react';
function PencegahanKriminalitas() {
const [search, setSearch] = useState("");
@@ -76,14 +77,16 @@ function ListPencegahanKriminalitas({ search }: { search: string }) {
{/* Judul + Tombol Tambah */}
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Pencegahan Kriminalitas</Title>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/pencegahan-kriminalitas/create')}
>
Tambah Baru
</Button>
<Tooltip label="Tambah Program Pencegahan" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/pencegahan-kriminalitas/create')}
>
Tambah Baru
</Button>
</Tooltip>
</Group>
{/* Tabel */}
@@ -103,9 +106,9 @@ function ListPencegahanKriminalitas({ search }: { search: string }) {
<TableTr key={item.id}>
<TableTd>
<Box w={200}>
<Text fw={500} truncate="end" lineClamp={1}>
{item.judul}
</Text>
<Text fw={500} truncate="end" lineClamp={1}>
{item.judul}
</Text>
</Box>
</TableTd>
<TableTd>

View File

@@ -2,7 +2,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client";
import polsekTerdekat from "@/app/admin/(dashboard)/_state/keamanan/polsek-terdekat";
import colors from "@/con/colors";
import {
Box,
@@ -15,13 +14,15 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from "@mantine/core";
import { IconArrowBack } from "@tabler/icons-react";
import { useParams, useRouter } from "next/navigation";
import { useProxy } from "valtio/utils";
import { useEffect, useState } from "react";
import { toast } from "react-toastify";
import { useProxy } from "valtio/utils";
import polsekTerdekat from "@/app/admin/(dashboard)/_state/keamanan/polsek-terdekat";
function EditPolsekTerdekat() {
const polsekState = useProxy(polsekTerdekat);
@@ -51,36 +52,36 @@ function EditPolsekTerdekat() {
layananPolsekId: "",
});
// load data untuk form edit
useEffect(() => {
const loadPolsekTerdekat = async () => {
const id = params?.id as string;
if (!id) return;
try {
const data = await polsekState.edit.load(id);
if (data) {
setFormData({
nama: data.nama || "",
jarakKeDesa: data.jarakKeDesa || "",
alamat: data.alamat || "",
nomorTelepon: data.nomorTelepon || "",
jamOperasional: data.jamOperasional || "",
embedMapUrl: data.embedMapUrl || "",
namaTempatMaps: data.namaTempatMaps || "",
alamatMaps: data.alamatMaps || "",
linkPetunjukArah: data.linkPetunjukArah || "",
layananPolsekId: data.layananPolsekId || "",
});
// load data untuk form edit
useEffect(() => {
const loadPolsekTerdekat = async () => {
const id = params?.id as string;
if (!id) return;
try {
const data = await polsekState.edit.load(id);
if (data) {
setFormData({
nama: data.nama || "",
jarakKeDesa: data.jarakKeDesa || "",
alamat: data.alamat || "",
nomorTelepon: data.nomorTelepon || "",
jamOperasional: data.jamOperasional || "",
embedMapUrl: data.embedMapUrl || "",
namaTempatMaps: data.namaTempatMaps || "",
alamatMaps: data.alamatMaps || "",
linkPetunjukArah: data.linkPetunjukArah || "",
layananPolsekId: data.layananPolsekId || "",
});
}
} catch (error) {
console.error("Error loading polsek terdekat:", error);
toast.error("Gagal memuat data polsek terdekat");
}
} catch (error) {
console.error("Error loading polsek terdekat:", error);
toast.error("Gagal memuat data polsek terdekat");
}
};
loadPolsekTerdekat();
}, [params?.id]);
};
loadPolsekTerdekat();
}, [params?.id]);
const fetchLayanan = async () => {
try {
@@ -247,14 +248,16 @@ function EditPolsekTerdekat() {
{/* Header */}
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Polsek Terdekat
</Title>

View File

@@ -1,13 +1,13 @@
'use client'
import colors from '@/con/colors';
import { Box, Button, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { Box, Button, Group, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import polsekTerdekat from '../../../_state/keamanan/polsek-terdekat';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
import polsekTerdekat from '../../../_state/keamanan/polsek-terdekat';
function DetailPolsekTerdekat() {
const router = useRouter();
@@ -157,28 +157,32 @@ function DetailPolsekTerdekat() {
{/* Aksi */}
<Group gap="sm">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
<Tooltip label="Hapus Data" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/polsek-terdekat/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
<Tooltip label="Edit Data" withArrow position="top">
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/polsek-terdekat/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -11,14 +11,15 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { IconArrowBack } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
import { useProxy } from 'valtio/utils';
import polsekTerdekat from '../../../_state/keamanan/polsek-terdekat';
import { useEffect, useState } from 'react';
import { toast } from 'react-toastify';
function CreatePolsekTerdekat() {
const polsekState = useProxy(polsekTerdekat);
@@ -121,14 +122,16 @@ function CreatePolsekTerdekat() {
{/* Header */}
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Polsek Terdekat
</Title>

View File

@@ -16,7 +16,8 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImac, IconPlus, IconSearch } from '@tabler/icons-react';
@@ -75,14 +76,16 @@ function ListPolsekTerdekat({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Polsek Terdekat</Title>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/polsek-terdekat/create')}
>
Tambah Baru
</Button>
<Tooltip label="Tambah Polsek" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/polsek-terdekat/create')}
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: "auto" }}>
@@ -107,11 +110,11 @@ function ListPolsekTerdekat({ search }: { search: string }) {
</Box>
</TableTd>
<TableTd>{item.jarakKeDesa}</TableTd>
<TableTd>
<Box w={150}>
<TableTd>
<Box w={150}>
<Text truncate="end" lineClamp={1}>{item.alamat}</Text>
</Box>
</TableTd>
</Box>
</TableTd>
<TableTd>
<Button
variant="light"

View File

@@ -9,7 +9,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from "@mantine/core";
import {
IconArrowBack,
@@ -104,14 +105,16 @@ function EditTipsKeamanan() {
<Box px={{ base: "sm", md: "lg" }} py="md">
{/* Header */}
<Group mb="md">
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button
variant="subtle"
onClick={() => router.back()}
p="xs"
radius="md"
>
<IconArrowBack color={colors["blue-button"]} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Tips Keamanan
</Title>

View File

@@ -1,10 +1,10 @@
'use client'
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
import { useProxy } from 'valtio/utils';
import { Box, Button, Group, Image, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconArrowBack, IconEdit, IconTrash } from '@tabler/icons-react';
import { useParams, useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import colors from '@/con/colors';
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
@@ -99,29 +99,33 @@ function DetailTipsKeamanan() {
</Box>
<Group gap="sm">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
disabled={stateKeamanan.delete.loading}
>
<IconTrash size={20} />
</Button>
<Tooltip label="Hapus Tips Keamanan" withArrow position="top">
<Button
color="red"
onClick={() => {
setSelectedId(data.id);
setModalHapus(true);
}}
variant="light"
radius="md"
size="md"
disabled={stateKeamanan.delete.loading}
>
<IconTrash size={20} />
</Button>
</Tooltip>
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/tips-keamanan/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
<Tooltip label="Edit Tips Keamanan" withArrow position="top">
<Button
color="green"
onClick={() => router.push(`/admin/keamanan/tips-keamanan/${data.id}/edit`)}
variant="light"
radius="md"
size="md"
>
<IconEdit size={20} />
</Button>
</Tooltip>
</Group>
</Stack>
</Paper>

View File

@@ -10,7 +10,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
@@ -65,9 +66,11 @@ function CreateKeamananLingkungan() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header Back + Title */}
<Group mb="md">
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Tambah Tips Keamanan
</Title>

View File

@@ -16,13 +16,14 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
Tooltip,
} from '@mantine/core';
import { useShallowEffect } from '@mantine/hooks';
import { IconDeviceImac, IconPlus, IconSearch } from '@tabler/icons-react';
import { useRouter } from 'next/navigation';
import { useState } from 'react';
import { useProxy } from 'valtio/utils';
import { useState } from 'react';
import HeaderSearch from '../../_com/header';
import tipsKeamananState from '../../_state/keamanan/tips-keamanan';
@@ -73,14 +74,16 @@ function ListTipsKeamanan({ search }: { search: string }) {
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
<Group justify="space-between" mb="md">
<Title order={4}>Daftar Tips Keamanan</Title>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/tips-keamanan/create')}
>
Tambah Baru
</Button>
<Tooltip label="Tambah Tips Keamanan" withArrow>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/keamanan/tips-keamanan/create')}
>
Tambah Baru
</Button>
</Tooltip>
</Group>
<Box style={{ overflowX: "auto" }}>
<Table highlightOnHover>

View File

@@ -1,7 +1,7 @@
/* eslint-disable react-hooks/exhaustive-deps */
'use client'
import colors from '@/con/colors';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title, Tooltip } from '@mantine/core';
import { IconActivity, IconBuildingHospital, IconCalendarEvent, IconGauge, IconNotes } from '@tabler/icons-react';
import { usePathname, useRouter } from 'next/navigation';
import React, { useEffect, useState } from 'react';
@@ -17,31 +17,36 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
label: "Presentase Kelahiran & Kematian",
value: "presentasekelahiran&kematian",
href: "/admin/kesehatan/data-kesehatan-warga/persentase_data_kelahiran_kematian",
icon: <IconActivity size={18} stroke={1.8} />
icon: <IconActivity size={18} stroke={1.8} />,
tooltip: "Lihat data kelahiran dan kematian"
},
{
label: "Grafik Hasil Kepuasan Masyarakat",
value: "grafikhasilkepuasan",
href: "/admin/kesehatan/data-kesehatan-warga/grafik_hasil_kepuasan",
icon: <IconGauge size={18} stroke={1.8} />
icon: <IconGauge size={18} stroke={1.8} />,
tooltip: "Grafik kepuasan masyarakat terhadap pelayanan"
},
{
label: "Fasilitas Kesehatan",
value: "fasilitaskesehatan",
href: "/admin/kesehatan/data-kesehatan-warga/fasilitas_kesehatan",
icon: <IconBuildingHospital size={18} stroke={1.8} />
icon: <IconBuildingHospital size={18} stroke={1.8} />,
tooltip: "Data fasilitas kesehatan desa"
},
{
label: "Jadwal Kegiatan",
value: "jadwalkegiatan",
href: "/admin/kesehatan/data-kesehatan-warga/jadwal_kegiatan",
icon: <IconCalendarEvent size={18} stroke={1.8} />
icon: <IconCalendarEvent size={18} stroke={1.8} />,
tooltip: "Atur jadwal kegiatan kesehatan"
},
{
label: "Artikel Kesehatan",
value: "artikelkesehatan",
href: "/admin/kesehatan/data-kesehatan-warga/artikel_kesehatan",
icon: <IconNotes size={18} stroke={1.8} />
icon: <IconNotes size={18} stroke={1.8} />,
tooltip: "Artikel & informasi seputar kesehatan"
},
];
@@ -95,39 +100,46 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
}}
>
{tabs.map((tab, i) => (
<TabsTab
<Tooltip
key={i}
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
label={tab.tooltip}
position="bottom"
withArrow
transitionProps={{ transition: 'pop', duration: 200 }}
>
{tab.label}
</TabsTab>
<TabsTab
value={tab.value}
leftSection={tab.icon}
style={{
fontWeight: 600,
fontSize: "0.9rem",
transition: "all 0.2s ease",
}}
>
{tab.label}
</TabsTab>
</Tooltip>
))}
</TabsList>
</ScrollArea>
</TabsList>
</ScrollArea>
{tabs.map((tab, i) => (
<TabsPanel
key={i}
value={tab.value}
style={{
padding: "1.5rem",
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
borderRadius: "1rem",
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
}}
>
{children}
</TabsPanel>
))}
</Tabs>
</Stack >
{tabs.map((tab, i) => (
<TabsPanel
key={i}
value={tab.value}
style={{
padding: "1.5rem",
background: "linear-gradient(180deg, #ffffff, #f5f6fa)",
borderRadius: "1rem",
boxShadow: "0 4px 16px rgba(0,0,0,0.05)",
}}
>
{children}
</TabsPanel>
))}
</Tabs>
</Stack>
);
}

View File

@@ -14,7 +14,8 @@ import {
Stack,
Text,
TextInput,
Title
Title,
Tooltip,
} from '@mantine/core';
import { Dropzone } from '@mantine/dropzone';
import { IconArrowBack, IconPhoto, IconUpload, IconX } from '@tabler/icons-react';
@@ -150,9 +151,11 @@ function EditArtikelKesehatan() {
<Box px={{ base: 'sm', md: 'lg' }} py="md">
{/* Header */}
<Group mb="md">
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
<Tooltip label="Kembali ke halaman sebelumnya" withArrow>
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
<IconArrowBack color={colors['blue-button']} size={24} />
</Button>
</Tooltip>
<Title order={4} ml="sm" c="dark">
Edit Artikel Kesehatan
</Title>

Some files were not shown because too many files have changed in this diff Show More