Compare commits
2 Commits
nico/11-de
...
nico/15-de
| Author | SHA1 | Date | |
|---|---|---|---|
| 342e9bbc65 | |||
| f6f77d9e35 |
@@ -1,14 +1,15 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
plugins: {
|
plugins: {
|
||||||
'postcss-preset-mantine': {},
|
'postcss-preset-mantine': {},
|
||||||
'postcss-simple-vars': {
|
'postcss-simple-vars': {
|
||||||
variables: {
|
variables: {
|
||||||
'mantine-breakpoint-xs': '36em',
|
/* Mobile first */
|
||||||
'mantine-breakpoint-sm': '48em',
|
'mantine-breakpoint-xs': '30em', // 480px → mobile kecil–normal
|
||||||
'mantine-breakpoint-md': '62em',
|
'mantine-breakpoint-sm': '48em', // 768px → tablet / mobile landscape
|
||||||
'mantine-breakpoint-lg': '75em',
|
'mantine-breakpoint-md': '64em', // 1024px → laptop & desktop kecil
|
||||||
'mantine-breakpoint-xl': '88em',
|
'mantine-breakpoint-lg': '80em', // 1280px → desktop standar
|
||||||
},
|
'mantine-breakpoint-xl': '90em', // 1440px+ → desktop besar
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
},
|
||||||
|
};
|
||||||
|
|||||||
@@ -44,18 +44,56 @@ function CreatePolsekTerdekat() {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isValidGoogleMapsEmbed = (url: string): boolean => {
|
||||||
|
try {
|
||||||
|
const u = new URL(url);
|
||||||
|
return (
|
||||||
|
u.hostname === 'www.google.com' &&
|
||||||
|
u.pathname === '/maps/embed' &&
|
||||||
|
u.searchParams.has('pb')
|
||||||
|
);
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
try {
|
const { embedMapUrl } = polsekState.create.form;
|
||||||
setIsSubmitting(true);
|
|
||||||
await polsekState.create.create();
|
// ✅ Validasi Google Maps Embed URL (jika diisi)
|
||||||
resetForm();
|
if (embedMapUrl && !isValidGoogleMapsEmbed(embedMapUrl)) {
|
||||||
router.push("/admin/keamanan/polsek-terdekat");
|
toast.error("URL embed peta tidak valid. Harap paste iframe dari Google Maps.");
|
||||||
} catch (error) {
|
return;
|
||||||
console.error(error)
|
}
|
||||||
toast.error("Gagal menambah polsek terdekat");
|
|
||||||
} finally {
|
try {
|
||||||
setIsSubmitting(false);
|
setIsSubmitting(true);
|
||||||
|
await polsekState.create.create();
|
||||||
|
resetForm();
|
||||||
|
router.push("/admin/keamanan/polsek-terdekat");
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
toast.error("Gagal menambah polsek terdekat");
|
||||||
|
} finally {
|
||||||
|
setIsSubmitting(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const extractEmbedUrl = (input: string): string => {
|
||||||
|
// Jika sudah berupa URL embed yang valid
|
||||||
|
if (input.startsWith('https://www.google.com/maps/embed?')) {
|
||||||
|
return input.trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Coba parse sebagai HTML string (iframe)
|
||||||
|
const iframeRegex = /<iframe[^>]*src=["']([^"']*)["'][^>]*>/i;
|
||||||
|
const match = input.match(iframeRegex);
|
||||||
|
if (match && match[1]?.startsWith('https://www.google.com/maps/embed?')) {
|
||||||
|
return match[1].trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika tidak cocok, kembalikan input asli (atau string kosong)
|
||||||
|
return input.trim();
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchLayanan = async () => {
|
const fetchLayanan = async () => {
|
||||||
@@ -190,9 +228,14 @@ function CreatePolsekTerdekat() {
|
|||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
value={polsekState.create.form.embedMapUrl}
|
value={polsekState.create.form.embedMapUrl}
|
||||||
onChange={(val) => (polsekState.create.form.embedMapUrl = val.target.value)}
|
onChange={(e) => {
|
||||||
|
const rawValue = e.currentTarget.value;
|
||||||
|
const cleanUrl = extractEmbedUrl(rawValue);
|
||||||
|
polsekState.create.form.embedMapUrl = cleanUrl;
|
||||||
|
}}
|
||||||
|
description="Contoh: https://www.google.com/maps/embed?pb=..."
|
||||||
label={<Text fw="bold" fz="sm">Embed Map URL</Text>}
|
label={<Text fw="bold" fz="sm">Embed Map URL</Text>}
|
||||||
placeholder="Masukkan embed map url"
|
placeholder="Paste iframe dari Google Maps atau URL embed langsung"
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
value={polsekState.create.form.namaTempatMaps}
|
value={polsekState.create.form.namaTempatMaps}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { useProxy } from 'valtio/utils';
|
|||||||
import HeaderSearch from '../../_com/header';
|
import HeaderSearch from '../../_com/header';
|
||||||
import sdgsDesa from '../../_state/landing-page/sdgs-desa';
|
import sdgsDesa from '../../_state/landing-page/sdgs-desa';
|
||||||
|
|
||||||
|
|
||||||
function SdgsDesa() {
|
function SdgsDesa() {
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
return (
|
return (
|
||||||
@@ -27,7 +26,7 @@ function SdgsDesa() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ListSdgsDesa({ search }: { search: string }) {
|
function ListSdgsDesa({ search }: { search: string }) {
|
||||||
const listState = useProxy(sdgsDesa)
|
const listState = useProxy(sdgsDesa);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
@@ -39,10 +38,10 @@ function ListSdgsDesa({ search }: { search: string }) {
|
|||||||
} = listState.findMany;
|
} = listState.findMany;
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 10, search)
|
load(page, 10, search);
|
||||||
}, [page, search])
|
}, [page, search]);
|
||||||
|
|
||||||
const filteredData = data || []
|
const filteredData = data || [];
|
||||||
|
|
||||||
// Handle loading state
|
// Handle loading state
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
@@ -53,79 +52,71 @@ function ListSdgsDesa({ search }: { search: string }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.length === 0) {
|
const isEmpty = data.length === 0;
|
||||||
return (
|
|
||||||
<Box py={10}>
|
|
||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
|
||||||
<Group justify="space-between" mb="md">
|
|
||||||
<Title order={4}>Daftar Sdgs Desa</Title>
|
|
||||||
<Button
|
|
||||||
leftSection={<IconPlus size={18} />}
|
|
||||||
color={colors['blue-button']}
|
|
||||||
variant="light"
|
|
||||||
onClick={() => router.push('/admin/landing-page/SDGs/create')}
|
|
||||||
>
|
|
||||||
Tambah Baru
|
|
||||||
</Button>
|
|
||||||
</Group>
|
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
|
||||||
<Table highlightOnHover striped verticalSpacing="sm">
|
|
||||||
<TableThead>
|
|
||||||
<TableTr>
|
|
||||||
<TableTh style={{ width: '60%' }}>Nama Sdgs Desa</TableTh>
|
|
||||||
<TableTh style={{ width: '20%' }}>Jumlah</TableTh>
|
|
||||||
<TableTh style={{ width: '20%', textAlign: 'center' }}>Aksi</TableTh>
|
|
||||||
</TableTr>
|
|
||||||
</TableThead>
|
|
||||||
<TableTbody>
|
|
||||||
<TableTr>
|
|
||||||
<TableTd colSpan={3} style={{ textAlign: 'center', padding: '2rem' }}>
|
|
||||||
<Text c="dimmed">Tidak ada data Sdgs Desa</Text>
|
|
||||||
</TableTd>
|
|
||||||
</TableTr>
|
|
||||||
</TableTbody>
|
|
||||||
</Table>
|
|
||||||
</Box>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py={{ base: 'sm', md: 'lg' }}>
|
||||||
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p={{ base: 'md', md: 'lg' }} shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb={{ base: 'sm', md: 'md' }}>
|
||||||
<Title order={4}>Daftar Sdgs Desa</Title>
|
<Title order={2} lh={1.2}>
|
||||||
<Button leftSection={<IconPlus size={18} />} color="blue" variant="light"
|
Daftar Sdgs Desa
|
||||||
onClick={() => router.push('/admin/landing-page/SDGs/create')}
|
</Title>
|
||||||
>
|
<Button
|
||||||
Tambah Baru
|
leftSection={<IconPlus size={18} />}
|
||||||
</Button>
|
color={colors['blue-button']}
|
||||||
|
variant="light"
|
||||||
|
onClick={() => router.push('/admin/landing-page/SDGs/create')}
|
||||||
|
>
|
||||||
|
Tambah Baru
|
||||||
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
|
||||||
<Table highlightOnHover>
|
{/* Desktop Table */}
|
||||||
|
<Box visibleFrom="md">
|
||||||
|
<Table highlightOnHover striped verticalSpacing="sm">
|
||||||
<TableThead>
|
<TableThead>
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTh style={{ width: '60%' }}>Nama Sdgs Desa</TableTh>
|
<TableTh style={{ width: '60%' }}>
|
||||||
<TableTh style={{ width: '20%' }}>Jumlah</TableTh>
|
<Text fz="sm" fw={600} c="dark.7" ta="left">
|
||||||
<TableTh style={{ width: '20%', textAlign: 'center' }}>Aksi</TableTh>
|
Nama Sdgs Desa
|
||||||
|
</Text>
|
||||||
|
</TableTh>
|
||||||
|
<TableTh style={{ width: '20%' }}>
|
||||||
|
<Text fz="sm" fw={600} c="dark.7" ta="left">
|
||||||
|
Jumlah
|
||||||
|
</Text>
|
||||||
|
</TableTh>
|
||||||
|
<TableTh style={{ width: '20%' }}>
|
||||||
|
<Text fz="sm" fw={600} c="dark.7" ta="center">
|
||||||
|
Aksi
|
||||||
|
</Text>
|
||||||
|
</TableTh>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
</TableThead>
|
</TableThead>
|
||||||
<TableTbody>
|
<TableTbody>
|
||||||
{filteredData.map((item) => (
|
{isEmpty ? (
|
||||||
<TableTr key={item.id}>
|
<TableTr>
|
||||||
<TableTd style={{ width: '60%' }}>
|
<TableTd colSpan={3} ta="center" py="xl">
|
||||||
<Text fw={500} truncate="end" lineClamp={1}>
|
<Text c="dimmed" fz="sm" lh={1.5}>
|
||||||
{item.name}
|
Tidak ada data Sdgs Desa
|
||||||
</Text>
|
</Text>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd style={{ width: '20%' }}>
|
</TableTr>
|
||||||
<Text fz="sm" c="dimmed">
|
) : (
|
||||||
{item.jumlah || '0'}
|
filteredData.map((item) => (
|
||||||
</Text>
|
<TableTr key={item.id}>
|
||||||
</TableTd>
|
<TableTd style={{ width: '60%' }}>
|
||||||
<TableTd style={{ width: '20%', textAlign: 'center' }}>
|
<Text fz="md" fw={500} truncate="end" lineClamp={1} lh={1.5}>
|
||||||
<Button
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd style={{ width: '20%' }}>
|
||||||
|
<Text fz="sm" c="dark.6" lh={1.5}>
|
||||||
|
{item.jumlah || '0'}
|
||||||
|
</Text>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd style={{ width: '20%' }} ta="center">
|
||||||
|
<Button
|
||||||
size="xs"
|
size="xs"
|
||||||
radius="md"
|
radius="md"
|
||||||
variant="light"
|
variant="light"
|
||||||
@@ -135,27 +126,69 @@ function ListSdgsDesa({ search }: { search: string }) {
|
|||||||
>
|
>
|
||||||
Detail
|
Detail
|
||||||
</Button>
|
</Button>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
))}
|
))
|
||||||
|
)}
|
||||||
</TableTbody>
|
</TableTbody>
|
||||||
</Table>
|
</Table>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{/* Mobile Cards */}
|
||||||
|
<Box hiddenFrom="md">
|
||||||
|
{isEmpty ? (
|
||||||
|
<Center py="xl">
|
||||||
|
<Text c="dimmed" fz="sm" lh={1.5} ta="center">
|
||||||
|
Tidak ada data Sdgs Desa
|
||||||
|
</Text>
|
||||||
|
</Center>
|
||||||
|
) : (
|
||||||
|
<Stack gap="sm">
|
||||||
|
{filteredData.map((item) => (
|
||||||
|
<Paper key={item.id} withBorder p="md" radius="md">
|
||||||
|
<Stack gap={4}>
|
||||||
|
<Text fz="sm" fw={600} lh={1.4}>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
<Text fz="xs" c="dark.6" lh={1.4}>
|
||||||
|
Jumlah: {item.jumlah || '0'}
|
||||||
|
</Text>
|
||||||
|
<Group justify="flex-end" mt="xs">
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
radius="md"
|
||||||
|
variant="light"
|
||||||
|
color="blue"
|
||||||
|
leftSection={<IconDeviceImacCog size={16} />}
|
||||||
|
onClick={() => router.push(`/admin/landing-page/SDGs/${item.id}`)}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
)}
|
||||||
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
<Center mt="lg">
|
|
||||||
<Pagination
|
{!isEmpty && (
|
||||||
value={page}
|
<Center mt={{ base: 'md', md: 'lg' }}>
|
||||||
onChange={(newPage) => {
|
<Pagination
|
||||||
load(newPage, 10);
|
value={page}
|
||||||
window.scrollTo(0, 0);
|
onChange={(newPage) => {
|
||||||
}}
|
load(newPage, 10);
|
||||||
total={Math.max(1, totalPages)}
|
window.scrollTo(0, 0);
|
||||||
withEdges
|
}}
|
||||||
radius="md"
|
total={Math.max(1, totalPages)}
|
||||||
/>
|
withEdges
|
||||||
</Center>
|
radius="md"
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SdgsDesa;
|
export default SdgsDesa;
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
import colors from "@/con/colors";
|
import colors from "@/con/colors";
|
||||||
import {
|
import {
|
||||||
|
Box,
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
Stack,
|
Stack,
|
||||||
Tabs,
|
Tabs,
|
||||||
@@ -68,37 +69,76 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
|
|||||||
keepMounted={false}
|
keepMounted={false}
|
||||||
>
|
>
|
||||||
{/* ✅ Scroll horizontal wrapper */}
|
{/* ✅ Scroll horizontal wrapper */}
|
||||||
<ScrollArea type="auto" offsetScrollbars>
|
<Box visibleFrom='md'>
|
||||||
<TabsList
|
<ScrollArea type="auto" offsetScrollbars>
|
||||||
p="sm"
|
<TabsList
|
||||||
style={{
|
p="sm"
|
||||||
background: "linear-gradient(135deg, #e7ebf7, #f9faff)",
|
style={{
|
||||||
borderRadius: "1rem",
|
background: "linear-gradient(135deg, #e7ebf7, #f9faff)",
|
||||||
boxShadow: "inset 0 0 10px rgba(0,0,0,0.05)",
|
borderRadius: "1rem",
|
||||||
display: "flex",
|
boxShadow: "inset 0 0 10px rgba(0,0,0,0.05)",
|
||||||
flexWrap: "nowrap",
|
display: "flex",
|
||||||
gap: "0.5rem",
|
flexWrap: "nowrap",
|
||||||
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
|
gap: "0.5rem",
|
||||||
}}
|
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
|
||||||
>
|
}}
|
||||||
{tabs.map((tab, i) => (
|
>
|
||||||
<TabsTab
|
{tabs.map((tab, i) => (
|
||||||
key={i}
|
<TabsTab
|
||||||
value={tab.value}
|
key={i}
|
||||||
leftSection={tab.icon}
|
value={tab.value}
|
||||||
style={{
|
leftSection={tab.icon}
|
||||||
fontWeight: 600,
|
style={{
|
||||||
fontSize: "0.9rem",
|
fontWeight: 600,
|
||||||
transition: "all 0.2s ease",
|
fontSize: "0.9rem",
|
||||||
flexShrink: 0, // ✅ mencegah tab mengecil
|
transition: "all 0.2s ease",
|
||||||
}}
|
flexShrink: 0, // ✅ jangan mengecil aneh-aneh
|
||||||
>
|
}}
|
||||||
{tab.label}
|
>
|
||||||
</TabsTab>
|
{tab.label}
|
||||||
))}
|
</TabsTab>
|
||||||
</TabsList>
|
))}
|
||||||
</ScrollArea>
|
</TabsList>
|
||||||
|
</ScrollArea>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box hiddenFrom='md'>
|
||||||
|
<ScrollArea
|
||||||
|
type="auto"
|
||||||
|
offsetScrollbars={false}
|
||||||
|
w="100%"
|
||||||
|
>
|
||||||
|
|
||||||
|
<TabsList
|
||||||
|
p="xs" // lebih kecil
|
||||||
|
style={{
|
||||||
|
background: "linear-gradient(135deg, #e7ebf7, #f9faff)",
|
||||||
|
borderRadius: "1rem",
|
||||||
|
display: "flex",
|
||||||
|
flexWrap: "nowrap",
|
||||||
|
gap: "0.5rem",
|
||||||
|
width: "max-content", // ⬅️ kunci
|
||||||
|
maxWidth: "100%", // ⬅️ penting
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tabs.map((tab, i) => (
|
||||||
|
<TabsTab
|
||||||
|
key={i}
|
||||||
|
value={tab.value}
|
||||||
|
leftSection={tab.icon}
|
||||||
|
style={{
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: "0.9rem",
|
||||||
|
paddingInline: "0.75rem", // ⬅️ lebih ramping
|
||||||
|
flexShrink: 0, // ✅ jangan mengecil aneh-aneh
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tab.label}
|
||||||
|
</TabsTab>
|
||||||
|
))}
|
||||||
|
</TabsList>
|
||||||
|
</ScrollArea>
|
||||||
|
</Box>
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<TabsPanel
|
<TabsPanel
|
||||||
key={i}
|
key={i}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ export default function EditKategoriDesaAntiKorupsi() {
|
|||||||
|
|
||||||
// 🧩 UI
|
// 🧩 UI
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export default function CreateKategoriDesaAntiKorupsi() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
|
|||||||
@@ -1,6 +1,23 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
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,
|
||||||
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
import { IconEdit, IconPlus, IconSearch, IconTrash } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -10,9 +27,8 @@ import HeaderSearch from '../../../_com/header';
|
|||||||
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
import { ModalKonfirmasiHapus } from '../../../_com/modalKonfirmasiHapus';
|
||||||
import korupsiState from '../../../_state/landing-page/desa-anti-korupsi';
|
import korupsiState from '../../../_state/landing-page/desa-anti-korupsi';
|
||||||
|
|
||||||
|
|
||||||
function KategoriDesaAntiKorupsi() {
|
function KategoriDesaAntiKorupsi() {
|
||||||
const [search, setSearch] = useState("")
|
const [search, setSearch] = useState('');
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<HeaderSearch
|
<HeaderSearch
|
||||||
@@ -28,126 +44,188 @@ function KategoriDesaAntiKorupsi() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ListKategoriKegiatan({ search }: { search: string }) {
|
function ListKategoriKegiatan({ search }: { search: string }) {
|
||||||
const stateKategori = useProxy(korupsiState.kategoriDesaAntiKorupsi)
|
const stateKategori = useProxy(korupsiState.kategoriDesaAntiKorupsi);
|
||||||
const [modalHapus, setModalHapus] = useState(false)
|
const [modalHapus, setModalHapus] = useState(false);
|
||||||
const [selectedId, setSelectedId] = useState<string | null>(null)
|
const [selectedId, setSelectedId] = useState<string | null>(null);
|
||||||
const router = useRouter()
|
const router = useRouter();
|
||||||
|
|
||||||
const {
|
const { data, page, totalPages, loading, load } = stateKategori.findMany;
|
||||||
data,
|
|
||||||
page,
|
|
||||||
totalPages,
|
|
||||||
loading,
|
|
||||||
load,
|
|
||||||
} = stateKategori.findMany;
|
|
||||||
|
|
||||||
const handleHapus = () => {
|
const handleHapus = () => {
|
||||||
if (selectedId) {
|
if (selectedId) {
|
||||||
stateKategori.delete.byId(selectedId)
|
stateKategori.delete.byId(selectedId);
|
||||||
setModalHapus(false)
|
setModalHapus(false);
|
||||||
setSelectedId(null)
|
setSelectedId(null);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 10, search)
|
load(page, 10, search);
|
||||||
}, [page, search])
|
}, [page, search]);
|
||||||
|
|
||||||
const filteredData = data || []
|
const filteredData = data || [];
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Stack py={10}>
|
<Stack py="xl">
|
||||||
<Skeleton height={600} radius="md" />
|
<Skeleton height={600} radius="md" />
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
// Mobile cards
|
||||||
<Box py={10}>
|
const renderMobileCards = () => (
|
||||||
<Paper bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
<Stack gap="md">
|
||||||
<Group justify="space-between" mb="md">
|
{filteredData.length > 0 ? (
|
||||||
<Title order={4}>Daftar Kategori Kegiatan</Title>
|
filteredData.map((item) => (
|
||||||
<Button
|
<Paper key={item.id} p="md" withBorder>
|
||||||
leftSection={<IconPlus size={18} />}
|
<Group justify="space-between" align="flex-start">
|
||||||
color="blue"
|
<Box flex={1}>
|
||||||
variant="light"
|
<Text fw={500} fz={{ base: 'sm', md: 'md' }} lh={1.45} lineClamp={2}>
|
||||||
onClick={() => router.push('/admin/landing-page/desa-anti-korupsi/kategori-desa-anti-korupsi/create')}
|
{item.name}
|
||||||
>
|
</Text>
|
||||||
Tambah Baru
|
</Box>
|
||||||
</Button>
|
<Group gap="xs" wrap="nowrap">
|
||||||
</Group>
|
<Button
|
||||||
<Box style={{ overflowX: "auto" }}>
|
variant="light"
|
||||||
<Table highlightOnHover striped verticalSpacing="sm">
|
color="green"
|
||||||
<TableThead>
|
size="xs"
|
||||||
<TableTr>
|
onClick={() => router.push(`/admin/landing-page/desa-anti-korupsi/kategori-desa-anti-korupsi/${item.id}`)}
|
||||||
<TableTh>Nama Kategori</TableTh>
|
>
|
||||||
<TableTh>Edit</TableTh>
|
<IconEdit size={16} />
|
||||||
<TableTh>Hapus</TableTh>
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="light"
|
||||||
|
color="red"
|
||||||
|
size="xs"
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedId(item.id);
|
||||||
|
setModalHapus(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconTrash size={16} />
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Group>
|
||||||
|
</Paper>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Paper p="xl" ta="center">
|
||||||
|
<Text c="dimmed" fz="sm" lh={1.4}>
|
||||||
|
Tidak ada data kategori yang ditemukan
|
||||||
|
</Text>
|
||||||
|
</Paper>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
);
|
||||||
|
|
||||||
|
// Desktop table
|
||||||
|
const renderDesktopTable = () => (
|
||||||
|
<Box>
|
||||||
|
<Table highlightOnHover striped verticalSpacing="sm" miw={300}>
|
||||||
|
<TableThead>
|
||||||
|
<TableTr>
|
||||||
|
<TableTh>
|
||||||
|
<Text fw={600} fz="sm" c="dimmed">
|
||||||
|
Nama Kategori
|
||||||
|
</Text>
|
||||||
|
</TableTh>
|
||||||
|
<TableTh>
|
||||||
|
<Text fw={600} fz="sm" c="dimmed">
|
||||||
|
Edit
|
||||||
|
</Text>
|
||||||
|
</TableTh>
|
||||||
|
<TableTh>
|
||||||
|
<Text fw={600} fz="sm" c="dimmed">
|
||||||
|
Hapus
|
||||||
|
</Text>
|
||||||
|
</TableTh>
|
||||||
|
</TableTr>
|
||||||
|
</TableThead>
|
||||||
|
<TableTbody>
|
||||||
|
{filteredData.length > 0 ? (
|
||||||
|
filteredData.map((item) => (
|
||||||
|
<TableTr key={item.id}>
|
||||||
|
<TableTd>
|
||||||
|
<Text fw={500} fz="md" lh={1.45} lineClamp={1}>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd w={60}>
|
||||||
|
<Button
|
||||||
|
variant="light"
|
||||||
|
color="green"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => router.push(`/admin/landing-page/desa-anti-korupsi/kategori-desa-anti-korupsi/${item.id}`)}
|
||||||
|
>
|
||||||
|
<IconEdit size={18} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd w={60}>
|
||||||
|
<Button
|
||||||
|
variant="light"
|
||||||
|
color="red"
|
||||||
|
size="sm"
|
||||||
|
onClick={() => {
|
||||||
|
setSelectedId(item.id);
|
||||||
|
setModalHapus(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<IconTrash size={18} />
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
</TableThead>
|
))
|
||||||
<TableTbody>
|
) : (
|
||||||
{filteredData.length > 0 ? (
|
<TableTr>
|
||||||
filteredData.map((item) => (
|
<TableTd colSpan={3} ta="center" py="xl">
|
||||||
<TableTr key={item.id}>
|
<Text c="dimmed" fz="sm" lh={1.4}>
|
||||||
<TableTd>
|
Tidak ada data kategori yang ditemukan
|
||||||
<Box w={200}>
|
</Text>
|
||||||
<Text fw={500} lineClamp={1}>{item.name}</Text>
|
</TableTd>
|
||||||
</Box>
|
</TableTr>
|
||||||
</TableTd>
|
)}
|
||||||
<TableTd>
|
</TableTbody>
|
||||||
<Button
|
</Table>
|
||||||
variant="light"
|
</Box>
|
||||||
color="green"
|
);
|
||||||
size="sm"
|
|
||||||
onClick={() => router.push(`/admin/landing-page/desa-anti-korupsi/kategori-desa-anti-korupsi/${item.id}`)}
|
return (
|
||||||
>
|
<Box py={{ base: 'xl', md: 'xl' }}>
|
||||||
<IconEdit size={18} />
|
<Paper bg={colors['white-1']} p={{ base: 'md', md: 'xl' }} shadow="md" radius="md">
|
||||||
</Button>
|
<Group justify="space-between" mb={{ base: 'md', md: 'lg' }}>
|
||||||
</TableTd>
|
<Title order={2} lh={1.2}>
|
||||||
<TableTd>
|
Daftar Kategori Kegiatan
|
||||||
<Button
|
</Title>
|
||||||
variant="light"
|
<Button
|
||||||
color="red"
|
leftSection={<IconPlus size={18} />}
|
||||||
size="sm"
|
color="blue"
|
||||||
onClick={() => {
|
variant="light"
|
||||||
setSelectedId(item.id);
|
onClick={() => router.push('/admin/landing-page/desa-anti-korupsi/kategori-desa-anti-korupsi/create')}
|
||||||
setModalHapus(true);
|
>
|
||||||
}}
|
Tambah Baru
|
||||||
>
|
</Button>
|
||||||
<IconTrash size={18} />
|
</Group>
|
||||||
</Button>
|
|
||||||
</TableTd>
|
<Box visibleFrom="md">{renderDesktopTable()}</Box>
|
||||||
</TableTr>
|
<Box hiddenFrom="md">{renderMobileCards()}</Box>
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<TableTr>
|
|
||||||
<TableTd colSpan={2}>
|
|
||||||
<Center py={20}>
|
|
||||||
<Text c="dimmed">Tidak ada data kategori yang ditemukan</Text>
|
|
||||||
</Center>
|
|
||||||
</TableTd>
|
|
||||||
</TableTr>
|
|
||||||
)}
|
|
||||||
</TableTbody>
|
|
||||||
</Table>
|
|
||||||
</Box>
|
|
||||||
</Paper>
|
</Paper>
|
||||||
<Center>
|
|
||||||
<Pagination
|
{totalPages > 1 && (
|
||||||
value={page}
|
<Center mt="xl">
|
||||||
onChange={(newPage) => {
|
<Pagination
|
||||||
load(newPage, 10);
|
value={page}
|
||||||
window.scrollTo({ top: 0, behavior: 'smooth' });
|
onChange={(newPage) => {
|
||||||
}}
|
load(newPage, 10);
|
||||||
total={totalPages}
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
||||||
mt="md"
|
}}
|
||||||
mb="md"
|
total={totalPages}
|
||||||
color="blue"
|
color="blue"
|
||||||
radius="md"
|
radius="md"
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
{/* Modal Konfirmasi Hapus */}
|
)}
|
||||||
|
|
||||||
<ModalKonfirmasiHapus
|
<ModalKonfirmasiHapus
|
||||||
opened={modalHapus}
|
opened={modalHapus}
|
||||||
onClose={() => setModalHapus(false)}
|
onClose={() => setModalHapus(false)}
|
||||||
@@ -158,4 +236,4 @@ function ListKategoriKegiatan({ search }: { search: string }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default KategoriDesaAntiKorupsi
|
export default KategoriDesaAntiKorupsi;
|
||||||
@@ -150,7 +150,7 @@ export default function EditDesaAntiKorupsi() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ export default function DetailKegiatanDesa() {
|
|||||||
const data = detailState.findUnique.data;
|
const data = detailState.findUnique.data;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box px={{ base: 0, md: 'xs' }} py="xs">
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -53,7 +53,7 @@ export default function DetailKegiatanDesa() {
|
|||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Paper
|
<Paper
|
||||||
w={{ base: "100%", md: "50%" }}
|
w={{ base: "100%", md: "70%" }}
|
||||||
bg={colors['white-1']}
|
bg={colors['white-1']}
|
||||||
p="lg"
|
p="lg"
|
||||||
radius="md"
|
radius="md"
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export default function CreateDesaAntiKorupsi() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ function ListDesaAntiKorupsi({ search }: { search: string }) {
|
|||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Stack py="md">
|
<Stack py={{ base: 'sm', md: 'md' }}>
|
||||||
<Skeleton height={650} radius="lg" />
|
<Skeleton height={650} radius="lg" />
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
@@ -46,11 +46,13 @@ function ListDesaAntiKorupsi({ search }: { search: string }) {
|
|||||||
|
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
return (
|
return (
|
||||||
<Box py="md">
|
<Box py={{ base: 'sm', md: 'md' }}>
|
||||||
<Paper p="lg" radius="lg" shadow="md" withBorder>
|
<Paper p={{ base: 'md', md: 'lg' }} radius="lg" shadow="md" withBorder>
|
||||||
<Stack align="center" gap="sm">
|
<Stack align="center" gap="sm">
|
||||||
<Title order={4}>Data Program Desa Anti Korupsi</Title>
|
<Title order={2} lh={1.2}>
|
||||||
<Text c="dimmed" ta="center">
|
Data Program Desa Anti Korupsi
|
||||||
|
</Title>
|
||||||
|
<Text c="dimmed" ta="center" fz={{ base: 'xs', md: 'sm' }} lh={1.5}>
|
||||||
Belum ada data program yang tersedia
|
Belum ada data program yang tersedia
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -61,48 +63,56 @@ function ListDesaAntiKorupsi({ search }: { search: string }) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Stack gap="md">
|
<Stack gap={'md'}>
|
||||||
<Paper p="lg" radius="lg" shadow="md" withBorder>
|
<Paper p={{ base: 'md', md: 'lg' }} radius="lg" shadow="md" withBorder>
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb={{ base: 'sm', md: 'md' }}>
|
||||||
<Title order={4}>Daftar Program Desa Anti Korupsi</Title>
|
<Title order={2} lh={1.2}>
|
||||||
<Button leftSection={<IconPlus size={18} />} color="blue" variant="light"
|
Daftar Program Desa Anti Korupsi
|
||||||
onClick={() => router.push('/admin/landing-page/desa-anti-korupsi/list-desa-anti-korupsi/create')}
|
</Title>
|
||||||
>
|
<Button
|
||||||
Tambah Baru
|
leftSection={<IconPlus size={18} />}
|
||||||
</Button>
|
color="blue"
|
||||||
|
variant="light"
|
||||||
|
onClick={() =>
|
||||||
|
router.push('/admin/landing-page/desa-anti-korupsi/list-desa-anti-korupsi/create')
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Tambah Baru
|
||||||
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
|
||||||
|
{/* Desktop Table */}
|
||||||
|
<Box visibleFrom="md">
|
||||||
<Table
|
<Table
|
||||||
striped
|
striped
|
||||||
highlightOnHover
|
highlightOnHover
|
||||||
|
|
||||||
withRowBorders
|
withRowBorders
|
||||||
verticalSpacing="sm"
|
verticalSpacing="sm"
|
||||||
>
|
>
|
||||||
<TableThead>
|
<TableThead>
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTh style={{ width: '50%' }}>Nama Program</TableTh>
|
<TableTh w="50%">Nama Program</TableTh>
|
||||||
<TableTh style={{ width: '30%' }}>Kategori</TableTh>
|
<TableTh w="30%">Kategori</TableTh>
|
||||||
<TableTh style={{ width: '20%', textAlign: 'center' }}>Aksi</TableTh>
|
<TableTh w="20%" ta="center">
|
||||||
|
Aksi
|
||||||
|
</TableTh>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
</TableThead>
|
</TableThead>
|
||||||
<TableTbody>
|
<TableTbody>
|
||||||
{filteredData.length > 0 ? (
|
{filteredData.length > 0 ? (
|
||||||
filteredData.map((item) => (
|
filteredData.map((item) => (
|
||||||
<TableTr key={item.id}>
|
<TableTr key={item.id}>
|
||||||
<TableTd style={{ width: '50%' }}>
|
<TableTd w="50%">
|
||||||
<Text fw={500} lineClamp={1}>
|
<Text fw={500} lineClamp={1} fz="md" lh={1.5}>
|
||||||
{item.name || '-'}
|
{item.name || '-'}
|
||||||
</Text>
|
</Text>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd style={{ width: '30%' }}>
|
<TableTd w="30%">
|
||||||
<Box w={200}>
|
<Text fz="sm" c="dimmed" lineClamp={1} lh={1.5}>
|
||||||
<Text fz="sm" c="dimmed" lineClamp={1}>
|
|
||||||
{item.kategori?.name || '-'}
|
{item.kategori?.name || '-'}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd style={{ width: '20%', textAlign: 'center' }}>
|
<TableTd w="20%" ta="center">
|
||||||
<Button
|
<Button
|
||||||
size="xs"
|
size="xs"
|
||||||
radius="md"
|
radius="md"
|
||||||
@@ -123,7 +133,7 @@ function ListDesaAntiKorupsi({ search }: { search: string }) {
|
|||||||
) : (
|
) : (
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTd colSpan={3}>
|
<TableTd colSpan={3}>
|
||||||
<Text ta="center" c="dimmed">
|
<Text ta="center" c="dimmed" fz="sm" lh={1.5}>
|
||||||
Tidak ditemukan data dengan kata kunci pencarian
|
Tidak ditemukan data dengan kata kunci pencarian
|
||||||
</Text>
|
</Text>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
@@ -132,6 +142,48 @@ function ListDesaAntiKorupsi({ search }: { search: string }) {
|
|||||||
</TableTbody>
|
</TableTbody>
|
||||||
</Table>
|
</Table>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
{/* Mobile Cards */}
|
||||||
|
<Box hiddenFrom="md">
|
||||||
|
<Stack gap="xs">
|
||||||
|
{filteredData.length > 0 ? (
|
||||||
|
filteredData.map((item) => (
|
||||||
|
<Paper key={item.id} p="sm" radius="md" withBorder shadow="xs">
|
||||||
|
<Stack gap="xs">
|
||||||
|
<Text fw={500} fz="sm" lh={1.5} lineClamp={1}>
|
||||||
|
{item.name || '-'}
|
||||||
|
</Text>
|
||||||
|
<Text fz="xs" c="dimmed" lh={1.5} lineClamp={1}>
|
||||||
|
Kategori: {item.kategori?.name || '-'}
|
||||||
|
</Text>
|
||||||
|
<Group justify="flex-end">
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
radius="md"
|
||||||
|
variant="light"
|
||||||
|
color="blue"
|
||||||
|
leftSection={<IconDeviceImacCog size={16} />}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/admin/landing-page/desa-anti-korupsi/list-desa-anti-korupsi/${item.id}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Paper p="sm" radius="md" withBorder>
|
||||||
|
<Text ta="center" c="dimmed" fz="xs" lh={1.5}>
|
||||||
|
Tidak ditemukan data dengan kata kunci pencarian
|
||||||
|
</Text>
|
||||||
|
</Paper>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
<Center>
|
<Center>
|
||||||
@@ -144,7 +196,6 @@ function ListDesaAntiKorupsi({ search }: { search: string }) {
|
|||||||
}}
|
}}
|
||||||
size="md"
|
size="md"
|
||||||
radius="md"
|
radius="md"
|
||||||
mt="md"
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -152,4 +203,4 @@ function ListDesaAntiKorupsi({ search }: { search: string }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DesaAntiKorupsi;
|
export default DesaAntiKorupsi;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
import { Box, ScrollArea, Stack, Tabs, TabsList, TabsPanel, TabsTab, Title } from '@mantine/core';
|
||||||
import { IconChartBar, IconUsers } from '@tabler/icons-react';
|
import { IconChartBar, IconUsers } from '@tabler/icons-react';
|
||||||
import { usePathname, useRouter } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
@@ -53,36 +53,41 @@ function LayoutTabsKepuasan({ children }: { children: React.ReactNode }) {
|
|||||||
radius="lg"
|
radius="lg"
|
||||||
keepMounted={false}
|
keepMounted={false}
|
||||||
>
|
>
|
||||||
|
|
||||||
{/* ✅ Scroll horizontal wrapper */}
|
{/* ✅ Scroll horizontal wrapper */}
|
||||||
<ScrollArea type="auto" offsetScrollbars>
|
<Box>
|
||||||
<TabsList
|
<ScrollArea type="auto" offsetScrollbars>
|
||||||
p="sm"
|
<TabsList
|
||||||
style={{
|
p="sm"
|
||||||
background: "linear-gradient(135deg, #e7ebf7, #f9faff)",
|
style={{
|
||||||
borderRadius: "1rem",
|
background: "linear-gradient(135deg, #e7ebf7, #f9faff)",
|
||||||
boxShadow: "inset 0 0 10px rgba(0,0,0,0.05)",
|
borderRadius: "1rem",
|
||||||
display: "flex",
|
boxShadow: "inset 0 0 10px rgba(0,0,0,0.05)",
|
||||||
flexWrap: "nowrap",
|
display: "flex",
|
||||||
gap: "0.5rem",
|
flexWrap: "nowrap",
|
||||||
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
|
gap: "0.5rem",
|
||||||
}}
|
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
|
||||||
>
|
}}
|
||||||
{tabs.map((e, i) => (
|
>
|
||||||
<TabsTab
|
{tabs.map((tab, i) => (
|
||||||
key={i}
|
<TabsTab
|
||||||
value={e.value}
|
key={i}
|
||||||
leftSection={e.icon}
|
value={tab.value}
|
||||||
style={{
|
leftSection={tab.icon}
|
||||||
fontWeight: 500,
|
style={{
|
||||||
fontSize: "0.9rem",
|
fontWeight: 600,
|
||||||
transition: "all 0.2s ease",
|
fontSize: "0.9rem",
|
||||||
}}
|
transition: "all 0.2s ease",
|
||||||
>
|
flexShrink: 0, // ✅ jangan mengecil aneh-aneh
|
||||||
{e.label}
|
}}
|
||||||
</TabsTab>
|
>
|
||||||
))}
|
{tab.label}
|
||||||
</TabsList>
|
</TabsTab>
|
||||||
</ScrollArea>
|
))}
|
||||||
|
</TabsList>
|
||||||
|
</ScrollArea>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{tabs.map((e, i) => (
|
{tabs.map((e, i) => (
|
||||||
<TabsPanel key={i} value={e.value}>
|
<TabsPanel key={i} value={e.value}>
|
||||||
<></>
|
<></>
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ function EditResponden() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ export default function DetailResponden() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box px={{ base: 0, md: 'xs' }} py="xs">
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -50,7 +50,7 @@ export default function DetailResponden() {
|
|||||||
|
|
||||||
<Paper
|
<Paper
|
||||||
withBorder
|
withBorder
|
||||||
w={{ base: "100%", md: "60%" }}
|
w={{ base: "100%", md: "70%" }}
|
||||||
bg={colors['white-1']}
|
bg={colors['white-1']}
|
||||||
p="lg"
|
p="lg"
|
||||||
radius="md"
|
radius="md"
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ function ListResponden({ search }: ListRespondenProps) {
|
|||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Stack py="md">
|
<Stack py={{ base: 'md', md: 'lg' }}>
|
||||||
<Skeleton height={650} radius="lg" />
|
<Skeleton height={650} radius="lg" />
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
@@ -68,11 +68,13 @@ function ListResponden({ search }: ListRespondenProps) {
|
|||||||
|
|
||||||
if (data.length === 0) {
|
if (data.length === 0) {
|
||||||
return (
|
return (
|
||||||
<Box py="md">
|
<Box py={{ base: 'md', md: 'lg' }}>
|
||||||
<Paper p="lg" radius="lg" shadow="md" withBorder>
|
<Paper p={{ base: 'md', md: 'lg' }} radius="lg" shadow="md" withBorder>
|
||||||
<Stack align="center" gap="sm">
|
<Stack align="center" gap="sm">
|
||||||
<Title order={4}>Data Responden</Title>
|
<Title order={2} lh={1.2}>
|
||||||
<Text c="dimmed" ta="center">
|
Data Responden
|
||||||
|
</Title>
|
||||||
|
<Text c="dimmed" ta="center" fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
Belum ada data responden yang tersedia
|
Belum ada data responden yang tersedia
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -83,12 +85,13 @@ function ListResponden({ search }: ListRespondenProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
<Stack gap="md">
|
<Stack gap={'lg'}>
|
||||||
<Paper p="lg" radius="lg" shadow="md" withBorder>
|
{/* Desktop Table */}
|
||||||
<Title order={4} mb="sm">
|
<Box visibleFrom="md">
|
||||||
Daftar Responden
|
<Paper p="lg" radius="lg" shadow="md" withBorder>
|
||||||
</Title>
|
<Title order={2} size="lg" mb="md" lh={1.2}>
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
Daftar Responden
|
||||||
|
</Title>
|
||||||
<Table
|
<Table
|
||||||
striped
|
striped
|
||||||
highlightOnHover
|
highlightOnHover
|
||||||
@@ -97,18 +100,18 @@ function ListResponden({ search }: ListRespondenProps) {
|
|||||||
>
|
>
|
||||||
<TableThead>
|
<TableThead>
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTh style={{ width: '5%' }}>No</TableTh>
|
<TableTh fz="sm" fw={600} w={60}>No</TableTh>
|
||||||
<TableTh style={{ width: '25%' }}>Nama</TableTh>
|
<TableTh fz="sm" fw={600}>Nama</TableTh>
|
||||||
<TableTh style={{ width: '20%' }}>Tanggal</TableTh>
|
<TableTh fz="sm" fw={600}>Tanggal</TableTh>
|
||||||
<TableTh style={{ width: '20%' }}>Jenis Kelamin</TableTh>
|
<TableTh fz="sm" fw={600}>Jenis Kelamin</TableTh>
|
||||||
<TableTh style={{ width: '15%' }}>Aksi</TableTh>
|
<TableTh fz="sm" fw={600} w={120}>Aksi</TableTh>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
</TableThead>
|
</TableThead>
|
||||||
<TableTbody>
|
<TableTbody>
|
||||||
{filteredData.length === 0 ? (
|
{filteredData.length === 0 ? (
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTd colSpan={5}>
|
<TableTd colSpan={5}>
|
||||||
<Text ta="center" c="dimmed">
|
<Text ta="center" c="dimmed" fz="sm" lh={1.5}>
|
||||||
Tidak ditemukan data dengan kata kunci pencarian
|
Tidak ditemukan data dengan kata kunci pencarian
|
||||||
</Text>
|
</Text>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
@@ -116,24 +119,18 @@ function ListResponden({ search }: ListRespondenProps) {
|
|||||||
) : (
|
) : (
|
||||||
filteredData.map((item, index) => (
|
filteredData.map((item, index) => (
|
||||||
<TableTr key={item.id}>
|
<TableTr key={item.id}>
|
||||||
<TableTd>{index + 1}</TableTd>
|
<TableTd fz="md" lh={1.5}>{index + 1}</TableTd>
|
||||||
<TableTd>{item.name}</TableTd>
|
<TableTd fz="md" lh={1.5}>{item.name}</TableTd>
|
||||||
<TableTd>
|
<TableTd fz="md" lh={1.5}>
|
||||||
<Box w={150}>
|
|
||||||
{item.tanggal
|
{item.tanggal
|
||||||
? new Date(item.tanggal).toLocaleDateString('id-ID', {
|
? new Date(item.tanggal).toLocaleDateString('id-ID', {
|
||||||
day: '2-digit',
|
day: '2-digit',
|
||||||
month: 'long',
|
month: 'long',
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
})
|
})
|
||||||
: '-'}
|
: '-'}
|
||||||
</Box>
|
|
||||||
</TableTd>
|
|
||||||
<TableTd>
|
|
||||||
<Box w={100}>
|
|
||||||
{item.jenisKelamin.name}
|
|
||||||
</Box>
|
|
||||||
</TableTd>
|
</TableTd>
|
||||||
|
<TableTd fz="md" lh={1.5}>{item.jenisKelamin.name}</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Button
|
<Button
|
||||||
size="xs"
|
size="xs"
|
||||||
@@ -155,8 +152,64 @@ function ListResponden({ search }: ListRespondenProps) {
|
|||||||
)}
|
)}
|
||||||
</TableTbody>
|
</TableTbody>
|
||||||
</Table>
|
</Table>
|
||||||
</Box>
|
</Paper>
|
||||||
</Paper>
|
</Box>
|
||||||
|
|
||||||
|
{/* Mobile Cards */}
|
||||||
|
<Box hiddenFrom="md">
|
||||||
|
<Stack gap="sm">
|
||||||
|
<Title order={2} size="md" lh={1.2} px="md">
|
||||||
|
Daftar Responden
|
||||||
|
</Title>
|
||||||
|
{filteredData.length === 0 ? (
|
||||||
|
<Paper p="md" radius="lg" shadow="sm" mx="md">
|
||||||
|
<Text ta="center" c="dimmed" fz="sm" lh={1.5}>
|
||||||
|
Tidak ditemukan data dengan kata kunci pencarian
|
||||||
|
</Text>
|
||||||
|
</Paper>
|
||||||
|
) : (
|
||||||
|
filteredData.map((item) => (
|
||||||
|
<Paper key={item.id} p="md" radius="lg" shadow="sm" mx="md">
|
||||||
|
<Stack gap={4}>
|
||||||
|
<Text fz="sm" c="dimmed" lh={1.4}>Nama</Text>
|
||||||
|
<Text fz="md" lh={1.5}>{item.name}</Text>
|
||||||
|
|
||||||
|
<Text fz="sm" c="dimmed" lh={1.4}>Tanggal</Text>
|
||||||
|
<Text fz="md" lh={1.5}>
|
||||||
|
{item.tanggal
|
||||||
|
? new Date(item.tanggal).toLocaleDateString('id-ID', {
|
||||||
|
day: '2-digit',
|
||||||
|
month: 'long',
|
||||||
|
year: 'numeric',
|
||||||
|
})
|
||||||
|
: '-'}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
<Text fz="sm" c="dimmed" lh={1.4}>Jenis Kelamin</Text>
|
||||||
|
<Text fz="md" lh={1.5}>{item.jenisKelamin.name}</Text>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
radius="md"
|
||||||
|
variant="light"
|
||||||
|
color="blue"
|
||||||
|
leftSection={<IconDeviceImac size={16} />}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/admin/landing-page/indeks-kepuasan-masyarakat/responden/${item.id}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
mt="xs"
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Center>
|
<Center>
|
||||||
<Pagination
|
<Pagination
|
||||||
value={page}
|
value={page}
|
||||||
@@ -167,7 +220,7 @@ function ListResponden({ search }: ListRespondenProps) {
|
|||||||
}}
|
}}
|
||||||
size="md"
|
size="md"
|
||||||
radius="md"
|
radius="md"
|
||||||
mt="md"
|
mt={{ base: 'md', md: 'lg' }}
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -175,4 +228,4 @@ function ListResponden({ search }: ListRespondenProps) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Responden;
|
export default Responden;
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import {
|
import {
|
||||||
|
Box,
|
||||||
ScrollArea,
|
ScrollArea,
|
||||||
Stack,
|
Stack,
|
||||||
Tabs,
|
Tabs,
|
||||||
@@ -74,36 +75,76 @@ function LayoutTabs({ children }: { children: React.ReactNode }) {
|
|||||||
keepMounted={false}
|
keepMounted={false}
|
||||||
>
|
>
|
||||||
{/* ✅ Scroll horizontal wrapper */}
|
{/* ✅ Scroll horizontal wrapper */}
|
||||||
<ScrollArea type="auto" offsetScrollbars>
|
<Box visibleFrom='md'>
|
||||||
<TabsList
|
<ScrollArea type="auto" offsetScrollbars>
|
||||||
p="sm"
|
<TabsList
|
||||||
style={{
|
p="sm"
|
||||||
background: "linear-gradient(135deg, #e7ebf7, #f9faff)",
|
style={{
|
||||||
borderRadius: "1rem",
|
background: "linear-gradient(135deg, #e7ebf7, #f9faff)",
|
||||||
boxShadow: "inset 0 0 10px rgba(0,0,0,0.05)",
|
borderRadius: "1rem",
|
||||||
display: "flex",
|
boxShadow: "inset 0 0 10px rgba(0,0,0,0.05)",
|
||||||
flexWrap: "nowrap",
|
display: "flex",
|
||||||
gap: "0.5rem",
|
flexWrap: "nowrap",
|
||||||
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
|
gap: "0.5rem",
|
||||||
}}
|
paddingInline: "0.5rem", // ✅ biar nggak nempel ke tepi
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tabs.map((tab, i) => (
|
||||||
|
<TabsTab
|
||||||
|
key={i}
|
||||||
|
value={tab.value}
|
||||||
|
leftSection={tab.icon}
|
||||||
|
style={{
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: "0.9rem",
|
||||||
|
transition: "all 0.2s ease",
|
||||||
|
flexShrink: 0, // ✅ jangan mengecil aneh-aneh
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tab.label}
|
||||||
|
</TabsTab>
|
||||||
|
))}
|
||||||
|
</TabsList>
|
||||||
|
</ScrollArea>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
<Box hiddenFrom='md'>
|
||||||
|
<ScrollArea
|
||||||
|
type="auto"
|
||||||
|
offsetScrollbars={false}
|
||||||
|
w="100%"
|
||||||
>
|
>
|
||||||
{tabs.map((tab, i) => (
|
|
||||||
<TabsTab
|
<TabsList
|
||||||
key={i}
|
p="xs" // lebih kecil
|
||||||
value={tab.value}
|
style={{
|
||||||
leftSection={tab.icon}
|
background: "linear-gradient(135deg, #e7ebf7, #f9faff)",
|
||||||
style={{
|
borderRadius: "1rem",
|
||||||
fontWeight: 600,
|
display: "flex",
|
||||||
fontSize: "0.9rem",
|
flexWrap: "nowrap",
|
||||||
transition: "all 0.2s ease",
|
gap: "0.5rem",
|
||||||
flexShrink: 0, // ✅ jangan mengecil aneh-aneh
|
width: "max-content", // ⬅️ kunci
|
||||||
}}
|
maxWidth: "100%", // ⬅️ penting
|
||||||
>
|
}}
|
||||||
{tab.label}
|
>
|
||||||
</TabsTab>
|
{tabs.map((tab, i) => (
|
||||||
))}
|
<TabsTab
|
||||||
</TabsList>
|
key={i}
|
||||||
</ScrollArea>
|
value={tab.value}
|
||||||
|
leftSection={tab.icon}
|
||||||
|
style={{
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: "0.9rem",
|
||||||
|
paddingInline: "0.75rem", // ⬅️ lebih ramping
|
||||||
|
flexShrink: 0, // ✅ jangan mengecil aneh-aneh
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{tab.label}
|
||||||
|
</TabsTab>
|
||||||
|
))}
|
||||||
|
</TabsList>
|
||||||
|
</ScrollArea>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{tabs.map((tab, i) => (
|
{tabs.map((tab, i) => (
|
||||||
<TabsPanel
|
<TabsPanel
|
||||||
|
|||||||
@@ -177,7 +177,7 @@ function EditMediaSosial() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 0, md: 'xs' }} py="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ function DetailMediaSosial() {
|
|||||||
const data = stateMediaSosial.findUnique.data;
|
const data = stateMediaSosial.findUnique.data;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box px={{ base: 0, md: 'xs' }} py="xs">
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
@@ -62,7 +62,7 @@ function DetailMediaSosial() {
|
|||||||
|
|
||||||
<Paper
|
<Paper
|
||||||
withBorder
|
withBorder
|
||||||
w={{ base: "100%", md: "50%" }}
|
w={{ base: "100%", md: "70%" }}
|
||||||
bg={colors['white-1']}
|
bg={colors['white-1']}
|
||||||
p="lg"
|
p="lg"
|
||||||
radius="md"
|
radius="md"
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ import { useProxy } from 'valtio/utils';
|
|||||||
import profileLandingPageState from '../../../../_state/landing-page/profile';
|
import profileLandingPageState from '../../../../_state/landing-page/profile';
|
||||||
import SelectSosialMedia from '@/app/admin/(dashboard)/_com/selectSocialMedia';
|
import SelectSosialMedia from '@/app/admin/(dashboard)/_com/selectSocialMedia';
|
||||||
|
|
||||||
|
|
||||||
// ⭐ Tambah type SosmedKey
|
// ⭐ Tambah type SosmedKey
|
||||||
type SosmedKey =
|
type SosmedKey =
|
||||||
| 'facebook'
|
| 'facebook'
|
||||||
@@ -88,7 +87,6 @@ export default function CreateMediaSosial() {
|
|||||||
stateMediaSosial.create.form.imageId = null;
|
stateMediaSosial.create.form.imageId = null;
|
||||||
stateMediaSosial.create.form.icon = sosmedMap[selectedSosmed].src!;
|
stateMediaSosial.create.form.icon = sosmedMap[selectedSosmed].src!;
|
||||||
|
|
||||||
|
|
||||||
await stateMediaSosial.create.create();
|
await stateMediaSosial.create.create();
|
||||||
resetForm();
|
resetForm();
|
||||||
router.push('/admin/landing-page/profil/media-sosial');
|
router.push('/admin/landing-page/profil/media-sosial');
|
||||||
@@ -129,13 +127,13 @@ export default function CreateMediaSosial() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||||
{/* Header */}
|
{/* Header */}
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
</Button>
|
</Button>
|
||||||
<Title order={4} ml="sm" c="dark">
|
<Title order={2} ml="sm" c="dark" lh={1.2} fz={{ base: 'md', md: 'lg' }}>
|
||||||
Tambah Media Sosial
|
Tambah Media Sosial
|
||||||
</Title>
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
@@ -155,7 +153,7 @@ export default function CreateMediaSosial() {
|
|||||||
{/* Custom icon uploader */}
|
{/* Custom icon uploader */}
|
||||||
{selectedSosmed === 'custom' && (
|
{selectedSosmed === 'custom' && (
|
||||||
<Box>
|
<Box>
|
||||||
<Text fw="bold" fz="sm" mb={6}>
|
<Text fw="bold" fz={{ base: 'sm', md: 'md' }} lh={1.45} mb={6}>
|
||||||
Upload Custom Icon
|
Upload Custom Icon
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
@@ -185,8 +183,10 @@ export default function CreateMediaSosial() {
|
|||||||
</Dropzone.Idle>
|
</Dropzone.Idle>
|
||||||
|
|
||||||
<Stack align="center" gap="xs">
|
<Stack align="center" gap="xs">
|
||||||
<Text fw={500}>Seret gambar atau klik untuk pilih</Text>
|
<Text fw={500} fz={{ base: 'sm', md: 'md' }} lh={1.45}>
|
||||||
<Text size="sm" c="dimmed">
|
Seret gambar atau klik untuk pilih
|
||||||
|
</Text>
|
||||||
|
<Text fz={{ base: 12, md: 'sm' }} c="dimmed" lh={1.4}>
|
||||||
Maksimal 5MB, format .png, .jpg, .jpeg, webp
|
Maksimal 5MB, format .png, .jpg, .jpeg, webp
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -229,7 +229,11 @@ export default function CreateMediaSosial() {
|
|||||||
|
|
||||||
{/* Input name */}
|
{/* Input name */}
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Nama Media Sosial"
|
label={
|
||||||
|
<Text fw={500} fz={{ base: 'sm', md: 'md' }} lh={1.45}>
|
||||||
|
Nama Media Sosial
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
placeholder="Masukkan nama media sosial"
|
placeholder="Masukkan nama media sosial"
|
||||||
value={stateMediaSosial.create.form.name ?? ''}
|
value={stateMediaSosial.create.form.name ?? ''}
|
||||||
onChange={(e) => (stateMediaSosial.create.form.name = e.target.value)}
|
onChange={(e) => (stateMediaSosial.create.form.name = e.target.value)}
|
||||||
@@ -238,7 +242,11 @@ export default function CreateMediaSosial() {
|
|||||||
|
|
||||||
{/* Input link */}
|
{/* Input link */}
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Link / Kontak"
|
label={
|
||||||
|
<Text fw={500} fz={{ base: 'sm', md: 'md' }} lh={1.45}>
|
||||||
|
Link / Kontak
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
placeholder="Masukkan link atau nomor"
|
placeholder="Masukkan link atau nomor"
|
||||||
value={stateMediaSosial.create.form.iconUrl ?? ''}
|
value={stateMediaSosial.create.form.iconUrl ?? ''}
|
||||||
onChange={(e) => (stateMediaSosial.create.form.iconUrl = e.target.value)}
|
onChange={(e) => (stateMediaSosial.create.form.iconUrl = e.target.value)}
|
||||||
@@ -266,4 +274,4 @@ export default function CreateMediaSosial() {
|
|||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,25 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Center, Group, Image, Pagination, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
import {
|
||||||
|
Box,
|
||||||
|
Button,
|
||||||
|
Center,
|
||||||
|
Group,
|
||||||
|
Image,
|
||||||
|
Pagination,
|
||||||
|
Paper,
|
||||||
|
Skeleton,
|
||||||
|
Stack,
|
||||||
|
Table,
|
||||||
|
TableTbody,
|
||||||
|
TableTd,
|
||||||
|
TableTh,
|
||||||
|
TableThead,
|
||||||
|
TableTr,
|
||||||
|
Text,
|
||||||
|
Title,
|
||||||
|
} from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
import { IconDeviceImacCog, IconPlus, IconSearch } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -28,11 +46,11 @@ function MediaSosial() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function ListMediaSosial({ search }: { search: string }) {
|
function ListMediaSosial({ search }: { search: string }) {
|
||||||
const stateMediaSosial = useProxy(profileLandingPageState.mediaSosial)
|
const stateMediaSosial = useProxy(profileLandingPageState.mediaSosial);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
|
||||||
const getIconSource = (item: any) => {
|
const getIconSource = (item: any) => {
|
||||||
if (item.image?.link) return item.image.link;
|
if (item.image?.link) return item.image.link;
|
||||||
if (item.icon && sosmedMap[item.icon as keyof typeof sosmedMap]?.src) {
|
if (item.icon && sosmedMap[item.icon as keyof typeof sosmedMap]?.src) {
|
||||||
return sosmedMap[item.icon as keyof typeof sosmedMap].src;
|
return sosmedMap[item.icon as keyof typeof sosmedMap].src;
|
||||||
}
|
}
|
||||||
@@ -48,101 +66,201 @@ function ListMediaSosial({ search }: { search: string }) {
|
|||||||
} = stateMediaSosial.findMany;
|
} = stateMediaSosial.findMany;
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 10, search)
|
load(page, 10, search);
|
||||||
}, [page, search])
|
}, [page, search]);
|
||||||
|
|
||||||
const filteredData = data || []
|
const filteredData = data || [];
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Stack py={10}>
|
<Stack py={{ base: 'sm', sm: 'md' }}>
|
||||||
<Skeleton height={600} radius="md" />
|
<Skeleton height={600} radius="md" />
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py={{ base: 'sm', sm: 'md' }}>
|
||||||
<Paper withBorder bg={colors['white-1']} p={'lg'} shadow="md" radius="md">
|
<Paper withBorder bg={colors['white-1']} p={{ base: 'md', sm: 'lg' }} shadow="md" radius="md">
|
||||||
<Group justify="space-between" mb="md">
|
<Group justify="space-between" mb={{ base: 'sm', sm: 'md' }}>
|
||||||
<Title order={4}>Daftar Media Sosial</Title>
|
<Title order={4} lh={1.15}>
|
||||||
<Button leftSection={<IconPlus size={18} />} color="blue" variant="light" onClick={() => router.push('/admin/landing-page/profil/media-sosial/create')}>
|
Daftar Media Sosial
|
||||||
|
</Title>
|
||||||
|
<Button
|
||||||
|
leftSection={<IconPlus size={18} />}
|
||||||
|
color="blue"
|
||||||
|
variant="light"
|
||||||
|
onClick={() => router.push('/admin/landing-page/profil/media-sosial/create')}
|
||||||
|
fz={{ base: 'xs', sm: 'sm' }}
|
||||||
|
>
|
||||||
Tambah Baru
|
Tambah Baru
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: "auto" }}>
|
|
||||||
<Table highlightOnHover>
|
|
||||||
<TableThead>
|
|
||||||
<TableTr>
|
|
||||||
<TableTh style={{ width: '25%' }}>Nama Media Sosial / Kontak</TableTh>
|
|
||||||
<TableTh style={{ width: '20%' }}>Gambar</TableTh>
|
|
||||||
<TableTh style={{ width: '20%' }}>Link / No. Telepon</TableTh>
|
|
||||||
<TableTh style={{ width: '15%' }}>Aksi</TableTh>
|
|
||||||
</TableTr>
|
|
||||||
</TableThead>
|
|
||||||
<TableTbody>
|
|
||||||
{filteredData.length > 0 ? (
|
|
||||||
filteredData.map((item) => (
|
|
||||||
<TableTr key={item.id}>
|
|
||||||
<TableTd style={{ width: '25%', }}>
|
|
||||||
<Text fw={500} truncate="end" lineClamp={1}>{item.name}</Text>
|
|
||||||
</TableTd>
|
|
||||||
<TableTd style={{ width: '20%' }}>
|
|
||||||
<Box w={50} h={50} style={{ borderRadius: 8, overflow: 'hidden' }}>
|
|
||||||
|
|
||||||
{(() => {
|
<Box>
|
||||||
const src = getIconSource(item);
|
{/* Desktop: Table | Mobile: Card-based vertical layout */}
|
||||||
|
<Box visibleFrom="md">
|
||||||
if (src) {
|
<Table highlightOnHover>
|
||||||
return (
|
<TableThead>
|
||||||
<Image
|
<TableTr>
|
||||||
loading="lazy"
|
<TableTh style={{ width: '25%' }}>
|
||||||
src={src}
|
<Text fw={600} fz="md" lh={1.45}>
|
||||||
alt={item.name}
|
Nama Media Sosial / Kontak
|
||||||
fit={item.image?.link ? "cover" : "contain"}
|
</Text>
|
||||||
/>
|
</TableTh>
|
||||||
);
|
<TableTh style={{ width: '20%' }}>
|
||||||
}
|
<Text fw={600} fz="md" lh={1.45}>
|
||||||
|
Gambar
|
||||||
return <Box bg={colors['blue-button']} w="100%" h="100%" />;
|
</Text>
|
||||||
})()}
|
</TableTh>
|
||||||
|
<TableTh style={{ width: '20%' }}>
|
||||||
</Box>
|
<Text fw={600} fz="md" lh={1.45}>
|
||||||
</TableTd>
|
Link / No. Telepon
|
||||||
<TableTd style={{ width: '20%', }}>
|
</Text>
|
||||||
<Box w={250}>
|
</TableTh>
|
||||||
<Text truncate fz="sm" c="dimmed" lineClamp={1}>
|
<TableTh style={{ width: '15%' }}>
|
||||||
{item.iconUrl || item.noTelp || '-'}
|
<Text fw={600} fz="md" lh={1.45}>
|
||||||
|
Aksi
|
||||||
|
</Text>
|
||||||
|
</TableTh>
|
||||||
|
</TableTr>
|
||||||
|
</TableThead>
|
||||||
|
<TableTbody>
|
||||||
|
{filteredData.length > 0 ? (
|
||||||
|
filteredData.map((item) => (
|
||||||
|
<TableTr key={item.id}>
|
||||||
|
<TableTd style={{ width: '25%' }}>
|
||||||
|
<Text fw={500} fz="md" lh={1.5} truncate="end" lineClamp={1}>
|
||||||
|
{item.name}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</TableTd>
|
||||||
</TableTd>
|
<TableTd style={{ width: '20%' }}>
|
||||||
<TableTd style={{ width: '15%' }}>
|
<Box w={50} h={50} style={{ borderRadius: 8, overflow: 'hidden' }}>
|
||||||
<Button
|
{(() => {
|
||||||
size="xs"
|
const src = getIconSource(item);
|
||||||
radius="md"
|
if (src) {
|
||||||
variant="light"
|
return (
|
||||||
color="blue"
|
<Image
|
||||||
leftSection={<IconDeviceImacCog size={16} />}
|
loading="lazy"
|
||||||
onClick={() => router.push(`/admin/landing-page/profil/media-sosial/${item.id}`)}
|
src={src}
|
||||||
>
|
alt={item.name}
|
||||||
Detail
|
fit={item.image?.link ? 'cover' : 'contain'}
|
||||||
</Button>
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <Box bg={colors['blue-button']} w="100%" h="100%" />;
|
||||||
|
})()}
|
||||||
|
</Box>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd style={{ width: '20%' }}>
|
||||||
|
<Box w={250}>
|
||||||
|
<Text truncate fz="sm" lh={1.5} c="dimmed" lineClamp={1}>
|
||||||
|
{item.iconUrl || item.noTelp || '-'}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd style={{ width: '15%' }}>
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
radius="md"
|
||||||
|
variant="light"
|
||||||
|
color="blue"
|
||||||
|
leftSection={<IconDeviceImacCog size={16} />}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(`/admin/landing-page/profil/media-sosial/${item.id}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<TableTr>
|
||||||
|
<TableTd colSpan={4}>
|
||||||
|
<Center py={20}>
|
||||||
|
<Text c="dimmed" fz="md" lh={1.5}>
|
||||||
|
Tidak ada data media sosial yang cocok
|
||||||
|
</Text>
|
||||||
|
</Center>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
))
|
)}
|
||||||
) : (
|
</TableTbody>
|
||||||
<TableTr>
|
</Table>
|
||||||
<TableTd colSpan={4}>
|
</Box>
|
||||||
<Center py={20}>
|
|
||||||
<Text color="dimmed">Tidak ada data media sosial yang cocok</Text>
|
{/* Mobile layout */}
|
||||||
</Center>
|
<Stack hiddenFrom="md" gap="xs">
|
||||||
</TableTd>
|
{filteredData.length > 0 ? (
|
||||||
</TableTr>
|
filteredData.map((item) => (
|
||||||
)}
|
<Paper key={item.id} withBorder p="sm" radius="md">
|
||||||
</TableTbody>
|
<Group justify="space-between" wrap="nowrap" align='center'>
|
||||||
</Table>
|
<Box>
|
||||||
|
<Text fw={600} fz="sm" lh={1.45}>
|
||||||
|
{item.name}
|
||||||
|
</Text>
|
||||||
|
</Box>
|
||||||
|
<Box w={40} h={40} style={{ borderRadius: 6, overflow: 'hidden' }}>
|
||||||
|
{(() => {
|
||||||
|
const src = getIconSource(item);
|
||||||
|
if (src) {
|
||||||
|
return (
|
||||||
|
<Image
|
||||||
|
loading="lazy"
|
||||||
|
src={src}
|
||||||
|
alt={item.name}
|
||||||
|
fit={item.image?.link ? 'cover' : 'contain'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <Box bg={colors['blue-button']} w="100%" h="100%" />;
|
||||||
|
})()}
|
||||||
|
</Box>
|
||||||
|
</Group>
|
||||||
|
<Box>
|
||||||
|
<a
|
||||||
|
href={item.link}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ textDecoration: 'underline' }}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fz="sm"
|
||||||
|
c="blue"
|
||||||
|
truncate
|
||||||
|
>
|
||||||
|
{item.iconUrl || item.noTelp || '-'}
|
||||||
|
</Text>
|
||||||
|
</a>
|
||||||
|
</Box>
|
||||||
|
<Group mt="sm" justify="flex-end">
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
radius="md"
|
||||||
|
variant="light"
|
||||||
|
color="blue"
|
||||||
|
leftSection={<IconDeviceImacCog size={16} />}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(`/admin/landing-page/profil/media-sosial/${item.id}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Paper>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<Center py={24}>
|
||||||
|
<Text c="dimmed" fz="sm" lh={1.5}>
|
||||||
|
Tidak ada data media sosial yang cocok
|
||||||
|
</Text>
|
||||||
|
</Center>
|
||||||
|
)}
|
||||||
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
<Center>
|
<Center>
|
||||||
<Pagination
|
<Pagination
|
||||||
value={page}
|
value={page}
|
||||||
@@ -161,4 +279,4 @@ function ListMediaSosial({ search }: { search: string }) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MediaSosial;
|
export default MediaSosial;
|
||||||
@@ -178,7 +178,7 @@ function EditPejabatDesa() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
<Button variant="subtle" onClick={handleBack} p="xs" radius="md">
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import profileLandingPageState from '@/app/admin/(dashboard)/_state/landing-page
|
|||||||
import colors from '@/con/colors';
|
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 } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconEdit } from '@tabler/icons-react';
|
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
@@ -35,15 +34,15 @@ function Page() {
|
|||||||
<Title order={3} c={colors['blue-button']}>Preview Pejabat Desa</Title>
|
<Title order={3} c={colors['blue-button']}>Preview Pejabat Desa</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 1 }}>
|
<GridCol span={{ base: 12, md: 1 }}>
|
||||||
<Button
|
<Button
|
||||||
c="green"
|
style={{fontSize: 15, fontWeight: "bold"}}
|
||||||
variant="light"
|
c="green"
|
||||||
leftSection={<IconEdit size={18} stroke={2} />}
|
variant="light"
|
||||||
radius="md"
|
radius="md"
|
||||||
onClick={() => router.push(`/admin/landing-page/profil/pejabat-desa/${allList.findUnique.data?.id}`)}
|
onClick={() => router.push(`/admin/landing-page/profil/pejabat-desa/${allList.findUnique.data?.id}`)}
|
||||||
>
|
>
|
||||||
Edit
|
Edit
|
||||||
</Button>
|
</Button>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
{dataArray.map((item) => (
|
{dataArray.map((item) => (
|
||||||
@@ -52,7 +51,7 @@ function Page() {
|
|||||||
<Grid>
|
<Grid>
|
||||||
<GridCol span={12}>
|
<GridCol span={12}>
|
||||||
<Center>
|
<Center>
|
||||||
<Image src="/darmasaba-icon.png" w={{ base: 100, md: 150 }} alt="Logo Desa" loading="lazy"/>
|
<Image src="/darmasaba-icon.png" w={{ base: 100, md: 150 }} alt="Logo Desa" loading="lazy" />
|
||||||
</Center>
|
</Center>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={12}>
|
<GridCol span={12}>
|
||||||
@@ -93,7 +92,7 @@ function Page() {
|
|||||||
</Paper>
|
</Paper>
|
||||||
<Box mt="lg">
|
<Box mt="lg">
|
||||||
<Text fz={{ base: "1.125rem", md: "1.5rem" }} fw="bold" mb={4}>Jabatan</Text>
|
<Text fz={{ base: "1.125rem", md: "1.5rem" }} fw="bold" mb={4}>Jabatan</Text>
|
||||||
<Text fz={{ base: "1rem", md: "1.4rem" }} ta="justify" c={colors['blue-button']}>
|
<Text fz={{ base: "1rem", md: "1.4rem" }} ta="left" c={colors['blue-button']}>
|
||||||
{item.position}
|
{item.position}
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -130,7 +130,7 @@ function EditProgramInovasi() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
|
|||||||
@@ -40,13 +40,15 @@ function DetailProgramInovasi() {
|
|||||||
const data = stateProgramInovasi.findUnique.data
|
const data = stateProgramInovasi.findUnique.data
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'md', md: 'xl' }} py="lg">
|
<Box px={{ base: 0, md: 'xs' }} py="xs">
|
||||||
<Button variant="subtle" onClick={() => router.back()} leftSection={<IconArrowBack size={22} color={colors['blue-button']} />}>
|
<Box pb="20">
|
||||||
Kembali
|
<Button variant="subtle" onClick={() => router.back()} leftSection={<IconArrowBack size={22} color={colors['blue-button']} />}>
|
||||||
</Button>
|
Kembali
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<Paper
|
<Paper
|
||||||
w={{ base: "100%", md: "60%" }}
|
w={{ base: "100%", md: "70%" }}
|
||||||
bg={colors['white-1']}
|
bg={colors['white-1']}
|
||||||
p="lg"
|
p="lg"
|
||||||
radius="md"
|
radius="md"
|
||||||
@@ -68,9 +70,9 @@ function DetailProgramInovasi() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Text fz="lg" fw="bold">Gambar</Text>
|
<Text fz="lg" fw="bold">Gambar</Text>
|
||||||
{data.image?.link ? (
|
{data.image?.link ? (
|
||||||
<Image
|
<Image
|
||||||
src={data.image.link}
|
src={data.image.link}
|
||||||
alt="Gambar Program"
|
alt="Gambar Program"
|
||||||
radius="md"
|
radius="md"
|
||||||
style={{ maxWidth: '100%', maxHeight: 300, objectFit: 'contain' }}
|
style={{ maxWidth: '100%', maxHeight: 300, objectFit: 'contain' }}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
@@ -106,28 +108,28 @@ function DetailProgramInovasi() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<Button
|
<Button
|
||||||
color="red"
|
color="red"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedId(data.id);
|
setSelectedId(data.id);
|
||||||
setModalHapus(true);
|
setModalHapus(true);
|
||||||
}}
|
}}
|
||||||
variant="light"
|
variant="light"
|
||||||
radius="md"
|
radius="md"
|
||||||
size="md"
|
size="md"
|
||||||
>
|
>
|
||||||
<IconTrash size={20} />
|
<IconTrash size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
color="green"
|
color="green"
|
||||||
onClick={() => router.push(`/admin/landing-page/profil/program-inovasi/${data.id}/edit`)}
|
onClick={() => router.push(`/admin/landing-page/profil/program-inovasi/${data.id}/edit`)}
|
||||||
variant="light"
|
variant="light"
|
||||||
radius="md"
|
radius="md"
|
||||||
size="md"
|
size="md"
|
||||||
>
|
>
|
||||||
<IconEdit size={20} />
|
<IconEdit size={20} />
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ function CreateProgramInovasi() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px={{ base: 'sm', md: 'lg' }} py="md">
|
<Box px={{ base: 0, md: 'lg' }} py="xs">
|
||||||
<Group mb="md">
|
<Group mb="md">
|
||||||
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
<Button variant="subtle" onClick={() => router.back()} p="xs" radius="md">
|
||||||
<IconArrowBack color={colors['blue-button']} size={24} />
|
<IconArrowBack color={colors['blue-button']} size={24} />
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ function ProgramInovasi() {
|
|||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px="md" py="lg">
|
<Box px={{base: 0, md: "md"}} py="lg">
|
||||||
<HeaderSearch
|
<HeaderSearch
|
||||||
title="Program Inovasi"
|
title="Program Inovasi"
|
||||||
placeholder="Cari program inovasi..."
|
placeholder="Cari program inovasi..."
|
||||||
@@ -52,75 +52,137 @@ function ListProgramInovasi({ search }: { search: string }) {
|
|||||||
<Group justify='space-between'>
|
<Group justify='space-between'>
|
||||||
<Title order={4}>Daftar Program Inovasi</Title>
|
<Title order={4}>Daftar Program Inovasi</Title>
|
||||||
<Button
|
<Button
|
||||||
color="blue"
|
color="blue"
|
||||||
leftSection={<IconPlus size={18} />}
|
leftSection={<IconPlus size={18} />}
|
||||||
variant="light"
|
variant="light"
|
||||||
radius="md"
|
radius="md"
|
||||||
onClick={() => router.push('/admin/landing-page/profil/program-inovasi/create')}
|
onClick={() => router.push('/admin/landing-page/profil/program-inovasi/create')}
|
||||||
>
|
>
|
||||||
Tambah Program
|
Tambah Program
|
||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
<Box style={{ overflowX: 'auto' }}>
|
<Box visibleFrom='md'>
|
||||||
<Table highlightOnHover striped verticalSpacing="sm">
|
<Box style={{ overflowX: 'auto' }}>
|
||||||
<TableThead>
|
<Table highlightOnHover striped verticalSpacing="sm">
|
||||||
<TableTr>
|
<TableThead>
|
||||||
<TableTh>Nama Program</TableTh>
|
|
||||||
<TableTh>Deskripsi</TableTh>
|
|
||||||
<TableTh>Link</TableTh>
|
|
||||||
<TableTh>Aksi</TableTh>
|
|
||||||
</TableTr>
|
|
||||||
</TableThead>
|
|
||||||
<TableTbody>
|
|
||||||
{filteredData.length === 0 ? (
|
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTd colSpan={4}>
|
<TableTh>Nama Program</TableTh>
|
||||||
<Center py={20}>
|
<TableTh>Deskripsi</TableTh>
|
||||||
<Text color="dimmed">Belum ada data program inovasi</Text>
|
<TableTh>Link</TableTh>
|
||||||
</Center>
|
<TableTh>Aksi</TableTh>
|
||||||
</TableTd>
|
|
||||||
</TableTr>
|
</TableTr>
|
||||||
) : (
|
</TableThead>
|
||||||
filteredData.map((item) => (
|
<TableTbody>
|
||||||
<TableTr key={item.id}>
|
{filteredData.length === 0 ? (
|
||||||
<TableTd>
|
<TableTr>
|
||||||
<Text fw={500}>{item.name}</Text>
|
<TableTd colSpan={4}>
|
||||||
</TableTd>
|
<Center py={20}>
|
||||||
<TableTd style={{ maxWidth: 250 }}>
|
<Text color="dimmed">Belum ada data program inovasi</Text>
|
||||||
<Text fz="sm" lineClamp={1} dangerouslySetInnerHTML={{ __html: item.description || '-' }}></Text>
|
</Center>
|
||||||
</TableTd>
|
|
||||||
<TableTd style={{ maxWidth: 250 }}>
|
|
||||||
<Tooltip label="Buka tautan program" position="top" withArrow>
|
|
||||||
<a
|
|
||||||
href={item.link}
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
style={{ color: colors['blue-button'], textDecoration: 'underline' }}
|
|
||||||
>
|
|
||||||
<Text truncate fz="sm">{item.link}</Text>
|
|
||||||
</a>
|
|
||||||
</Tooltip>
|
|
||||||
</TableTd>
|
|
||||||
<TableTd>
|
|
||||||
<Button
|
|
||||||
size="xs"
|
|
||||||
radius="md"
|
|
||||||
variant="light"
|
|
||||||
color="blue"
|
|
||||||
leftSection={<IconDeviceImacCog size={16} />}
|
|
||||||
onClick={() =>
|
|
||||||
router.push(`/admin/landing-page/profil/program-inovasi/${item.id}`)
|
|
||||||
}
|
|
||||||
>
|
|
||||||
Detail
|
|
||||||
</Button>
|
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
))
|
) : (
|
||||||
)}
|
filteredData.map((item) => (
|
||||||
</TableTbody>
|
<TableTr key={item.id}>
|
||||||
</Table>
|
<TableTd>
|
||||||
|
<Text fw={500}>{item.name}</Text>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd style={{ maxWidth: 250 }}>
|
||||||
|
<Text fz="sm" lineClamp={1} dangerouslySetInnerHTML={{ __html: item.description || '-' }}></Text>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd style={{ maxWidth: 250 }}>
|
||||||
|
<Tooltip label="Buka tautan program" position="top" withArrow>
|
||||||
|
<a
|
||||||
|
href={item.link}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ color: colors['blue-button'], textDecoration: 'underline' }}
|
||||||
|
>
|
||||||
|
<Text truncate fz="sm">{item.link}</Text>
|
||||||
|
</a>
|
||||||
|
</Tooltip>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
radius="md"
|
||||||
|
variant="light"
|
||||||
|
color="blue"
|
||||||
|
leftSection={<IconDeviceImacCog size={16} />}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(`/admin/landing-page/profil/program-inovasi/${item.id}`)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</TableTd>
|
||||||
|
</TableTr>
|
||||||
|
))
|
||||||
|
)}
|
||||||
|
</TableTbody>
|
||||||
|
</Table>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box hiddenFrom="md" pt={20}>
|
||||||
|
<Stack gap="sm">
|
||||||
|
{filteredData.map((item) => (
|
||||||
|
<Paper
|
||||||
|
key={item.id}
|
||||||
|
withBorder
|
||||||
|
radius="md"
|
||||||
|
p="md"
|
||||||
|
shadow="xs"
|
||||||
|
>
|
||||||
|
<Stack gap={6}>
|
||||||
|
{/* Title */}
|
||||||
|
<Text fw={600}>{item.name}</Text>
|
||||||
|
|
||||||
|
{/* Description */}
|
||||||
|
<Text fz="sm" c="gray.7" lineClamp={2}>
|
||||||
|
{item.description || '-'}
|
||||||
|
</Text>
|
||||||
|
|
||||||
|
{/* Link */}
|
||||||
|
<Box>
|
||||||
|
<a
|
||||||
|
href={item.link}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
style={{ textDecoration: 'underline' }}
|
||||||
|
>
|
||||||
|
<Text
|
||||||
|
fz="sm"
|
||||||
|
c="blue"
|
||||||
|
truncate
|
||||||
|
>
|
||||||
|
{item.link}
|
||||||
|
</Text>
|
||||||
|
</a>
|
||||||
|
</Box>
|
||||||
|
|
||||||
|
{/* Action */}
|
||||||
|
<Group justify="flex-end" mt="xs">
|
||||||
|
<Button
|
||||||
|
size="xs"
|
||||||
|
radius="md"
|
||||||
|
variant="light"
|
||||||
|
color="blue"
|
||||||
|
leftSection={<IconDeviceImacCog size={16} />}
|
||||||
|
onClick={() =>
|
||||||
|
router.push(
|
||||||
|
`/admin/landing-page/profil/program-inovasi/${item.id}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
Detail
|
||||||
|
</Button>
|
||||||
|
</Group>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
))}
|
||||||
|
</Stack>
|
||||||
|
</Box>
|
||||||
|
|
||||||
{filteredData.length > 0 && (
|
{filteredData.length > 0 && (
|
||||||
<Center mt="md">
|
<Center mt="md">
|
||||||
<Pagination
|
<Pagination
|
||||||
|
|||||||
@@ -1,399 +1,3 @@
|
|||||||
// 'use client'
|
|
||||||
|
|
||||||
// import colors from "@/con/colors";
|
|
||||||
// import { authStore } from "@/store/authStore";
|
|
||||||
// import {
|
|
||||||
// ActionIcon,
|
|
||||||
// AppShell,
|
|
||||||
// AppShellHeader,
|
|
||||||
// AppShellMain,
|
|
||||||
// AppShellNavbar,
|
|
||||||
// Burger,
|
|
||||||
// Center,
|
|
||||||
// Flex,
|
|
||||||
// Group,
|
|
||||||
// Image,
|
|
||||||
// Loader,
|
|
||||||
// NavLink,
|
|
||||||
// ScrollArea,
|
|
||||||
// Text,
|
|
||||||
// Tooltip,
|
|
||||||
// rem
|
|
||||||
// } from "@mantine/core";
|
|
||||||
// import { useDisclosure } from "@mantine/hooks";
|
|
||||||
// import {
|
|
||||||
// IconChevronLeft,
|
|
||||||
// IconChevronRight,
|
|
||||||
// IconLogout2
|
|
||||||
// } from "@tabler/icons-react";
|
|
||||||
// import _ from "lodash";
|
|
||||||
// import Link from "next/link";
|
|
||||||
// import { useRouter, useSelectedLayoutSegments } from "next/navigation";
|
|
||||||
// import { useEffect, useState } from "react";
|
|
||||||
// // import { useSnapshot } from "valtio";
|
|
||||||
// import { getNavbar } from "./(dashboard)/user&role/_com/dynamicNavbar";
|
|
||||||
|
|
||||||
// export default function Layout({ children }: { children: React.ReactNode }) {
|
|
||||||
// const [opened, { toggle }] = useDisclosure();
|
|
||||||
// const [loading, setLoading] = useState(true);
|
|
||||||
// const [isLoggingOut, setIsLoggingOut] = useState(false);
|
|
||||||
// const [desktopOpened, { toggle: toggleDesktop }] = useDisclosure(true);
|
|
||||||
// const router = useRouter();
|
|
||||||
// const segments = useSelectedLayoutSegments().map((s) => _.lowerCase(s));
|
|
||||||
|
|
||||||
// // const { user } = useSnapshot(authStore);
|
|
||||||
|
|
||||||
// // console.log("Current user in store:", user);
|
|
||||||
|
|
||||||
// // ✅ FIX: Selalu fetch user data setiap kali komponen mount
|
|
||||||
// useEffect(() => {
|
|
||||||
// const fetchUser = async () => {
|
|
||||||
// try {
|
|
||||||
// const res = await fetch('/api/auth/me');
|
|
||||||
// const data = await res.json();
|
|
||||||
|
|
||||||
// if (data.user) {
|
|
||||||
// // ✅ Check if user is NOT active → redirect to waiting room
|
|
||||||
// if (!data.user.isActive) {
|
|
||||||
// authStore.setUser(null);
|
|
||||||
// router.replace('/waiting-room');
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ✅ Fetch menuIds
|
|
||||||
// const menuRes = await fetch(`/api/admin/user-menu-access?userId=${data.user.id}`);
|
|
||||||
// const menuData = await menuRes.json();
|
|
||||||
|
|
||||||
// const menuIds = menuData.success && Array.isArray(menuData.menuIds)
|
|
||||||
// ? [...menuData.menuIds]
|
|
||||||
// : null;
|
|
||||||
|
|
||||||
// // ✅ Set user dengan menuIds yang fresh
|
|
||||||
// authStore.setUser({
|
|
||||||
// id: data.user.id,
|
|
||||||
// name: data.user.name,
|
|
||||||
// roleId: Number(data.user.roleId),
|
|
||||||
// menuIds,
|
|
||||||
// isActive: data.user.isActive
|
|
||||||
// });
|
|
||||||
|
|
||||||
// // ✅ TAMBAHKAN INI: Redirect ke dashboard sesuai roleId
|
|
||||||
// const currentPath = window.location.pathname;
|
|
||||||
// const expectedPath = getRedirectPath(Number(data.user.roleId));
|
|
||||||
|
|
||||||
// // Jika user di halaman /admin tapi bukan di path yang sesuai roleId
|
|
||||||
// if (currentPath === '/admin' || !currentPath.startsWith(expectedPath)) {
|
|
||||||
// router.replace(expectedPath);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// } else {
|
|
||||||
// authStore.setUser(null);
|
|
||||||
// router.replace('/login');
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error('Gagal memuat data pengguna:', error);
|
|
||||||
// authStore.setUser(null);
|
|
||||||
// router.replace('/login');
|
|
||||||
// } finally {
|
|
||||||
// setLoading(false);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// fetchUser();
|
|
||||||
// }, [router]);
|
|
||||||
|
|
||||||
// // ✅ Fungsi helper untuk get redirect path
|
|
||||||
// const getRedirectPath = (roleId: number): string => {
|
|
||||||
// switch (roleId) {
|
|
||||||
// case 0: // DEVELOPER
|
|
||||||
// case 1: // SUPERADMIN
|
|
||||||
// case 2: // ADMIN_DESA
|
|
||||||
// return '/admin/landing-page/profil/program-inovasi';
|
|
||||||
// case 3: // ADMIN_KESEHATAN
|
|
||||||
// return '/admin/kesehatan/posyandu';
|
|
||||||
// case 4: // ADMIN_PENDIDIKAN
|
|
||||||
// return '/admin/pendidikan/info-sekolah/jenjang-pendidikan';
|
|
||||||
// default:
|
|
||||||
// return '/admin';
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// if (loading) {
|
|
||||||
// return (
|
|
||||||
// <AppShell>
|
|
||||||
// <AppShellMain>
|
|
||||||
// <Center h="100vh">
|
|
||||||
// <Loader />
|
|
||||||
// </Center>
|
|
||||||
// </AppShellMain>
|
|
||||||
// </AppShell>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // ✅ Ambil menu berdasarkan roleId dan menuIds
|
|
||||||
// const currentNav = authStore.user
|
|
||||||
// ? getNavbar({ roleId: authStore.user.roleId, menuIds: authStore.user.menuIds })
|
|
||||||
// : [];
|
|
||||||
|
|
||||||
// const handleLogout = async () => {
|
|
||||||
// try {
|
|
||||||
// setIsLoggingOut(true);
|
|
||||||
|
|
||||||
// // ✅ Panggil API logout untuk clear session di server
|
|
||||||
// const response = await fetch('/api/auth/logout', { method: 'POST' });
|
|
||||||
// const result = await response.json();
|
|
||||||
|
|
||||||
// if (result.success) {
|
|
||||||
// // Clear user data dari store
|
|
||||||
// authStore.setUser(null);
|
|
||||||
|
|
||||||
// // Clear localStorage
|
|
||||||
// localStorage.removeItem('auth_nomor');
|
|
||||||
// localStorage.removeItem('auth_kodeId');
|
|
||||||
|
|
||||||
// // Force reload untuk reset semua state
|
|
||||||
// window.location.href = '/login';
|
|
||||||
// } else {
|
|
||||||
// console.error('Logout failed:', result.message);
|
|
||||||
// // Tetap redirect meskipun gagal
|
|
||||||
// authStore.setUser(null);
|
|
||||||
// window.location.href = '/login';
|
|
||||||
// }
|
|
||||||
// } catch (error) {
|
|
||||||
// console.error('Error during logout:', error);
|
|
||||||
// // Tetap clear store dan redirect jika error
|
|
||||||
// authStore.setUser(null);
|
|
||||||
// window.location.href = '/login';
|
|
||||||
// } finally {
|
|
||||||
// setIsLoggingOut(false);
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <AppShell
|
|
||||||
// suppressHydrationWarning
|
|
||||||
// header={{ height: 64 }}
|
|
||||||
// navbar={{
|
|
||||||
// width: { base: 260, sm: 280, lg: 300 },
|
|
||||||
// breakpoint: 'sm',
|
|
||||||
// collapsed: {
|
|
||||||
// mobile: !opened,
|
|
||||||
// desktop: !desktopOpened,
|
|
||||||
// },
|
|
||||||
// }}
|
|
||||||
// padding="md"
|
|
||||||
// >
|
|
||||||
// <AppShellHeader
|
|
||||||
// style={{
|
|
||||||
// background: "linear-gradient(90deg, #ffffff, #f9fbff)",
|
|
||||||
// borderBottom: `1px solid ${colors["blue-button"]}20`,
|
|
||||||
// padding: '0 16px',
|
|
||||||
// }}
|
|
||||||
// px={{ base: 'sm', sm: 'md' }}
|
|
||||||
// py={{ base: 'xs', sm: 'sm' }}
|
|
||||||
// >
|
|
||||||
// <Group w="100%" h="100%" justify="space-between" wrap="nowrap">
|
|
||||||
// <Flex align="center" gap="sm">
|
|
||||||
// <Image
|
|
||||||
// src="/assets/images/darmasaba-icon.png"
|
|
||||||
// alt="Logo Darmasaba"
|
|
||||||
// w={{ base: 32, sm: 40 }}
|
|
||||||
// h={{ base: 32, sm: 40 }}
|
|
||||||
// radius="md"
|
|
||||||
// loading="lazy"
|
|
||||||
// style={{
|
|
||||||
// minWidth: '32px',
|
|
||||||
// height: 'auto',
|
|
||||||
// }}
|
|
||||||
// />
|
|
||||||
// <Text
|
|
||||||
// fw={700}
|
|
||||||
// c={colors["blue-button"]}
|
|
||||||
// fz={{ base: 'md', sm: 'xl' }}
|
|
||||||
// >
|
|
||||||
// Admin Darmasaba
|
|
||||||
// </Text>
|
|
||||||
// </Flex>
|
|
||||||
|
|
||||||
// <Group gap="xs">
|
|
||||||
// {!desktopOpened && (
|
|
||||||
// <Tooltip label="Buka Navigasi" position="bottom" withArrow>
|
|
||||||
// <ActionIcon
|
|
||||||
// variant="light"
|
|
||||||
// radius="xl"
|
|
||||||
// size="lg"
|
|
||||||
// onClick={toggleDesktop}
|
|
||||||
// color={colors["blue-button"]}
|
|
||||||
// >
|
|
||||||
// <IconChevronRight />
|
|
||||||
// </ActionIcon>
|
|
||||||
// </Tooltip>
|
|
||||||
// )}
|
|
||||||
|
|
||||||
// <Burger
|
|
||||||
// opened={opened}
|
|
||||||
// onClick={toggle}
|
|
||||||
// hiddenFrom="sm"
|
|
||||||
// size="md"
|
|
||||||
// color={colors["blue-button"]}
|
|
||||||
// mr="xs"
|
|
||||||
// />
|
|
||||||
|
|
||||||
// <Tooltip label="Kembali ke Website Desa" position="bottom" withArrow>
|
|
||||||
// <ActionIcon
|
|
||||||
// onClick={() => {
|
|
||||||
// router.push("/darmasaba");
|
|
||||||
// }}
|
|
||||||
// color={colors["blue-button"]}
|
|
||||||
// radius="xl"
|
|
||||||
// size="lg"
|
|
||||||
// variant="gradient"
|
|
||||||
// gradient={{ from: colors["blue-button"], to: "#228be6" }}
|
|
||||||
// >
|
|
||||||
// <Image
|
|
||||||
// src="/assets/images/darmasaba-icon.png"
|
|
||||||
// alt="Logo Darmasaba"
|
|
||||||
// w={20}
|
|
||||||
// h={20}
|
|
||||||
// radius="md"
|
|
||||||
// loading="lazy"
|
|
||||||
// style={{
|
|
||||||
// minWidth: '20px',
|
|
||||||
// height: 'auto',
|
|
||||||
// }}
|
|
||||||
// />
|
|
||||||
// </ActionIcon>
|
|
||||||
// </Tooltip>
|
|
||||||
// <Tooltip label="Keluar" position="bottom" withArrow>
|
|
||||||
// <ActionIcon
|
|
||||||
// onClick={handleLogout}
|
|
||||||
// color={colors["blue-button"]}
|
|
||||||
// radius="xl"
|
|
||||||
// size="lg"
|
|
||||||
// variant="gradient"
|
|
||||||
// gradient={{ from: colors["blue-button"], to: "#228be6" }}
|
|
||||||
// loading={isLoggingOut}
|
|
||||||
// disabled={isLoggingOut}
|
|
||||||
// >
|
|
||||||
// <IconLogout2 size={22} />
|
|
||||||
// </ActionIcon>
|
|
||||||
// </Tooltip>
|
|
||||||
// </Group>
|
|
||||||
// </Group>
|
|
||||||
// </AppShellHeader>
|
|
||||||
|
|
||||||
// <AppShellNavbar
|
|
||||||
// component={ScrollArea}
|
|
||||||
// style={{
|
|
||||||
// background: "#ffffff",
|
|
||||||
// borderRight: `1px solid ${colors["blue-button"]}20`,
|
|
||||||
// }}
|
|
||||||
// p={{ base: 'xs', sm: 'sm' }}
|
|
||||||
// >
|
|
||||||
// <AppShell.Section p="sm">
|
|
||||||
// {currentNav.map((v, k) => {
|
|
||||||
// const isParentActive = segments.includes(_.lowerCase(v.name));
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <NavLink
|
|
||||||
// key={k}
|
|
||||||
// defaultOpened={isParentActive}
|
|
||||||
// c={isParentActive ? colors["blue-button"] : "gray"}
|
|
||||||
// label={
|
|
||||||
// <Text fw={isParentActive ? 600 : 400} fz="sm">
|
|
||||||
// {v.name}
|
|
||||||
// </Text>
|
|
||||||
// }
|
|
||||||
// style={{
|
|
||||||
// borderRadius: rem(10),
|
|
||||||
// marginBottom: rem(4),
|
|
||||||
// transition: "background 150ms ease",
|
|
||||||
// }}
|
|
||||||
// styles={{
|
|
||||||
// root: {
|
|
||||||
// '&:hover': {
|
|
||||||
// backgroundColor: 'rgba(25, 113, 194, 0.05)',
|
|
||||||
// },
|
|
||||||
// },
|
|
||||||
// }}
|
|
||||||
// variant="light"
|
|
||||||
// active={isParentActive}
|
|
||||||
// >
|
|
||||||
// {v.children.map((child, key) => {
|
|
||||||
// const isChildActive = segments.includes(
|
|
||||||
// _.lowerCase(child.name)
|
|
||||||
// );
|
|
||||||
|
|
||||||
// return (
|
|
||||||
// <NavLink
|
|
||||||
// key={key}
|
|
||||||
// href={child.path}
|
|
||||||
// c={isChildActive ? colors["blue-button"] : "gray"}
|
|
||||||
// label={
|
|
||||||
// <Text fw={isChildActive ? 600 : 400} fz="sm">
|
|
||||||
// {child.name}
|
|
||||||
// </Text>
|
|
||||||
// }
|
|
||||||
// styles={{
|
|
||||||
// root: {
|
|
||||||
// borderRadius: rem(8),
|
|
||||||
// marginBottom: rem(2),
|
|
||||||
// transition: 'background 150ms ease',
|
|
||||||
// padding: '6px 12px',
|
|
||||||
// '&:hover': {
|
|
||||||
// backgroundColor: isChildActive ? 'rgba(25, 113, 194, 0.15)' : 'rgba(25, 113, 194, 0.05)',
|
|
||||||
// },
|
|
||||||
// ...(isChildActive && {
|
|
||||||
// backgroundColor: 'rgba(25, 113, 194, 0.1)',
|
|
||||||
// }),
|
|
||||||
// },
|
|
||||||
// }}
|
|
||||||
// active={isChildActive}
|
|
||||||
// component={Link}
|
|
||||||
// />
|
|
||||||
// );
|
|
||||||
// })}
|
|
||||||
// </NavLink>
|
|
||||||
// );
|
|
||||||
// })}
|
|
||||||
// </AppShell.Section>
|
|
||||||
|
|
||||||
// <AppShell.Section py="md">
|
|
||||||
// <Group justify="end" pr="sm">
|
|
||||||
// <Tooltip
|
|
||||||
// label={desktopOpened ? "Tutup Navigasi" : "Buka Navigasi"}
|
|
||||||
// position="top"
|
|
||||||
// withArrow
|
|
||||||
// >
|
|
||||||
// <ActionIcon
|
|
||||||
// variant="light"
|
|
||||||
// radius="xl"
|
|
||||||
// size="lg"
|
|
||||||
// onClick={toggleDesktop}
|
|
||||||
// color={colors["blue-button"]}
|
|
||||||
// >
|
|
||||||
// <IconChevronLeft />
|
|
||||||
// </ActionIcon>
|
|
||||||
// </Tooltip>
|
|
||||||
// </Group>
|
|
||||||
// </AppShell.Section>
|
|
||||||
// </AppShellNavbar>
|
|
||||||
|
|
||||||
// <AppShellMain
|
|
||||||
// style={{
|
|
||||||
// background: "linear-gradient(180deg, #fdfdfd, #f6f9fc)",
|
|
||||||
// minHeight: "100vh",
|
|
||||||
// }}
|
|
||||||
// >
|
|
||||||
// {children}
|
|
||||||
// </AppShellMain>
|
|
||||||
// </AppShell>
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// app/admin/layout.tsx
|
|
||||||
|
|
||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import colors from "@/con/colors";
|
import colors from "@/con/colors";
|
||||||
|
|||||||
@@ -76,13 +76,13 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
<Flex pb={30} justify={'center'} gap={'xl'} align={'center'}>
|
<Flex pb={30} justify={'center'} gap={'xl'} align={'center'}>
|
||||||
<Box>
|
<Box>
|
||||||
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
<Flex gap={{base: 7, md: 5}} align={'center'}>
|
||||||
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Laki-Laki</Text>
|
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Laki-Laki</Text>
|
||||||
<ColorSwatch color="#5082EE" size={30} />
|
<ColorSwatch color="#5082EE" size={30} />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
<Box>
|
<Box>
|
||||||
<Flex gap={{ base: 0, md: 5 }} align={'center'}>
|
<Flex gap={{base: 7, md: 5}} align={'center'}>
|
||||||
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Perempuan</Text>
|
<Text fw={'bold'} fz={{ base: 'md', md: 'h4' }}>Perempuan</Text>
|
||||||
<ColorSwatch color="#6EDF9C" size={30} />
|
<ColorSwatch color="#6EDF9C" size={30} />
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ function Page() {
|
|||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={20} />}
|
||||||
w={{ base: "50%", md: "100%" }}
|
w={"100%"}
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Stack, Box, Text, Paper, Skeleton } from '@mantine/core';
|
import { Stack, Box, Text, Paper, Skeleton, Center } from '@mantine/core';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
import { BarChart } from '@mantine/charts';
|
import { BarChart } from '@mantine/charts';
|
||||||
@@ -53,6 +53,7 @@ function Page() {
|
|||||||
Ton: item.value,
|
Ton: item.value,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
const chartWidth = Math.max(600, chartData.length * 150); // contoh: 150px per bar
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||||
@@ -78,24 +79,29 @@ function Page() {
|
|||||||
<Box style={{ width: '100%', overflowX: 'auto' }}>
|
<Box style={{ width: '100%', overflowX: 'auto' }}>
|
||||||
<Paper p="xl">
|
<Paper p="xl">
|
||||||
<Text pb={10} fw="bold" fz="h4">Statistik Sektor Unggulan Darmasaba</Text>
|
<Text pb={10} fw="bold" fz="h4">Statistik Sektor Unggulan Darmasaba</Text>
|
||||||
<Box style={{ width: '100%', minWidth: '600px' }}>
|
<Box style={{ width: '100%', overflowX: 'auto', maxWidth: `${chartWidth}px` }}>
|
||||||
<BarChart
|
<Center>
|
||||||
p={10}
|
<BarChart
|
||||||
h={300}
|
p={10}
|
||||||
data={chartData}
|
h={300}
|
||||||
dataKey="sektor"
|
data={chartData}
|
||||||
series={[
|
dataKey="sektor"
|
||||||
{ name: 'Ton', color: colors['blue-button'] },
|
series={[
|
||||||
]}
|
{ name: 'Ton', color: colors['blue-button'] },
|
||||||
tickLine="y"
|
]}
|
||||||
tooltipAnimationDuration={200}
|
tickLine="y"
|
||||||
withTooltip
|
tooltipAnimationDuration={200}
|
||||||
style={{
|
withTooltip
|
||||||
fontFamily: 'inherit',
|
withXAxis
|
||||||
}}
|
withYAxis
|
||||||
xAxisLabel="Sektor"
|
xAxisLabel="Sektor"
|
||||||
yAxisLabel="Ton"
|
yAxisLabel="Ton"
|
||||||
/>
|
style={{
|
||||||
|
fontFamily: 'inherit',
|
||||||
|
fontSize: '12px', // ukuran font lebih kecil di mobile
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Center>
|
||||||
</Box>
|
</Box>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -365,7 +365,6 @@ function StrukturOrganisasiBumDes() {
|
|||||||
<Box
|
<Box
|
||||||
ref={chartContainerRef}
|
ref={chartContainerRef}
|
||||||
style={{
|
style={{
|
||||||
borderRadius: '12px',
|
|
||||||
overflowX: 'auto',
|
overflowX: 'auto',
|
||||||
overflowY: 'auto',
|
overflowY: 'auto',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
|
|||||||
@@ -1,20 +1,18 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor';
|
||||||
import ajukanIdeInovatifState from '@/app/admin/(dashboard)/_state/inovasi/ajukan-ide-inovatif';
|
import ajukanIdeInovatifState from '@/app/admin/(dashboard)/_state/inovasi/ajukan-ide-inovatif';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { ActionIcon, Box, Button, Flex, List, ListItem, Modal, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
|
import { ActionIcon, Box, Button, Flex, List, ListItem, Modal, Paper, SimpleGrid, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||||
import { useDisclosure } from '@mantine/hooks';
|
import { useDisclosure } from '@mantine/hooks';
|
||||||
import { IconArrowRight, IconBulbFilled } from '@tabler/icons-react';
|
import { IconBulbFilled } from '@tabler/icons-react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
import CreateEditor from '@/app/admin/(dashboard)/_com/createEditor';
|
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const [opened, { open, close }] = useDisclosure(false);
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
const ideInovatif = useProxy(ajukanIdeInovatifState)
|
const ideInovatif = useProxy(ajukanIdeInovatifState);
|
||||||
|
|
||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
// Reset state di valtio
|
|
||||||
ideInovatif.create.form = {
|
ideInovatif.create.form = {
|
||||||
name: "",
|
name: "",
|
||||||
deskripsi: "",
|
deskripsi: "",
|
||||||
@@ -23,53 +21,66 @@ function Page() {
|
|||||||
masalah: "",
|
masalah: "",
|
||||||
benefit: "",
|
benefit: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
// Reset state lokal
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
// Submit data berita
|
|
||||||
await ideInovatif.create.create();
|
await ideInovatif.create.create();
|
||||||
|
|
||||||
// Reset form setelah submit
|
|
||||||
resetForm();
|
resetForm();
|
||||||
close();
|
close();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap="22">
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: 'md', md: 100 }} >
|
|
||||||
<Text ta={"center"} fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
|
<Title
|
||||||
|
order={1}
|
||||||
|
ta="center"
|
||||||
|
c={colors["blue-button"]}
|
||||||
|
fw="bold"
|
||||||
|
style={{ fontSize: 'clamp(1.75rem, 4vw, 2.25rem)' }}
|
||||||
|
>
|
||||||
Ajukan Ide Inovatif
|
Ajukan Ide Inovatif
|
||||||
|
</Title>
|
||||||
|
<Text ta="center" fz={{ base: 'sm', md: 'md' }} c="black" lh="1.6">
|
||||||
|
Desa Darmasaba percaya bahwa setiap warga memiliki potensi luar biasa untuk menciptakan perubahan positif. Platform "Ajukan Ide Inovatif" hadir sebagai ruang inklusif bagi seluruh masyarakat untuk mengembangkan dan mengusulkan gagasan transformatif.
|
||||||
</Text>
|
</Text>
|
||||||
<Text ta={'center'} fz={'h4'}>Desa Darmasaba percaya bahwa setiap warga memiliki potensi luar biasa untuk menciptakan perubahan positif. Platform "Ajukan Ide Inovatif" hadir sebagai ruang inklusif bagi seluruh masyarakat untuk mengembangkan dan mengusulkan gagasan transformatif.</Text>
|
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<Stack gap={'lg'} p={'lg'}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<SimpleGrid
|
<Stack gap="lg" p="lg">
|
||||||
cols={{
|
<SimpleGrid cols={{ base: 1, md: 2 }}>
|
||||||
base: 1,
|
<Paper p="xl">
|
||||||
md: 2,
|
<Stack gap="xs">
|
||||||
}}
|
<Title order={2} c={colors['blue-button']} fw="bold">
|
||||||
>
|
Tujuan Ide Inovatif Ini
|
||||||
<Paper p={'xl'} >
|
</Title>
|
||||||
<Stack gap={"xs"}>
|
<List>
|
||||||
<Text fz={'h3'} fw={'bold'} c={colors['blue-button']}>Tujuan Ide Inovatif Ini</Text>
|
<ListItem ta="justify" fz={{ base: 'sm', md: 'md' }} lh="1.5">
|
||||||
<List>
|
Mendorong partisipasi aktif masyarakat
|
||||||
<ListItem ta={'justify'} fz={{ base: 'h4', md: 'lg' }}>Mendorong partisipasi aktif masyarakat</ListItem>
|
</ListItem>
|
||||||
<ListItem ta={'justify'} fz={{ base: 'h4', md: 'lg' }}>Memfasilitasi inovasi berbasis lokal</ListItem>
|
<ListItem ta="justify" fz={{ base: 'sm', md: 'md' }} lh="1.5">
|
||||||
<ListItem ta={'justify'} fz={{ base: 'h4', md: 'lg' }}>Memecahkan tantangan komunal</ListItem>
|
Memfasilitasi inovasi berbasis lokal
|
||||||
<ListItem ta={'justify'} fz={{ base: 'h4', md: 'lg' }}>Mengembangkan potensi kreativitas warga</ListItem>
|
</ListItem>
|
||||||
</List>
|
<ListItem ta="justify" fz={{ base: 'sm', md: 'md' }} lh="1.5">
|
||||||
|
Memecahkan tantangan komunal
|
||||||
|
</ListItem>
|
||||||
|
<ListItem ta="justify" fz={{ base: 'sm', md: 'md' }} lh="1.5">
|
||||||
|
Mengembangkan potensi kreativitas warga
|
||||||
|
</ListItem>
|
||||||
|
</List>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
<Paper p={'xl'} >
|
|
||||||
<Flex align={'center'} justify={'space-between'}>
|
<Paper p="xl">
|
||||||
|
<Flex align="center" justify="space-between" direction={{ base: 'column', md: 'row' }} gap="md">
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz={'h4'} fw={'bold'} c={colors['blue-button']}>Apabila Anda Ingin Mengajukan Ide Inovatif Bisa Klik Pada Gambar Di Samping</Text>
|
<Title order={3} c={colors['blue-button']} fw="bold" ta={{ base: 'center', md: 'start' }}>
|
||||||
<IconArrowRight size={30} color={colors['blue-button']} />
|
Apabila Anda Ingin Mengajukan Ide Inovatif Bisa Klik Pada Gambar
|
||||||
|
</Title>
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: 5, md: 10 }} py={5}>
|
<Box px={{ base: 5, md: 10 }} py={5}>
|
||||||
<ActionIcon variant="transparent" size={150} onClick={open}>
|
<ActionIcon variant="transparent" size={150} onClick={open}>
|
||||||
@@ -88,32 +99,46 @@ function Page() {
|
|||||||
radius={0}
|
radius={0}
|
||||||
transitionProps={{ transition: 'fade', duration: 200 }}
|
transitionProps={{ transition: 'fade', duration: 200 }}
|
||||||
>
|
>
|
||||||
<Paper p={"md"} withBorder>
|
<Paper p="md" withBorder>
|
||||||
<Stack gap={"xs"}>
|
<Stack gap="xs">
|
||||||
<Title order={3}>Ajukan Ide Inovatif</Title>
|
<Title order={3}>Ajukan Ide Inovatif</Title>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={<Text fz={"sm"} fw={"bold"}>Nama</Text>}
|
label={
|
||||||
|
<Text fz="sm" fw="bold">
|
||||||
|
Nama
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
placeholder="masukkan nama"
|
placeholder="masukkan nama"
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
ideInovatif.create.form.name = val.target.value
|
ideInovatif.create.form.name = val.target.value;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={<Text fz={"sm"} fw={"bold"}>Alamat</Text>}
|
label={
|
||||||
|
<Text fz="sm" fw="bold">
|
||||||
|
Alamat
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
placeholder="masukkan alamat"
|
placeholder="masukkan alamat"
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
ideInovatif.create.form.alamat = val.target.value
|
ideInovatif.create.form.alamat = val.target.value;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={<Text fz={"sm"} fw={"bold"}>Nama Ide</Text>}
|
label={
|
||||||
|
<Text fz="sm" fw="bold">
|
||||||
|
Nama Ide
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
placeholder="masukkan nama ide"
|
placeholder="masukkan nama ide"
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
ideInovatif.create.form.namaIde = val.target.value
|
ideInovatif.create.form.namaIde = val.target.value;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz={"sm"} fw={"bold"}>Deskripsi</Text>
|
<Text fz="sm" fw="bold">
|
||||||
|
Deskripsi
|
||||||
|
</Text>
|
||||||
<CreateEditor
|
<CreateEditor
|
||||||
value={ideInovatif.create.form.deskripsi}
|
value={ideInovatif.create.form.deskripsi}
|
||||||
onChange={(htmlContent) => {
|
onChange={(htmlContent) => {
|
||||||
@@ -122,26 +147,35 @@ function Page() {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={<Text fz={"sm"} fw={"bold"}>Masalah</Text>}
|
label={
|
||||||
|
<Text fz="sm" fw="bold">
|
||||||
|
Masalah
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
placeholder="masukkan masalah"
|
placeholder="masukkan masalah"
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
ideInovatif.create.form.masalah = val.target.value
|
ideInovatif.create.form.masalah = val.target.value;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label={<Text fz={"sm"} fw={"bold"}>Benefit</Text>}
|
label={
|
||||||
|
<Text fz="sm" fw="bold">
|
||||||
|
Benefit
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
placeholder="masukkan benefit"
|
placeholder="masukkan benefit"
|
||||||
onChange={(val) => {
|
onChange={(val) => {
|
||||||
ideInovatif.create.form.benefit = val.target.value
|
ideInovatif.create.form.benefit = val.target.value;
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button bg={colors['blue-button']} onClick={handleSubmit}>Simpan</Button>
|
<Button bg={colors['blue-button']} onClick={handleSubmit}>
|
||||||
|
Simpan
|
||||||
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -54,11 +54,11 @@ function Page() {
|
|||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={20} />}
|
||||||
w={{ base: "50%", md: "100%" }}
|
w={"100%"}
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Text fz={'md'}>Menjadikan Desa Darmasaba pusat inovasi digital untuk pemberdayaan masyarakat</Text>
|
<Text pt={20} fz={'md'}>Menjadikan Desa Darmasaba pusat inovasi digital untuk pemberdayaan masyarakat</Text>
|
||||||
<Text fz={'md'}>dan peningkatan ekonomi berbasis teknologi.</Text>
|
<Text fz={'md'}>dan peningkatan ekonomi berbasis teknologi.</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
import { Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import infoTeknoState from '@/app/admin/(dashboard)/_state/inovasi/info-tekno';
|
import infoTeknoState from '@/app/admin/(dashboard)/_state/inovasi/info-tekno';
|
||||||
import { IconSearch } from '@tabler/icons-react';
|
import { IconSearch } from '@tabler/icons-react';
|
||||||
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const [search, setSearch] = useState("")
|
const [search, setSearch] = useState("")
|
||||||
const [debouncedSearch] = useDebouncedValue(search, 1000); // 500ms delay
|
const [debouncedSearch] = useDebouncedValue(search, 1000);
|
||||||
const state = useProxy(infoTeknoState)
|
const state = useProxy(infoTeknoState)
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
@@ -34,17 +34,24 @@ function Page() {
|
|||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: 'md', md: 100 }} >
|
|
||||||
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<Grid align='center'>
|
<Grid align='center'>
|
||||||
<GridCol span={{ base: 12, md: 9 }}>
|
<GridCol span={{ base: 12, md: 9 }}>
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<Title
|
||||||
|
order={1}
|
||||||
|
c={colors["blue-button"]}
|
||||||
|
fw={"bold"}
|
||||||
|
ta={{ base: 'center', md: 'left' }}
|
||||||
|
>
|
||||||
Info Teknologi Tepat Guna
|
Info Teknologi Tepat Guna
|
||||||
</Text>
|
</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 3 }}>
|
<GridCol span={{ base: 12, md: 3 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -53,13 +60,19 @@ function Page() {
|
|||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={20} />}
|
||||||
w={{ base: "50%", md: "100%" }}
|
w={{ base: "100%", md: "100%" }}
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Text fz={'md'}>Desa Darmasaba berkomitmen mengembangkan teknologi tepat guna yang sesuai dengan kebutuhan masyarakat,</Text>
|
|
||||||
<Text fz={'md'}>mendukung pembangunan berkelanjutan, dan meningkatkan kualitas hidup warga.</Text>
|
<Text pt={20} fz={{ base: 'sm', md: 'md' }} ta={{ base: 'center', md: 'left' }} lh={1.5}>
|
||||||
|
Desa Darmasaba berkomitmen mengembangkan teknologi tepat guna yang sesuai dengan kebutuhan masyarakat,
|
||||||
|
</Text>
|
||||||
|
<Text fz={{ base: 'sm', md: 'md' }} ta={{ base: 'center', md: 'left' }} lh={1.5}>
|
||||||
|
mendukung pembangunan berkelanjutan, dan meningkatkan kualitas hidup warga.
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<Stack gap={'lg'} p={'lg'}>
|
<Stack gap={'lg'} p={'lg'}>
|
||||||
<SimpleGrid
|
<SimpleGrid
|
||||||
@@ -74,12 +87,14 @@ function Page() {
|
|||||||
<Paper p={'xl'} key={k}>
|
<Paper p={'xl'} key={k}>
|
||||||
<Stack gap={"xs"}>
|
<Stack gap={"xs"}>
|
||||||
<Image src={v.image.link || ''} pb={10} radius={10} alt='' loading="lazy" />
|
<Image src={v.image.link || ''} pb={10} radius={10} alt='' loading="lazy" />
|
||||||
<Text fz={'h3'} fw={'bold'}>{v.name}</Text>
|
<Title order={3} fw={'bold'} ta="left">
|
||||||
|
{v.name}
|
||||||
|
</Title>
|
||||||
<Box pr={'lg'} pb={10}>
|
<Box pr={'lg'} pb={10}>
|
||||||
<Text
|
<Text
|
||||||
size="md"
|
fz={{ base: 'xs', md: 'sm' }}
|
||||||
ta="justify"
|
ta="justify"
|
||||||
lh={1} // line height biar enak dibaca
|
lh={1.5}
|
||||||
style={{
|
style={{
|
||||||
wordBreak: "break-word",
|
wordBreak: "break-word",
|
||||||
whiteSpace: "normal",
|
whiteSpace: "normal",
|
||||||
@@ -94,10 +109,11 @@ function Page() {
|
|||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Center>
|
<Center>
|
||||||
<Pagination
|
<Pagination
|
||||||
value={page}
|
value={page}
|
||||||
onChange={(newPage) => load(newPage)} // ini penting!
|
onChange={(newPage) => load(newPage)}
|
||||||
total={totalPages}
|
total={totalPages}
|
||||||
my="md"
|
my="md"
|
||||||
/>
|
/>
|
||||||
@@ -106,4 +122,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client'
|
'use client'
|
||||||
|
|
||||||
import { Box, Center, Image, Paper, Skeleton, Stack, Text } from '@mantine/core'
|
import { Box, Center, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core'
|
||||||
import { useShallowEffect } from '@mantine/hooks'
|
import { useShallowEffect } from '@mantine/hooks'
|
||||||
import { useParams } from 'next/navigation'
|
import { useParams } from 'next/navigation'
|
||||||
import { useProxy } from 'valtio/utils'
|
import { useProxy } from 'valtio/utils'
|
||||||
@@ -31,59 +31,62 @@ function DetailKeamananLingkunganUser() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap="lg">
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap="lg">
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
|
|
||||||
{/* Wrapper Detail */}
|
{/* Wrapper Detail */}
|
||||||
<Paper
|
<Paper
|
||||||
withBorder
|
withBorder
|
||||||
w={{ base: '100%', md: '80%' }}
|
w={{ base: '100%', md: '80%' }}
|
||||||
mx="auto"
|
mx="auto"
|
||||||
bg={colors['white-1']}
|
bg={colors['white-1']}
|
||||||
p="xl"
|
p="xl"
|
||||||
radius="lg"
|
radius="lg"
|
||||||
shadow="md"
|
shadow="md"
|
||||||
>
|
>
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
{/* Judul */}
|
{/* Judul */}
|
||||||
<Text
|
<Title
|
||||||
ta="center"
|
order={1}
|
||||||
fz={{ base: 'xl', md: '2xl' }}
|
ta="center"
|
||||||
fw={700}
|
c={colors['blue-button']}
|
||||||
c={colors['blue-button']}
|
style={{ lineHeight: 1.15 }}
|
||||||
>
|
>
|
||||||
{data?.name || 'Tanpa Judul'}
|
{data?.name || 'Tanpa Judul'}
|
||||||
</Text>
|
</Title>
|
||||||
|
|
||||||
{/* Gambar */}
|
{/* Gambar */}
|
||||||
<Center>
|
<Center>
|
||||||
<Image
|
<Image
|
||||||
w={{ base: 250, sm: 400, md: 550 }}
|
w={{ base: 250, sm: 400, md: 550 }}
|
||||||
src={data?.image?.link}
|
src={data?.image?.link}
|
||||||
alt={data?.name || 'gambar keamanan lingkungan'}
|
alt={data?.name || 'gambar keamanan lingkungan'}
|
||||||
radius="md"
|
radius="md"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
fit="cover"
|
fit="cover"
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
|
|
||||||
{/* Deskripsi */}
|
{/* Deskripsi */}
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="lg" fw="bold" mb={5}>
|
<Title order={3} mb={5} style={{ lineHeight: 1.2 }}>
|
||||||
Deskripsi
|
Deskripsi
|
||||||
</Text>
|
</Title>
|
||||||
<Text
|
<Box pl={20}>
|
||||||
fz="md"
|
<Text
|
||||||
c="dimmed"
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
dangerouslySetInnerHTML={{ __html: data?.deskripsi || '-' }}
|
lh={{ base: 1.5, md: 1.55 }}
|
||||||
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
c={data?.deskripsi ? 'text' : 'dimmed'}
|
||||||
/>
|
dangerouslySetInnerHTML={{ __html: data?.deskripsi || '-' }}
|
||||||
</Box>
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
</Stack>
|
/>
|
||||||
</Paper>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DetailKeamananLingkunganUser
|
export default DetailKeamananLingkunganUser
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import keamananLingkunganState from '@/app/admin/(dashboard)/_state/keamanan/keamanan-lingkungan';
|
import keamananLingkunganState from '@/app/admin/(dashboard)/_state/keamanan/keamanan-lingkungan';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
import { Box, Button, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconSearch } from '@tabler/icons-react';
|
import { IconSearch } from '@tabler/icons-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
@@ -14,7 +14,7 @@ function Page() {
|
|||||||
const state = useProxy(keamananLingkunganState)
|
const state = useProxy(keamananLingkunganState)
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const [search, setSearch] = useState('')
|
const [search, setSearch] = useState('')
|
||||||
const [debouncedSearch] = useDebouncedValue(search, 1000); // 500ms delay
|
const [debouncedSearch] = useDebouncedValue(search, 1000);
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
page,
|
page,
|
||||||
@@ -43,9 +43,9 @@ function Page() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
||||||
<GridCol span={{ base: 12, md: 9 }}>
|
<GridCol span={{ base: 12, md: 9 }}>
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<Title order={1} c={colors["blue-button"]} lh={1.15}>
|
||||||
Keamanan Lingkungan (Pecalang / Patwal)
|
Keamanan Lingkungan (Pecalang / Patwal)
|
||||||
</Text>
|
</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 3 }}>
|
<GridCol span={{ base: 12, md: 3 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
@@ -54,18 +54,29 @@ function Page() {
|
|||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={20} />}
|
||||||
w={{ base: "50%", md: "100%" }}
|
w={"100%"}
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Text px={{ base: 'md', md: 100 }} pt={20} ta={"justify"} fz="md" mt={4} >
|
<Text
|
||||||
|
px={{ base: 'md', md: 100 }}
|
||||||
|
pt={20}
|
||||||
|
ta={"justify"}
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
lh={1.55}
|
||||||
|
mt={4}
|
||||||
|
c={'black'}
|
||||||
|
>
|
||||||
Pecalang dan Patwal (Patroli Pengawal) bertugas memastikan desa tetap aman, tertib, dan kondusif bagi seluruh warga.
|
Pecalang dan Patwal (Patroli Pengawal) bertugas memastikan desa tetap aman, tertib, dan kondusif bagi seluruh warga.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<Stack gap={'lg'}>
|
<Stack gap={'lg'}>
|
||||||
<SimpleGrid
|
<SimpleGrid
|
||||||
cols={{ base: 1, sm: 2, md: 3 }} spacing="xl" mt="lg">
|
cols={{ base: 1, sm: 2, md: 3 }}
|
||||||
|
spacing="xl"
|
||||||
|
mt="lg"
|
||||||
|
>
|
||||||
{data.map((v, k) => (
|
{data.map((v, k) => (
|
||||||
<Paper
|
<Paper
|
||||||
key={k}
|
key={k}
|
||||||
@@ -107,17 +118,18 @@ function Page() {
|
|||||||
onMouseLeave={(e) => (e.currentTarget.style.transform = 'scale(1)')}
|
onMouseLeave={(e) => (e.currentTarget.style.transform = 'scale(1)')}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
<Text ta="center" fw={700} fz="lg" c={colors['blue-button']}>
|
<Title order={2} ta="center" c={colors['blue-button']} lh={1.2}>
|
||||||
{v.name}
|
{v.name}
|
||||||
</Text>
|
</Title>
|
||||||
<Text
|
<Text
|
||||||
fz="sm"
|
fz={{ base: 'xs', md: 'sm' }}
|
||||||
ta="justify"
|
ta="justify"
|
||||||
lineClamp={3}
|
lineClamp={3}
|
||||||
lh={1.6}
|
lh={1.55}
|
||||||
style={{
|
style={{
|
||||||
minHeight: '4.8em',
|
minHeight: '4.8em',
|
||||||
}}
|
}}
|
||||||
|
c={'black'}
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
@@ -159,4 +171,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import kontakDarurat from '@/app/admin/(dashboard)/_state/keamanan/kontak-darurat-keamanan';
|
import kontakDarurat from '@/app/admin/(dashboard)/_state/keamanan/kontak-darurat-keamanan';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Avatar, Box, Center, Flex, Group, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
import { Avatar, Box, Center, Flex, Group, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconPhoneCall, IconSearch } from '@tabler/icons-react';
|
import { IconPhoneCall, IconSearch } from '@tabler/icons-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
@@ -42,10 +42,10 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
<Group px={{ base: 'md', md: 100 }} justify={'space-between'} align='center'>
|
<Group px={{ base: 'md', md: 100 }} justify={'space-between'} align='center'>
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<Title order={1} c={colors["blue-button"]} style={{ lineHeight: 1.15 }}>
|
||||||
Kontak Darurat
|
Kontak Darurat
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="md" >
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5} c={colors['blue-button-2']} style={{ color: colors['blue-button-2'] }}>
|
||||||
Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung.
|
Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -66,17 +66,21 @@ function Page() {
|
|||||||
<IconPhoneCall size={30} color={colors["blue-button"]} />
|
<IconPhoneCall size={30} color={colors["blue-button"]} />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Box>
|
<Box>
|
||||||
<Text ta={'center'} c={colors['blue-button']} py={10} fz={{ base: "md", md: "h4" }} fw={"bold"} >
|
<Text ta={'center'} c={colors['blue-button']} py={10} fz={{ base: "sm", md: "md" }} fw={"bold"} lh={1.3} >
|
||||||
Nomor Darurat Utama
|
Nomor Darurat Utama
|
||||||
</Text>
|
</Text>
|
||||||
<Text ta={'center'} fw={"bold"} fz={'h2'} c={colors["blue-button"]}>112</Text>
|
<Title order={2} ta={'center'} c={colors["blue-button"]} style={{ lineHeight: 1.15 }}>
|
||||||
|
112
|
||||||
|
</Title>
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
<Center>
|
<Center>
|
||||||
<Text fz={"h1"} c={colors["blue-button"]} fw={"bold"}>Tidak ada kontak darurat yang ditemukan</Text>
|
<Title order={2} c={colors["blue-button"]} style={{ lineHeight: 1.15 }}>
|
||||||
|
Tidak ada kontak darurat yang ditemukan
|
||||||
|
</Title>
|
||||||
</Center>
|
</Center>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
@@ -89,10 +93,10 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
<Group px={{ base: 'md', md: 100 }} justify={'space-between'} align='center'>
|
<Group px={{ base: 'md', md: 100 }} justify={'space-between'} align='center'>
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<Title order={1} c={colors["blue-button"]} style={{ lineHeight: 1.15 }}>
|
||||||
Kontak Darurat
|
Kontak Darurat
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz={{ base: "h4", md: "h3" }} >
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5} c={colors['blue-button-2']}>
|
||||||
Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung.
|
Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -113,10 +117,12 @@ function Page() {
|
|||||||
<IconPhoneCall size={30} color={colors["blue-button"]} />
|
<IconPhoneCall size={30} color={colors["blue-button"]} />
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Box>
|
<Box>
|
||||||
<Text ta={'center'} c={colors['blue-button']} py={10} fz={{ base: "md", md: "h4" }} fw={"bold"} >
|
<Text ta={'center'} c={colors['blue-button']} py={10} fz={{ base: "sm", md: "md" }} fw={"bold"} lh={1.3} >
|
||||||
Nomor Darurat Utama
|
Nomor Darurat Utama
|
||||||
</Text>
|
</Text>
|
||||||
<Text ta={'center'} fw={"bold"} fz={'h2'} c={colors["blue-button"]}>112</Text>
|
<Title order={2} ta={'center'} c={colors["blue-button"]} style={{ lineHeight: 1.15 }}>
|
||||||
|
112
|
||||||
|
</Title>
|
||||||
</Box>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -124,19 +130,13 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
<Box px={{ base: "md", md: 100 }}>
|
||||||
<SimpleGrid cols={{ base: 1, md: 2 }} spacing="xl">
|
<SimpleGrid cols={{ base: 1, md: 2 }} spacing="xl">
|
||||||
{/* Layanan Darurat */}
|
|
||||||
{data.map((item) => (
|
{data.map((item) => (
|
||||||
<a
|
<a
|
||||||
key={item.id}
|
key={item.id}
|
||||||
href={`tel:${item.kontakItems[0]?.kontakItem?.nomorTelepon || '112'}`}
|
href={`tel:${item.kontakItems[0]?.kontakItem?.nomorTelepon || '112'}`}
|
||||||
style={{ textDecoration: 'none' }}
|
style={{ textDecoration: 'none' }}
|
||||||
>
|
>
|
||||||
<Paper
|
<Paper p="lg" radius="md" bg={colors['white-trans-1']}>
|
||||||
|
|
||||||
p="lg"
|
|
||||||
radius="md"
|
|
||||||
bg={colors['white-trans-1']}
|
|
||||||
>
|
|
||||||
<Group pb="md" align="center">
|
<Group pb="md" align="center">
|
||||||
<Avatar radius="xl" size="lg" bg={colors['BG-trans']}>
|
<Avatar radius="xl" size="lg" bg={colors['BG-trans']}>
|
||||||
{item.icon && (
|
{item.icon && (
|
||||||
@@ -147,12 +147,11 @@ function Page() {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</Avatar>
|
</Avatar>
|
||||||
<Text fw="bold" fz={{ base: "lg", md: "xl" }} c={colors["blue-button"]}>
|
<Title order={3} c={colors["blue-button"]} style={{ lineHeight: 1.2 }}>
|
||||||
{item.nama}
|
{item.nama}
|
||||||
</Text>
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
{/* Kontak Items */}
|
|
||||||
{item.kontakItems?.map((kontak) => (
|
{item.kontakItems?.map((kontak) => (
|
||||||
<Paper
|
<Paper
|
||||||
key={kontak.id}
|
key={kontak.id}
|
||||||
@@ -171,11 +170,11 @@ function Page() {
|
|||||||
color={colors['blue-button']}
|
color={colors['blue-button']}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Text fw="bold" fz={{ base: "sm", md: "md" }} c={colors["blue-button"]}>
|
<Text fw="bold" fz={{ base: "xs", md: "sm" }} c={colors["blue-button"]} lh={1.45}>
|
||||||
{kontak.kontakItem?.nama}
|
{kontak.kontakItem?.nama}
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Text fw="bold" fz={{ base: "sm", md: "md" }} c={colors["blue-button"]}>
|
<Text fw="bold" fz={{ base: "xs", md: "sm" }} c={colors["blue-button"]} lh={1.45}>
|
||||||
{kontak.kontakItem?.nomorTelepon}
|
{kontak.kontakItem?.nomorTelepon}
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
@@ -204,4 +203,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import pencegahanKriminalitasState from '@/app/admin/(dashboard)/_state/keamanan/pencegahan-kriminalitas';
|
import pencegahanKriminalitasState from '@/app/admin/(dashboard)/_state/keamanan/pencegahan-kriminalitas';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Center, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Button, Center, Paper, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowRight } from '@tabler/icons-react';
|
import { IconArrowRight } from '@tabler/icons-react';
|
||||||
import { useTransitionRouter } from 'next-view-transitions';
|
import { useTransitionRouter } from 'next-view-transitions';
|
||||||
@@ -26,7 +26,7 @@ function Page() {
|
|||||||
if (!findFirst.data && !findFirst.loading) {
|
if (!findFirst.data && !findFirst.loading) {
|
||||||
kriminalitasState.findFirst.load();
|
kriminalitasState.findFirst.load();
|
||||||
}
|
}
|
||||||
}, [findFirst.data, findFirst.loading]);
|
}, []);
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
const LIMIT = 3;
|
const LIMIT = 3;
|
||||||
@@ -45,10 +45,10 @@ function Page() {
|
|||||||
return (
|
return (
|
||||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap={22}>
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap={22}>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<Text fz={{ base: 'h1', md: '2.5rem' }} c={colors['blue-button']} fw="bold">
|
<Title order={1} c={colors['blue-button']} fw="bold" lh={1.2}>
|
||||||
Pencegahan Kriminalitas
|
Pencegahan Kriminalitas
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz='md'>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
Keamanan Komunitas & Pencegahan Kriminal
|
Keamanan Komunitas & Pencegahan Kriminal
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -58,11 +58,11 @@ function Page() {
|
|||||||
spacing="xl"
|
spacing="xl"
|
||||||
>
|
>
|
||||||
<Paper p="xl" radius="xl" shadow="lg" >
|
<Paper p="xl" radius="xl" shadow="lg" >
|
||||||
<Text fz={{ base: 'h3', md: 'h2' }} c={colors['blue-button']} fw="bold">
|
<Title order={2} c={colors['blue-button']} fw="bold" lh={1.2}>
|
||||||
Program Keamanan Berjalan
|
Program Keamanan Berjalan
|
||||||
</Text>
|
</Title>
|
||||||
<Stack pt={30} gap="lg">
|
<Stack pt={30} gap="lg">
|
||||||
<Text c="dimmed">
|
<Text c="dimmed" fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
Tidak ada data pencegahan kriminalitas yang cocok
|
Tidak ada data pencegahan kriminalitas yang cocok
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -75,10 +75,10 @@ function Page() {
|
|||||||
return (
|
return (
|
||||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap={22}>
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap={22}>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<Text fz={{ base: 'h1', md: '2.5rem' }} c={colors['blue-button']} fw="bold">
|
<Title order={1} c={colors['blue-button']} fw="bold" lh={1.2}>
|
||||||
Pencegahan Kriminalitas
|
Pencegahan Kriminalitas
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz='md'>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
Keamanan Komunitas & Pencegahan Kriminal
|
Keamanan Komunitas & Pencegahan Kriminal
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -88,13 +88,13 @@ function Page() {
|
|||||||
spacing="xl"
|
spacing="xl"
|
||||||
>
|
>
|
||||||
<Paper p="xl" radius="xl" shadow="lg" >
|
<Paper p="xl" radius="xl" shadow="lg" >
|
||||||
<Text fz={{ base: 'h3', md: 'h2' }} c={colors['blue-button']} fw="bold">
|
<Title order={2} c={colors['blue-button']} fw="bold" lh={1.2}>
|
||||||
Program Keamanan Berjalan
|
Program Keamanan Berjalan
|
||||||
</Text>
|
</Title>
|
||||||
<Stack pt={30} gap="lg">
|
<Stack pt={30} gap="lg">
|
||||||
<Box
|
<Box
|
||||||
style={{
|
style={{
|
||||||
minHeight: 300, // sesuaikan: tinggi area yg muat 3 item
|
minHeight: 300,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{data.length > 0 ? (
|
{data.length > 0 ? (
|
||||||
@@ -120,14 +120,16 @@ function Page() {
|
|||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
<Text fz="h3" c={colors['white-1']}>
|
<Title order={3} c={colors['white-1']} lh={1.2}>
|
||||||
{item.judul}
|
{item.judul}
|
||||||
</Text>
|
</Title>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
<Text c="dimmed">Tidak ada data pencegahan kriminalitas yang cocok</Text>
|
<Text c="dimmed" fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
|
Tidak ada data pencegahan kriminalitas yang cocok
|
||||||
|
</Text>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
<Button
|
<Button
|
||||||
@@ -169,12 +171,18 @@ function Page() {
|
|||||||
style={{ borderRadius: 8 }}
|
style={{ borderRadius: 8 }}
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Text fz="sm" c="dimmed">Tidak ada video</Text>
|
<Text fz={{ base: 'xs', md: 'sm' }} c="dimmed" lh={1.4}>
|
||||||
|
Tidak ada video
|
||||||
|
</Text>
|
||||||
)}
|
)}
|
||||||
<Text py={10} fz={{ base: 'h3', md: 'h2' }} fw="bold" c={colors['blue-button']}>
|
<Title order={2} py={10} fw="bold" c={colors['blue-button']} lh={1.2}>
|
||||||
{findFirst.data?.judul}
|
{findFirst.data?.judul}
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="h4" dangerouslySetInnerHTML={{ __html: findFirst.data?.deskripsiSingkat }} />
|
<Text
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
lh={1.5}
|
||||||
|
dangerouslySetInnerHTML={{ __html: findFirst.data?.deskripsiSingkat }}
|
||||||
|
/>
|
||||||
</Paper>
|
</Paper>
|
||||||
) : null}
|
) : null}
|
||||||
</Box>
|
</Box>
|
||||||
@@ -195,4 +203,4 @@ function Page() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
/* eslint-disable react-hooks/exhaustive-deps */
|
/* eslint-disable react-hooks/exhaustive-deps */
|
||||||
import polsekTerdekatState from '@/app/admin/(dashboard)/_state/keamanan/polsek-terdekat';
|
import polsekTerdekatState from '@/app/admin/(dashboard)/_state/keamanan/polsek-terdekat';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Badge, Box, Button, Center, Flex, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
import { Badge, Box, Button, Center, Flex, Paper, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { IconArrowDown, IconClock, IconNavigation, IconPhone, IconPin } from '@tabler/icons-react';
|
import { IconArrowDown, IconClock, IconNavigation, IconPhone, IconPin } from '@tabler/icons-react';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
@@ -35,15 +35,15 @@ function Page() {
|
|||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Box pb={10} px={{ base: 20, md: 100 }}>
|
<Box pb={10} px={{ base: 20, md: 100 }}>
|
||||||
<Text fz={{ base: 'h1', md: '2.5rem' }} c={colors['blue-button']} fw="bold">
|
<Title order={1} c={colors['blue-button']}>
|
||||||
Kantor Polisi Terdekat
|
Kantor Polisi Terdekat
|
||||||
</Text>
|
</Title>
|
||||||
<Text pb={15} fz="md">
|
<Text pb={15} fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung
|
Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
<Center py="xl">
|
<Center py="xl">
|
||||||
<Text fz="lg" fw="bold" c="red">
|
<Text fz={{ base: 'md', md: 'lg' }} fw="bold" c="red" lh={1.4}>
|
||||||
Data Polsek tidak ada
|
Data Polsek tidak ada
|
||||||
</Text>
|
</Text>
|
||||||
</Center>
|
</Center>
|
||||||
@@ -58,10 +58,10 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box pb={10} px={{ base: 20, md: 100 }}>
|
<Box pb={10} px={{ base: 20, md: 100 }}>
|
||||||
<Text fz={{ base: 'h1', md: '2.5rem' }} c={colors['blue-button']} fw="bold">
|
<Title order={1} c={colors['blue-button']}>
|
||||||
Kantor Polisi Terdekat
|
Kantor Polisi Terdekat
|
||||||
</Text>
|
</Title>
|
||||||
<Text pb={15} fz="h4">
|
<Text pb={15} fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung
|
Desa Darmasaba, Kecamatan Abiansemal, Kabupaten Badung
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -79,10 +79,10 @@ function Page() {
|
|||||||
<>
|
<>
|
||||||
{/* === KIRI === */}
|
{/* === KIRI === */}
|
||||||
<Box>
|
<Box>
|
||||||
<Text c={colors['blue-button']} fw="bold" fz="h2">
|
<Title order={2} c={colors['blue-button']} lh={1.2}>
|
||||||
{data.nama}
|
{data.nama}
|
||||||
</Text>
|
</Title>
|
||||||
<Text c={colors['blue-button']} fz="sm">
|
<Text c={colors['blue-button']} fz={{ base: 'xs', md: 'sm' }} lh={1.4}>
|
||||||
{data.jarakKeDesa}
|
{data.jarakKeDesa}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
@@ -98,11 +98,11 @@ function Page() {
|
|||||||
<IconPin size={22} />
|
<IconPin size={22} />
|
||||||
</Box>
|
</Box>
|
||||||
<Text
|
<Text
|
||||||
fz="lg"
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
style={{
|
style={{
|
||||||
flex: 1,
|
flex: 1,
|
||||||
wordBreak: 'break-word',
|
wordBreak: 'break-word',
|
||||||
lineHeight: 1.4,
|
lineHeight: 1.5,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{data.alamat}
|
{data.alamat}
|
||||||
@@ -119,7 +119,7 @@ function Page() {
|
|||||||
<Box w={25} mt={3}>
|
<Box w={25} mt={3}>
|
||||||
<IconPhone size={22} />
|
<IconPhone size={22} />
|
||||||
</Box>
|
</Box>
|
||||||
<Text fz="lg">
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
{data.nomorTelepon}
|
{data.nomorTelepon}
|
||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -133,26 +133,26 @@ function Page() {
|
|||||||
style={{ wordBreak: 'break-word' }}
|
style={{ wordBreak: 'break-word' }}
|
||||||
>
|
>
|
||||||
<Box w={25} mt={3}>
|
<Box w={25} mt={3}>
|
||||||
<IconClock size={22} />
|
<IconClock size={22} />
|
||||||
</Box>
|
</Box>
|
||||||
<Text fz="lg">
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
{data.jamOperasional}
|
{data.jamOperasional}
|
||||||
</Text>
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
{/* Layanan */}
|
{/* Layanan */}
|
||||||
<Box>
|
<Box pt={15}>
|
||||||
<Text c={colors['blue-button']} fw="bold" fz="h2">
|
<Title order={2} c={colors['blue-button']} lh={1.2}>
|
||||||
Layanan Yang Tersedia :
|
Layanan Yang Tersedia:
|
||||||
</Text>
|
</Title>
|
||||||
<SimpleGrid py={10} cols={{ base: 1, md: 2 }}>
|
<SimpleGrid py={10} cols={{ base: 1, md: 2 }}>
|
||||||
<Text fz="lg">
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
{data.layananPolsek.nama}
|
{data.layananPolsek.nama}
|
||||||
</Text>
|
</Text>
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box pt={15}>
|
||||||
<Button
|
<Button
|
||||||
bg={colors['blue-button']}
|
bg={colors['blue-button']}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
@@ -205,4 +205,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import polsekTerdekatState from '@/app/admin/(dashboard)/_state/keamanan/polsek-terdekat';
|
import polsekTerdekatState from '@/app/admin/(dashboard)/_state/keamanan/polsek-terdekat';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Center, Grid, GridCol, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput } from '@mantine/core';
|
import { Box, Button, Center, Grid, GridCol, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconNavigation, IconSearch } from '@tabler/icons-react';
|
import { IconNavigation, IconSearch } from '@tabler/icons-react';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
@@ -13,8 +13,8 @@ import { useDebouncedValue } from '@mantine/hooks';
|
|||||||
function Page() {
|
function Page() {
|
||||||
const state = useProxy(polsekTerdekatState);
|
const state = useProxy(polsekTerdekatState);
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
const [debouncedSearch] = useDebouncedValue(search, 1000); // 500ms delay
|
const [debouncedSearch] = useDebouncedValue(search, 1000);
|
||||||
const router = useRouter()
|
const router = useRouter();
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data,
|
data,
|
||||||
@@ -25,71 +25,98 @@ function Page() {
|
|||||||
} = state.findMany;
|
} = state.findMany;
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
load(page, 3, debouncedSearch)
|
load(page, 3, debouncedSearch);
|
||||||
}, [page, debouncedSearch])
|
}, [page, debouncedSearch]);
|
||||||
|
|
||||||
if (loading || !data) {
|
if (loading || !data) {
|
||||||
return (
|
return (
|
||||||
<Box py={10}>
|
<Box py={10}>
|
||||||
<Skeleton h={500} />
|
<Skeleton h={500} />
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack pos={"relative"} bg={colors.Bg} py={"xl"} gap={"22"}>
|
<Stack pos="relative" bg={colors.Bg} py="xl" gap="22">
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Grid align='center' px={{ base: 'md', md: 100 }}>
|
|
||||||
|
<Grid align="center" px={{ base: 'md', md: 100 }}>
|
||||||
<GridCol span={{ base: 12, md: 9 }}>
|
<GridCol span={{ base: 12, md: 9 }}>
|
||||||
<Text fz={{ base: "h1", md: "2.5rem" }} c={colors["blue-button"]} fw={"bold"}>
|
<Title
|
||||||
|
order={1}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
lh={1.2}
|
||||||
|
>
|
||||||
Semua Polsek Terdekat
|
Semua Polsek Terdekat
|
||||||
</Text>
|
</Title>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
<GridCol span={{ base: 12, md: 3 }}>
|
<GridCol span={{ base: 12, md: 3 }}>
|
||||||
<TextInput
|
<TextInput
|
||||||
radius={"lg"}
|
radius="lg"
|
||||||
placeholder='Cari Polsek'
|
placeholder="Cari Polsek"
|
||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={20} />}
|
||||||
w={{ base: "50%", md: "100%" }}
|
w={{ base: '50%', md: '100%' }}
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Box px={{ base: "md", md: 100 }}>
|
|
||||||
<SimpleGrid
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
cols={{
|
<SimpleGrid cols={{ base: 1, md: 3 }}>
|
||||||
base: 1,
|
{data.map((v, k) => (
|
||||||
md: 3,
|
<Paper p="xl" bg={colors['white-trans-1']} key={k}>
|
||||||
}}
|
<Stack gap="xs">
|
||||||
>
|
<Title
|
||||||
{data.map((v, k) => {
|
order={3}
|
||||||
return (
|
fw="bold"
|
||||||
<Paper p={"xl"} bg={colors['white-trans-1']} key={k}>
|
lh={1.2}
|
||||||
<Stack gap={"xs"}>
|
>
|
||||||
<Text fw={"bold"} fz={"h3"}>{v.nama}</Text>
|
{v.nama}
|
||||||
<Text>Alamat: {v.alamat}</Text>
|
</Title>
|
||||||
<Text>Jarak: {v.jarakKeDesa}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
<Text>Telepon: {v.nomorTelepon}</Text>
|
Alamat: {v.alamat}
|
||||||
<Text>Jam Operasional: {v.jamOperasional}</Text>
|
</Text>
|
||||||
<Box pt={20}>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
<iframe style={{ border: 2, width: "100%" }} src={v.embedMapUrl} width="550" height="300" ></iframe>
|
Jarak: {v.jarakKeDesa}
|
||||||
</Box>
|
</Text>
|
||||||
<Box pt={20}>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
<Button onClick={() => router.push(v.linkPetunjukArah)} fullWidth bg={colors["blue-button"]} radius={10} leftSection={<IconNavigation size={20} />}>Petunjuk Arah</Button>
|
Telepon: {v.nomorTelepon}
|
||||||
</Box>
|
</Text>
|
||||||
</Stack>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>
|
||||||
</Paper>
|
Jam Operasional: {v.jamOperasional}
|
||||||
)
|
</Text>
|
||||||
})}
|
<Box pt={20}>
|
||||||
|
<iframe
|
||||||
|
style={{ border: 2, width: '100%' }}
|
||||||
|
src={v.embedMapUrl}
|
||||||
|
width="550"
|
||||||
|
height="300"
|
||||||
|
></iframe>
|
||||||
|
</Box>
|
||||||
|
<Box pt={20}>
|
||||||
|
<Button
|
||||||
|
onClick={() => router.push(v.linkPetunjukArah)}
|
||||||
|
fullWidth
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
radius={10}
|
||||||
|
leftSection={<IconNavigation size={20} />}
|
||||||
|
>
|
||||||
|
Petunjuk Arah
|
||||||
|
</Button>
|
||||||
|
</Box>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Center>
|
<Center>
|
||||||
<Pagination
|
<Pagination
|
||||||
value={page}
|
value={page}
|
||||||
onChange={(newPage) => load(newPage)} // ini penting!
|
onChange={(newPage) => load(newPage)}
|
||||||
total={totalPages}
|
total={totalPages}
|
||||||
mt="md"
|
mt="md"
|
||||||
mb="md"
|
mb="md"
|
||||||
@@ -99,4 +126,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -56,7 +56,7 @@ function Page() {
|
|||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.target.value)}
|
onChange={(e) => setSearch(e.target.value)}
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={20} />}
|
||||||
w={{ base: '50%', md: '100%' }}
|
w={'100%'}
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
|
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
|
||||||
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
|
import BackButton from '@/app/darmasaba/(pages)/desa/layanan/_com/BackButto';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Divider, Flex, Group, Image, List, ListItem, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text } from '@mantine/core';
|
import { Box, Divider, Flex, Group, Image, List, ListItem, Paper, Skeleton, Stack, Table, TableTbody, TableTd, TableTh, TableThead, TableTr, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconAlertCircle, IconCalendar, IconInfoCircle } from '@tabler/icons-react';
|
import { IconAlertCircle, IconCalendar, IconInfoCircle } from '@tabler/icons-react';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
@@ -37,9 +37,9 @@ function Page() {
|
|||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<Paper radius="xl" shadow="md" withBorder>
|
<Paper radius="xl" shadow="md" withBorder>
|
||||||
<Box style={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }} bg={colors['blue-button']}>
|
<Box style={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }} bg={colors['blue-button']}>
|
||||||
<Text p="md" fz={{ base: 'h3', md: 'h2' }} c={colors['white-1']} fw="bold">
|
<Title order={1} p="md" c={colors['white-1']} fw="bold">
|
||||||
{state.findUnique.data.title || 'Detail Artikel Kesehatan'}
|
{state.findUnique.data.title || 'Detail Artikel Kesehatan'}
|
||||||
</Text>
|
</Title>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box p="lg">
|
<Box p="lg">
|
||||||
@@ -64,7 +64,7 @@ function Page() {
|
|||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconCalendar size={18} color={colors['blue-button']} />
|
<IconCalendar size={18} color={colors['blue-button']} />
|
||||||
<Text c="dimmed" fz="sm">
|
<Text fz={{ base: 'xs', md: 'sm' }} lh={1.5}>
|
||||||
{new Date(state.findUnique.data.createdAt).toLocaleDateString('id-ID', {
|
{new Date(state.findUnique.data.createdAt).toLocaleDateString('id-ID', {
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
month: 'long',
|
month: 'long',
|
||||||
@@ -74,48 +74,47 @@ function Page() {
|
|||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="h4" fw="bold">Pendahuluan</Text>
|
<Title order={2} fw="bold">Pendahuluan</Title>
|
||||||
<Divider my="xs" />
|
<Divider my="xs" />
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text fz="md" lh={1.6} ta="justify" dangerouslySetInnerHTML={{ __html: state.findUnique.data.introduction?.content }} />
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.6} ta="justify" dangerouslySetInnerHTML={{ __html: state.findUnique.data.introduction?.content }} />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="h4" fw="bold">{state.findUnique.data.symptom?.title}</Text>
|
<Title order={2} fw="bold">{state.findUnique.data.symptom?.title}</Title>
|
||||||
<Divider my="xs" />
|
<Divider my="xs" />
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text fz="md" lh={1.6} ta="justify" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.symptom?.content }} />
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.6} ta="justify" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.symptom?.content }} />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="h4" fw="bold">{state.findUnique.data.prevention?.title}</Text>
|
<Title order={2} fw="bold">{state.findUnique.data.prevention?.title}</Title>
|
||||||
<Divider my="xs" />
|
<Divider my="xs" />
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text fz="md" lh={1.6} ta="justify" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.prevention?.content }} />
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.6} ta="justify" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.prevention?.content }} />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="h4" fw="bold">{state.findUnique.data.firstaid?.title}</Text>
|
<Title order={2} fw="bold">{state.findUnique.data.firstaid?.title}</Title>
|
||||||
<Divider my="xs" />
|
<Divider my="xs" />
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text fz="md" lh={1.6} ta="justify" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.firstaid?.content }} />
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.6} ta="justify" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.firstaid?.content }} />
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="h4" fw="bold">{state.findUnique.data.mythvsfact?.title}</Text>
|
<Title order={2} fw="bold">{state.findUnique.data.mythvsfact?.title}</Title>
|
||||||
<Divider my="xs" />
|
<Divider my="xs" />
|
||||||
<Box pb="md">
|
<Box pb="md">
|
||||||
<Table highlightOnHover withTableBorder withColumnBorders striped>
|
<Table highlightOnHover withTableBorder withColumnBorders striped>
|
||||||
<TableThead>
|
<TableThead>
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTh fz="sm" fw="bold">Mitos</TableTh>
|
<TableTh fz={{ base: 'xs', md: 'sm' }} fw="bold">Mitos</TableTh>
|
||||||
<TableTh fz="sm" fw="bold">Fakta</TableTh>
|
<TableTh fz={{ base: 'xs', md: 'sm' }} fw="bold">Fakta</TableTh>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
</TableThead>
|
</TableThead>
|
||||||
<TableTbody>
|
<TableTbody>
|
||||||
@@ -123,12 +122,12 @@ function Page() {
|
|||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text fz="sm" lh={1.6} style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.mythvsfact.mitos }} />
|
<Text fz={{ base: 'xs', md: 'sm' }} lh={1.6} style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.mythvsfact.mitos }} />
|
||||||
</Box>
|
</Box>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd>
|
<TableTd>
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text fz="sm" lh={1.6} style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.mythvsfact.fakta }} />
|
<Text fz={{ base: 'xs', md: 'sm' }} lh={1.6} style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.mythvsfact.fakta }} />
|
||||||
</Box>
|
</Box>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
@@ -143,34 +142,35 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="h4" fw="bold">Kapan Harus ke Dokter?</Text>
|
<Title order={2} fw="bold">Kapan Harus ke Dokter?</Title>
|
||||||
<Divider my="xs" />
|
<Divider my="xs" />
|
||||||
<Flex justify={'flex-start'} gap={"xs"} align={"center"} mb="xs">
|
<Flex justify={'flex-start'} gap={"xs"} align={"center"} mb="xs">
|
||||||
<IconAlertCircle size={18} color="red" />
|
<IconAlertCircle size={18} color="red" />
|
||||||
<Text fz="md">Segera bawa penderita ke fasilitas kesehatan jika mengalami:</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>Segera bawa penderita ke fasilitas kesehatan jika mengalami:</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text fz="md" lh={1.6} dangerouslySetInnerHTML={{ __html: state.findUnique.data.doctorsign.content }} /></Box>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.6} dangerouslySetInnerHTML={{ __html: state.findUnique.data.doctorsign.content }} />
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Paper p="lg" radius="md" bg={colors['blue-button-trans']} withBorder>
|
<Paper p="lg" radius="md" bg={colors['blue-button-trans']} withBorder>
|
||||||
<Group gap="xs" mb="sm">
|
<Group gap="xs" mb="sm">
|
||||||
<IconInfoCircle size={20} color={colors['white-1']} />
|
<IconInfoCircle size={20} color={colors['white-1']} />
|
||||||
<Text fz="h4" c={colors['white-1']} fw="bold">Informasi Lebih Lanjut</Text>
|
<Title order={3} c={colors['white-1']} fw="bold">Informasi Lebih Lanjut</Title>
|
||||||
</Group>
|
</Group>
|
||||||
<Stack gap={4}>
|
<Stack gap={4}>
|
||||||
<Text fz="sm" c={colors['white-1']}>Hotline DBD: <b>(0361) 123456</b></Text>
|
<Text fz={{ base: 'xs', md: 'sm' }} c={colors['white-1']}>Hotline DBD: <b>(0361) 123456</b></Text>
|
||||||
<Text fz="sm" c={colors['white-1']}>WhatsApp Center: <b>081234567890</b></Text>
|
<Text fz={{ base: 'xs', md: 'sm' }} c={colors['white-1']}>WhatsApp Center: <b>081234567890</b></Text>
|
||||||
<Text fz="sm" c={colors['white-1']}>Email: <b>p2p@dinkes.badungkab.go.id</b></Text>
|
<Text fz={{ base: 'xs', md: 'sm' }} c={colors['white-1']}>Email: <b>p2p@dinkes.badungkab.go.id</b></Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="h4" fw="bold">Referensi</Text>
|
<Title order={2} fw="bold">Referensi</Title>
|
||||||
<Divider my="xs" />
|
<Divider my="xs" />
|
||||||
<List spacing="xs" size="sm" type="ordered">
|
<List spacing="xs" fz={{ base: 'xs', md: 'sm' }} type="ordered">
|
||||||
<ListItem>Kementerian Kesehatan RI. (2024). Pedoman Pencegahan dan Pengendalian DBD.</ListItem>
|
<ListItem>Kementerian Kesehatan RI. (2024). Pedoman Pencegahan dan Pengendalian DBD.</ListItem>
|
||||||
<ListItem>World Health Organization. (2024). Dengue Guidelines for Diagnosis, Treatment, Prevention and Control.</ListItem>
|
<ListItem>World Health Organization. (2024). Dengue Guidelines for Diagnosis, Treatment, Prevention and Control.</ListItem>
|
||||||
<ListItem>Dinas Kesehatan Kabupaten Badung. (2025). Laporan Surveilans DBD Triwulan I 2025.</ListItem>
|
<ListItem>Dinas Kesehatan Kabupaten Badung. (2025). Laporan Surveilans DBD Triwulan I 2025.</ListItem>
|
||||||
@@ -186,4 +186,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
|
import artikelKesehatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/artikelKesehatan';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Card, Divider, Group, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Button, Card, Divider, Group, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconCalendar, IconChevronRight } from '@tabler/icons-react';
|
import { IconCalendar, IconChevronRight } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -27,13 +27,13 @@ function ArtikelKesehatanPage() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Paper p="xl" bg={colors['white-trans-1']} radius="xl" shadow="md">
|
<Paper p="xl" bg={colors['white-trans-1']} radius="xl" shadow="md">
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<Text ta="center" fw={700} fz="32px" c={colors['blue-button']}>
|
<Title ta="center" order={1} c={colors['blue-button']}>
|
||||||
Artikel Kesehatan
|
Artikel Kesehatan
|
||||||
</Text>
|
</Title>
|
||||||
<Divider size="sm" color={colors['blue-button']} />
|
<Divider size="sm" color={colors['blue-button']} />
|
||||||
{state.findMany.data.length === 0 ? (
|
{state.findMany.data.length === 0 ? (
|
||||||
<Box py="xl" ta="center">
|
<Box py="xl" ta="center">
|
||||||
<Text fz="lg" c="dimmed">
|
<Text fz={{ base: 'sm', sm: 'md' }} c="dimmed">
|
||||||
Belum ada artikel kesehatan yang tersedia
|
Belum ada artikel kesehatan yang tersedia
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -50,17 +50,26 @@ function ArtikelKesehatanPage() {
|
|||||||
onMouseLeave={(e) => (e.currentTarget.style.transform = 'translateY(0)')}
|
onMouseLeave={(e) => (e.currentTarget.style.transform = 'translateY(0)')}
|
||||||
>
|
>
|
||||||
<Card.Section>
|
<Card.Section>
|
||||||
<Image style={{ borderTopLeftRadius: '10px', borderTopRightRadius: '10px' }} src={item.image?.link} alt={item.title} height={200} fit="cover" loading="lazy" />
|
<Image
|
||||||
|
style={{ borderTopLeftRadius: '10px', borderTopRightRadius: '10px' }}
|
||||||
|
src={item.image?.link}
|
||||||
|
alt={item.title}
|
||||||
|
height={200}
|
||||||
|
fit="cover"
|
||||||
|
loading="lazy"
|
||||||
|
/>
|
||||||
</Card.Section>
|
</Card.Section>
|
||||||
<Stack gap="xs" mt="md">
|
<Stack gap="xs" mt="md">
|
||||||
<Text fw="bold" fz="xl" c={colors['blue-button']}>{item.title}</Text>
|
<Title order={3} c={colors['blue-button']}>
|
||||||
|
{item.title}
|
||||||
|
</Title>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconCalendar size={16} color='gray' />
|
<IconCalendar size={16} color='gray' />
|
||||||
<Text fz="sm" c="dimmed">
|
<Text fz={{ base: 'xs', sm: 'sm' }} c="dimmed">
|
||||||
{new Date(item.createdAt).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' })} • Dinas Kesehatan
|
{new Date(item.createdAt).toLocaleDateString('id-ID', { year: 'numeric', month: 'long', day: 'numeric' })} • Dinas Kesehatan
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Text fz="md" lineClamp={3}>
|
<Text fz={{ base: 'sm', sm: 'md' }} lh={{ base: 'sm', sm: 'md' }} lineClamp={3}>
|
||||||
{item.content}
|
{item.content}
|
||||||
</Text>
|
</Text>
|
||||||
<Group justify="flex-start">
|
<Group justify="flex-start">
|
||||||
@@ -84,4 +93,4 @@ function ArtikelKesehatanPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ArtikelKesehatanPage;
|
export default ArtikelKesehatanPage;
|
||||||
@@ -16,7 +16,6 @@ interface Kontak {
|
|||||||
email: string;
|
email: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
interface Lokasi {
|
interface Lokasi {
|
||||||
mapsEmbed: string;
|
mapsEmbed: string;
|
||||||
}
|
}
|
||||||
@@ -35,7 +34,7 @@ function Page() {
|
|||||||
state.findUnique.load(params?.id as string);
|
state.findUnique.load(params?.id as string);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const data = state.findUnique.data as any; // Temporary any to fix type issues
|
const data = state.findUnique.data as any;
|
||||||
|
|
||||||
const nama = data?.name || 'Fasilitas Kesehatan';
|
const nama = data?.name || 'Fasilitas Kesehatan';
|
||||||
const prosedur = data?.prosedurpendaftaran.content || '';
|
const prosedur = data?.prosedurpendaftaran.content || '';
|
||||||
@@ -111,11 +110,11 @@ function Page() {
|
|||||||
<Group gap="md" wrap="wrap">
|
<Group gap="md" wrap="wrap">
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<ThemeIcon variant="light" radius="xl"><IconMapPin size={18} /></ThemeIcon>
|
<ThemeIcon variant="light" radius="xl"><IconMapPin size={18} /></ThemeIcon>
|
||||||
<Text>{alamat}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>{alamat}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<ThemeIcon variant="light" radius="xl"><IconDeviceLandlinePhone size={18} /></ThemeIcon>
|
<ThemeIcon variant="light" radius="xl"><IconDeviceLandlinePhone size={18} /></ThemeIcon>
|
||||||
<Text>{kontak.telepon}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>{kontak.telepon}</Text>
|
||||||
<CopyButton value={kontak.telepon}>
|
<CopyButton value={kontak.telepon}>
|
||||||
{({ copied, copy }) => (
|
{({ copied, copy }) => (
|
||||||
<Tooltip label={copied ? 'Disalin' : 'Salin nomor'}>
|
<Tooltip label={copied ? 'Disalin' : 'Salin nomor'}>
|
||||||
@@ -126,7 +125,7 @@ function Page() {
|
|||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<ThemeIcon variant="light" radius="xl"><IconBrandWhatsapp size={18} /></ThemeIcon>
|
<ThemeIcon variant="light" radius="xl"><IconBrandWhatsapp size={18} /></ThemeIcon>
|
||||||
<Text>{kontak.whatsapp}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>{kontak.whatsapp}</Text>
|
||||||
<CopyButton value={kontak.whatsapp}>
|
<CopyButton value={kontak.whatsapp}>
|
||||||
{({ copied, copy }) => (
|
{({ copied, copy }) => (
|
||||||
<Tooltip label={copied ? 'Disalin' : 'Salin WhatsApp'}>
|
<Tooltip label={copied ? 'Disalin' : 'Salin WhatsApp'}>
|
||||||
@@ -137,7 +136,7 @@ function Page() {
|
|||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<ThemeIcon variant="light" radius="xl"><IconMail size={18} /></ThemeIcon>
|
<ThemeIcon variant="light" radius="xl"><IconMail size={18} /></ThemeIcon>
|
||||||
<Text>{kontak.email}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} lh={1.5}>{kontak.email}</Text>
|
||||||
<CopyButton value={kontak.email}>
|
<CopyButton value={kontak.email}>
|
||||||
{({ copied, copy }) => (
|
{({ copied, copy }) => (
|
||||||
<Tooltip label={copied ? 'Disalin' : 'Salin email'}>
|
<Tooltip label={copied ? 'Disalin' : 'Salin email'}>
|
||||||
@@ -163,33 +162,43 @@ function Page() {
|
|||||||
<Divider />
|
<Divider />
|
||||||
<Group gap="xl" align="start">
|
<Group gap="xl" align="start">
|
||||||
<Stack gap={2}>
|
<Stack gap={2}>
|
||||||
<Text c="dimmed" fz="sm">Nama Fasilitas</Text>
|
<Text c="dimmed" fz={{ base: 'xs', md: 'sm' }}>Nama Fasilitas</Text>
|
||||||
<Text fw={600}>{nama}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} fw={600} lh={1.5}>{nama}</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Stack gap={2}>
|
<Stack gap={2}>
|
||||||
<Text c="dimmed" fz="sm">Jam Operasional</Text>
|
<Text c="dimmed" fz={{ base: 'xs', md: 'sm' }}>Jam Operasional</Text>
|
||||||
<Text fw={600}>{jam}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} fw={600} lh={1.5}>{jam}</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Group>
|
</Group>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Title order={4}>Layanan Unggulan</Title>
|
<Title order={4}>Layanan Unggulan</Title>
|
||||||
<Divider />
|
<Divider />
|
||||||
{layananUnggulan ? (
|
{layananUnggulan ? (
|
||||||
<Box pl={"lg"}>
|
<Box pl="lg">
|
||||||
<Text fz="md" style={{ lineHeight: 1.7, wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: layananUnggulan }} />
|
<Text
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
lh={{ base: 1.6, md: 1.7 }}
|
||||||
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: layananUnggulan }}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Paper withBorder radius="md" p="md">
|
<Paper withBorder radius="md" p="md">
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<IconMoodEmpty />
|
<IconMoodEmpty />
|
||||||
<Text>Belum ada informasi fasilitas pendukung.</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} c="dimmed">Belum ada informasi layanan unggulan.</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Paper>
|
</Paper>
|
||||||
)}
|
)}
|
||||||
<Divider />
|
<Divider />
|
||||||
<Title order={4}>Peta Lokasi</Title>
|
<Title order={4}>Peta Lokasi</Title>
|
||||||
<AspectRatio ratio={16 / 9}>
|
<AspectRatio ratio={16 / 9}>
|
||||||
<iframe src={lokasi.mapsEmbed} style={{ border: 0, width: '100%', height: '100%', borderRadius: 16 }} loading="lazy" aria-label="Peta Lokasi" />
|
<iframe
|
||||||
|
src={lokasi.mapsEmbed}
|
||||||
|
style={{ border: 0, width: '100%', height: '100%', borderRadius: 16 }}
|
||||||
|
loading="lazy"
|
||||||
|
aria-label="Peta Lokasi"
|
||||||
|
/>
|
||||||
</AspectRatio>
|
</AspectRatio>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -201,9 +210,15 @@ function Page() {
|
|||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<Title order={4}>Kontak Cepat</Title>
|
<Title order={4}>Kontak Cepat</Title>
|
||||||
<Group gap="sm" wrap="wrap">
|
<Group gap="sm" wrap="wrap">
|
||||||
<Button variant="light" leftSection={<IconDeviceLandlinePhone size={18} />} component="a" href={`tel:${kontak.telepon}`} aria-label="Hubungi Telepon">Telepon</Button>
|
<Button variant="light" leftSection={<IconDeviceLandlinePhone size={18} />} component="a" href={`tel:${kontak.telepon}`} aria-label="Hubungi Telepon">
|
||||||
<Button variant="light" leftSection={<IconBrandWhatsapp size={18} />} component="a" href={`https://wa.me/${kontak.whatsapp.replace(/\D/g, '')}`} target="_blank" aria-label="Hubungi WhatsApp">WhatsApp</Button>
|
<Text fz={{ base: 'xs', md: 'sm' }}>Telepon</Text>
|
||||||
<Button variant="light" leftSection={<IconMail size={18} />} component="a" href={`mailto:${kontak.email}`} aria-label="Kirim Email">Email</Button>
|
</Button>
|
||||||
|
<Button variant="light" leftSection={<IconBrandWhatsapp size={18} />} component="a" href={`https://wa.me/${kontak.whatsapp.replace(/\D/g, '')}`} target="_blank" aria-label="Hubungi WhatsApp">
|
||||||
|
<Text fz={{ base: 'xs', md: 'sm' }}>WhatsApp</Text>
|
||||||
|
</Button>
|
||||||
|
<Button variant="light" leftSection={<IconMail size={18} />} component="a" href={`mailto:${kontak.email}`} aria-label="Kirim Email">
|
||||||
|
<Text fz={{ base: 'xs', md: 'sm' }}>Email</Text>
|
||||||
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Card>
|
</Card>
|
||||||
@@ -214,9 +229,15 @@ function Page() {
|
|||||||
<Table highlightOnHover withTableBorder withColumnBorders aria-label="Tabel Dokter">
|
<Table highlightOnHover withTableBorder withColumnBorders aria-label="Tabel Dokter">
|
||||||
<TableThead>
|
<TableThead>
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTh>Nama</TableTh>
|
<TableTh>
|
||||||
<TableTh>Spesialisasi</TableTh>
|
<Text fz={{ base: 'xs', md: 'sm' }} fw={600}>Nama</Text>
|
||||||
<TableTh>Jadwal</TableTh>
|
</TableTh>
|
||||||
|
<TableTh>
|
||||||
|
<Text fz={{ base: 'xs', md: 'sm' }} fw={600}>Spesialisasi</Text>
|
||||||
|
</TableTh>
|
||||||
|
<TableTh>
|
||||||
|
<Text fz={{ base: 'xs', md: 'sm' }} fw={600}>Jadwal</Text>
|
||||||
|
</TableTh>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
</TableThead>
|
</TableThead>
|
||||||
<TableTbody>
|
<TableTbody>
|
||||||
@@ -226,11 +247,15 @@ function Page() {
|
|||||||
<TableTd>
|
<TableTd>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconUser size={16} />
|
<IconUser size={16} />
|
||||||
<Text>{dokter.name || '-'}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }}>{dokter.name || '-'}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
<TableTd>{dokter.specialist || '-'}</TableTd>
|
<TableTd>
|
||||||
<TableTd>{dokter.jadwal || '-'}</TableTd>
|
<Text fz={{ base: 'sm', md: 'md' }}>{dokter.specialist || '-'}</Text>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Text fz={{ base: 'sm', md: 'md' }}>{dokter.jadwal || '-'}</Text>
|
||||||
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
@@ -238,7 +263,7 @@ function Page() {
|
|||||||
<TableTd colSpan={3}>
|
<TableTd colSpan={3}>
|
||||||
<Group justify="center" gap="xs" c="dimmed">
|
<Group justify="center" gap="xs" c="dimmed">
|
||||||
<IconSearch size={18} />
|
<IconSearch size={18} />
|
||||||
<Text>Tidak ada data tenaga medis.</Text>
|
<Text fz={{ base: 'sm', md: 'md' }}>Tidak ada data tenaga medis.</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
@@ -254,13 +279,18 @@ function Page() {
|
|||||||
<Divider />
|
<Divider />
|
||||||
{fasilitasPendukungHtml ? (
|
{fasilitasPendukungHtml ? (
|
||||||
<Box pl="lg">
|
<Box pl="lg">
|
||||||
<Text fz="md" style={{ wordBreak: "break-word", whiteSpace: "normal", lineHeight: 1.7 }} dangerouslySetInnerHTML={{ __html: fasilitasPendukungHtml }} />
|
<Text
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
lh={{ base: 1.6, md: 1.7 }}
|
||||||
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: fasilitasPendukungHtml }}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Paper withBorder radius="md" p="md">
|
<Paper withBorder radius="md" p="md">
|
||||||
<Group gap="sm">
|
<Group gap="sm">
|
||||||
<IconMoodEmpty />
|
<IconMoodEmpty />
|
||||||
<Text>Belum ada informasi fasilitas pendukung.</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} c="dimmed">Belum ada informasi fasilitas pendukung.</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Paper>
|
</Paper>
|
||||||
)}
|
)}
|
||||||
@@ -274,16 +304,24 @@ function Page() {
|
|||||||
<Table highlightOnHover withTableBorder withColumnBorders aria-label="Tabel Layanan dan Tarif">
|
<Table highlightOnHover withTableBorder withColumnBorders aria-label="Tabel Layanan dan Tarif">
|
||||||
<TableThead>
|
<TableThead>
|
||||||
<TableTr>
|
<TableTr>
|
||||||
<TableTh>Layanan</TableTh>
|
<TableTh>
|
||||||
<TableTh>Tarif</TableTh>
|
<Text fz={{ base: 'xs', md: 'sm' }} fw={600}>Layanan</Text>
|
||||||
|
</TableTh>
|
||||||
|
<TableTh>
|
||||||
|
<Text fz={{ base: 'xs', md: 'sm' }} fw={600}>Tarif</Text>
|
||||||
|
</TableTh>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
</TableThead>
|
</TableThead>
|
||||||
<TableTbody>
|
<TableTbody>
|
||||||
{Array.isArray(data?.tarifdanlayanan) && data.tarifdanlayanan.length > 0 ? (
|
{Array.isArray(data?.tarifdanlayanan) && data.tarifdanlayanan.length > 0 ? (
|
||||||
data.tarifdanlayanan.map((item: any) => (
|
data.tarifdanlayanan.map((item: any) => (
|
||||||
<TableTr key={item.id}>
|
<TableTr key={item.id}>
|
||||||
<TableTd>{item.layanan || '-'}</TableTd>
|
<TableTd>
|
||||||
<TableTd>{formatRupiah(item.tarif)}</TableTd>
|
<Text fz={{ base: 'sm', md: 'md' }}>{item.layanan || '-'}</Text>
|
||||||
|
</TableTd>
|
||||||
|
<TableTd>
|
||||||
|
<Text fz={{ base: 'sm', md: 'md' }}>{formatRupiah(item.tarif)}</Text>
|
||||||
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
))
|
))
|
||||||
) : (
|
) : (
|
||||||
@@ -291,7 +329,7 @@ function Page() {
|
|||||||
<TableTd colSpan={2}>
|
<TableTd colSpan={2}>
|
||||||
<Group justify="center" gap="xs" c="dimmed">
|
<Group justify="center" gap="xs" c="dimmed">
|
||||||
<IconSearch size={18} />
|
<IconSearch size={18} />
|
||||||
<Text>Tidak ada data tarif.</Text>
|
<Text fz={{ base: 'sm', md: 'md' }}>Tidak ada data tarif.</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</TableTd>
|
</TableTd>
|
||||||
</TableTr>
|
</TableTr>
|
||||||
@@ -301,7 +339,7 @@ function Page() {
|
|||||||
{gratisBpjs && (
|
{gratisBpjs && (
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<ThemeIcon variant="light" radius="xl"><IconCheck size={18} /></ThemeIcon>
|
<ThemeIcon variant="light" radius="xl"><IconCheck size={18} /></ThemeIcon>
|
||||||
<Text fw={600}>Gratis dengan BPJS Kesehatan</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} fw={600}>Gratis dengan BPJS Kesehatan</Text>
|
||||||
</Group>
|
</Group>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -317,9 +355,16 @@ function Page() {
|
|||||||
<Title order={3}>Prosedur Pendaftaran</Title>
|
<Title order={3}>Prosedur Pendaftaran</Title>
|
||||||
<Divider />
|
<Divider />
|
||||||
{prosedur ? (
|
{prosedur ? (
|
||||||
<Box pl="lg"><Text fz="md" style={{ wordBreak: "break-word", whiteSpace: "normal", lineHeight: 1.7 }} dangerouslySetInnerHTML={{ __html: prosedur }} /></Box>
|
<Box pl="lg">
|
||||||
|
<Text
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
lh={{ base: 1.6, md: 1.7 }}
|
||||||
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: prosedur }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
) : (
|
) : (
|
||||||
<Text fz="md" c="dimmed">Belum ada prosedur pendaftaran</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} c="dimmed">Belum ada prosedur pendaftaran</Text>
|
||||||
)}
|
)}
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -328,4 +373,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -40,7 +40,11 @@ function FasilitasKesehatanPage() {
|
|||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
{state.findMany.data.length === 0 ? (
|
{state.findMany.data.length === 0 ? (
|
||||||
<Box py="xl" ta="center">
|
<Box py="xl" ta="center">
|
||||||
<Text size="lg" c="dimmed" lh="1.5">
|
<Text
|
||||||
|
fz={{ base: 'sm', sm: 'md' }}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
lh={{ base: '1.5', sm: '1.6' }}
|
||||||
|
>
|
||||||
Belum ada fasilitas kesehatan yang tersedia
|
Belum ada fasilitas kesehatan yang tersedia
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -67,20 +71,36 @@ function FasilitasKesehatanPage() {
|
|||||||
>
|
>
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Group justify="space-between" align="center">
|
<Group justify="space-between" align="center">
|
||||||
<Title order={3} fw={700} c={colors['blue-button']} lh="1.3" />
|
<Title
|
||||||
|
order={3}
|
||||||
|
fw={700}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
fz={{ base: 'sm', sm: 'md' }}
|
||||||
|
lh={{ base: '1.3', sm: '1.3' }}
|
||||||
|
>
|
||||||
|
{item.name}
|
||||||
|
</Title>
|
||||||
<Badge color="blue" radius="sm" variant="light" size="xs">
|
<Badge color="blue" radius="sm" variant="light" size="xs">
|
||||||
Aktif
|
Aktif
|
||||||
</Badge>
|
</Badge>
|
||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconMapPin size={18} stroke={1.5} />
|
<IconMapPin size={18} stroke={1.5} />
|
||||||
<Text size="sm" lh="1.5">
|
<Text
|
||||||
|
fz={{ base: 'xs', sm: 'sm' }}
|
||||||
|
lh={{ base: '1.5', sm: '1.5' }}
|
||||||
|
c="text"
|
||||||
|
>
|
||||||
{item.informasiumum.alamat}
|
{item.informasiumum.alamat}
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconClock size={18} stroke={1.5} />
|
<IconClock size={18} stroke={1.5} />
|
||||||
<Text size="sm" lh="1.5">
|
<Text
|
||||||
|
fz={{ base: 'xs', sm: 'sm' }}
|
||||||
|
lh={{ base: '1.5', sm: '1.5' }}
|
||||||
|
c="text"
|
||||||
|
>
|
||||||
{item.informasiumum.jamOperasional}
|
{item.informasiumum.jamOperasional}
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ import {
|
|||||||
Paper,
|
Paper,
|
||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text
|
Text,
|
||||||
|
Title
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useDisclosure, useShallowEffect } from '@mantine/hooks';
|
import { useDisclosure, useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconMail, IconPhone, IconUser } from '@tabler/icons-react';
|
import { IconMail, IconPhone, IconUser } from '@tabler/icons-react';
|
||||||
@@ -51,55 +52,97 @@ function Page() {
|
|||||||
style={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }}
|
style={{ borderTopLeftRadius: 16, borderTopRightRadius: 16 }}
|
||||||
bg={colors['blue-button']}
|
bg={colors['blue-button']}
|
||||||
>
|
>
|
||||||
<Text p="md" fz={{ base: "h3", md: "h2" }} c={colors['white-1']} fw="bold">
|
<Title
|
||||||
|
p="md"
|
||||||
|
order={1}
|
||||||
|
c={colors['white-1']}
|
||||||
|
fw="bold"
|
||||||
|
ta={{ base: 'center', md: 'left' }}
|
||||||
|
>
|
||||||
Detail & Pendaftaran Kegiatan
|
Detail & Pendaftaran Kegiatan
|
||||||
</Text>
|
</Title>
|
||||||
</Box>
|
</Box>
|
||||||
<Box p="lg">
|
<Box p="lg">
|
||||||
<Stack gap="xl">
|
<Stack gap="xl">
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Text fz="lg" fw="bold">Informasi Kegiatan</Text>
|
<Title order={2} fw="bold">Informasi Kegiatan</Title>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Text fz="md" fw="bold">Nama Kegiatan: <Text span>{state.findUnique.data.informasijadwalkegiatan.name}</Text></Text>
|
<Text fw="bold">
|
||||||
<Text fz="md" fw="bold">Tanggal: <Text span>{state.findUnique.data.informasijadwalkegiatan.tanggal}</Text></Text>
|
Nama Kegiatan:
|
||||||
<Text fz="md" fw="bold">Waktu: <Text span>{state.findUnique.data.informasijadwalkegiatan.waktu}</Text></Text>
|
<Text span fw="normal">
|
||||||
<Text fz="md" fw="bold">Lokasi: <Text span>{state.findUnique.data.informasijadwalkegiatan.lokasi}</Text></Text>
|
{state.findUnique.data.informasijadwalkegiatan.name}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
<Text fw="bold">
|
||||||
|
Tanggal:
|
||||||
|
<Text span fw="normal">
|
||||||
|
{state.findUnique.data.informasijadwalkegiatan.tanggal}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
<Text fw="bold">
|
||||||
|
Waktu:
|
||||||
|
<Text span fw="normal">
|
||||||
|
{state.findUnique.data.informasijadwalkegiatan.waktu}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
|
<Text fw="bold">
|
||||||
|
Lokasi:
|
||||||
|
<Text span fw="normal">
|
||||||
|
{state.findUnique.data.informasijadwalkegiatan.lokasi}
|
||||||
|
</Text>
|
||||||
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Text fz="lg" fw="bold">Deskripsi Kegiatan</Text>
|
<Title order={2} fw="bold">Deskripsi Kegiatan</Title>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text ta="justify" fz="md" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsijadwalkegiatan.deskripsi }} />
|
<Text
|
||||||
|
ta="justify"
|
||||||
|
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsijadwalkegiatan.deskripsi }}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Text fz="lg" fw="bold">Layanan yang Tersedia</Text>
|
<Title order={2} fw="bold">Layanan yang Tersedia</Title>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text ta="justify" fz="md" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.layananjadwalkegiatan.content }} />
|
<Text
|
||||||
|
ta="justify"
|
||||||
|
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: state.findUnique.data.layananjadwalkegiatan.content }}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Text fz="lg" fw="bold">Syarat & Ketentuan</Text>
|
<Title order={2} fw="bold">Syarat & Ketentuan</Title>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text ta="justify" fz="md" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.syaratketentuanjadwalkegiatan.content }} />
|
<Text
|
||||||
|
ta="justify"
|
||||||
|
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: state.findUnique.data.syaratketentuanjadwalkegiatan.content }}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Text fz="lg" fw="bold">Dokumen yang Perlu Dibawa</Text>
|
<Title order={2} fw="bold">Dokumen yang Perlu Dibawa</Title>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text ta="justify" fz="md" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: state.findUnique.data.dokumenjadwalkegiatan.content }} />
|
<Text
|
||||||
|
ta="justify"
|
||||||
|
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: state.findUnique.data.dokumenjadwalkegiatan.content }}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Text fz="lg" fw="bold">Pendaftaran Kegiatan</Text>
|
<Title order={2} fw="bold">Pendaftaran Kegiatan</Title>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Group>
|
<Group>
|
||||||
<Button onClick={open}>Buat Pendaftaran</Button>
|
<Button onClick={open}>Buat Pendaftaran</Button>
|
||||||
@@ -112,18 +155,21 @@ function Page() {
|
|||||||
|
|
||||||
<Paper p="lg" radius="md" bg={colors['blue-button-trans']} shadow="sm">
|
<Paper p="lg" radius="md" bg={colors['blue-button-trans']} shadow="sm">
|
||||||
<Stack gap="xs">
|
<Stack gap="xs">
|
||||||
<Text fz="lg" c={colors['white-1']} fw="bold">Informasi Kontak</Text>
|
<Title order={3} c={colors['white-1']} fw="bold">Informasi Kontak</Title>
|
||||||
<Group gap="xs">
|
<Group gap="xs" justify="flex-start">
|
||||||
<IconUser size={18} color="white" />
|
<IconUser size={18} color="white" />
|
||||||
<Text fz="md" c={colors['white-1']}>Penanggung Jawab: <Text span fw="bold">Bidan Komang Ayu</Text></Text>
|
<Text c={colors['white-1']}>
|
||||||
|
Penanggung Jawab:
|
||||||
|
<Text span fw="bold">Bidan Komang Ayu</Text>
|
||||||
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconPhone size={18} color="white" />
|
<IconPhone size={18} color="white" />
|
||||||
<Text fz="md" c={colors['white-1']}>081234567890</Text>
|
<Text c={colors['white-1']}>081234567890</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconMail size={18} color="white" />
|
<IconMail size={18} color="white" />
|
||||||
<Text fz="md" c={colors['white-1']}>puskesmasabiansemal3@gmail.com</Text>
|
<Text c={colors['white-1']}>puskesmasabiansemal3@gmail.com</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -136,4 +182,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -2,15 +2,14 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import pendaftaranJadwalKegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/pendafataranJadwalKegiatan';
|
import pendaftaranJadwalKegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/pendafataranJadwalKegiatan';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Button, Divider, Stack, Text, Textarea, TextInput } from '@mantine/core';
|
import { Button, Divider, Stack, Text, Textarea, TextInput, Title } from '@mantine/core';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
|
|
||||||
function CreatePendaftaran() {
|
function CreatePendaftaran() {
|
||||||
const stateCreate = useProxy(pendaftaranJadwalKegiatanState);
|
const stateCreate = useProxy(pendaftaranJadwalKegiatanState);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
useEffect(() => {
|
|
||||||
stateCreate.findMany.load();
|
stateCreate.findMany.load();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
@@ -32,15 +31,19 @@ useEffect(() => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Text fz="lg" fw="bold">Formulir Pendaftaran</Text>
|
<Title order={2} ta="left">Formulir Pendaftaran</Title>
|
||||||
<Divider />
|
<Divider />
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Nama Balita"
|
label="Nama Balita"
|
||||||
placeholder="Masukkan nama balita"
|
placeholder="Masukkan nama balita"
|
||||||
size="md"
|
size="md"
|
||||||
value={stateCreate.create.form.name}
|
value={stateCreate.create.form.name}
|
||||||
onChange={(e) => stateCreate.create.form.name = e.target.value}
|
onChange={(e) => stateCreate.create.form.name = e.target.value}
|
||||||
|
styles={{
|
||||||
|
label: { fontSize: '14px', lineHeight: 1.4, fontWeight: 500 },
|
||||||
|
input: { fontSize: '16px', lineHeight: 1.5 },
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
type='date'
|
type='date'
|
||||||
@@ -50,41 +53,63 @@ useEffect(() => {
|
|||||||
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
w={{ base: '100%', md: '85%', lg: '75%', xl: '50%' }}
|
||||||
value={stateCreate.create.form.tanggal}
|
value={stateCreate.create.form.tanggal}
|
||||||
onChange={(e) => stateCreate.create.form.tanggal = e.target.value}
|
onChange={(e) => stateCreate.create.form.tanggal = e.target.value}
|
||||||
|
styles={{
|
||||||
|
label: { fontSize: '14px', lineHeight: 1.4, fontWeight: 500 },
|
||||||
|
input: { fontSize: '16px', lineHeight: 1.5 },
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Nama Orang Tua / Wali"
|
label="Nama Orang Tua / Wali"
|
||||||
placeholder="Masukkan nama orang tua / wali"
|
placeholder="Masukkan nama orang tua / wali"
|
||||||
size="md"
|
size="md"
|
||||||
value={stateCreate.create.form.namaOrangtua}
|
value={stateCreate.create.form.namaOrangtua}
|
||||||
onChange={(e) => stateCreate.create.form.namaOrangtua = e.target.value}
|
onChange={(e) => stateCreate.create.form.namaOrangtua = e.target.value}
|
||||||
|
styles={{
|
||||||
|
label: { fontSize: '14px', lineHeight: 1.4, fontWeight: 500 },
|
||||||
|
input: { fontSize: '16px', lineHeight: 1.5 },
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Nomor Telepon"
|
label="Nomor Telepon"
|
||||||
placeholder="Masukkan nomor telepon"
|
placeholder="Masukkan nomor telepon"
|
||||||
size="md"
|
size="md"
|
||||||
value={stateCreate.create.form.nomor}
|
value={stateCreate.create.form.nomor}
|
||||||
onChange={(e) => stateCreate.create.form.nomor = e.target.value}
|
onChange={(e) => stateCreate.create.form.nomor = e.target.value}
|
||||||
|
styles={{
|
||||||
|
label: { fontSize: '14px', lineHeight: 1.4, fontWeight: 500 },
|
||||||
|
input: { fontSize: '16px', lineHeight: 1.5 },
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Alamat"
|
label="Alamat"
|
||||||
placeholder="Masukkan alamat lengkap"
|
placeholder="Masukkan alamat lengkap"
|
||||||
size="md"
|
size="md"
|
||||||
value={stateCreate.create.form.alamat}
|
value={stateCreate.create.form.alamat}
|
||||||
onChange={(e) => stateCreate.create.form.alamat = e.target.value}
|
onChange={(e) => stateCreate.create.form.alamat = e.target.value}
|
||||||
|
styles={{
|
||||||
|
label: { fontSize: '14px', lineHeight: 1.4, fontWeight: 500 },
|
||||||
|
input: { fontSize: '16px', lineHeight: 1.5 },
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<Textarea
|
<Textarea
|
||||||
label="Catatan Khusus (Opsional)"
|
label="Catatan Khusus (Opsional)"
|
||||||
placeholder="Masukkan catatan jika ada"
|
placeholder="Masukkan catatan jika ada"
|
||||||
size="md"
|
size="md"
|
||||||
value={stateCreate.create.form.catatan}
|
value={stateCreate.create.form.catatan}
|
||||||
onChange={(e) => stateCreate.create.form.catatan = e.target.value}
|
onChange={(e) => stateCreate.create.form.catatan = e.target.value}
|
||||||
|
styles={{
|
||||||
|
label: { fontSize: '14px', lineHeight: 1.4, fontWeight: 500 },
|
||||||
|
input: { fontSize: '16px', lineHeight: 1.5 },
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
<Button size="md" radius="lg" bg={colors['blue-button']} onClick={handleSubmit}>
|
<Button size="md" radius="lg" bg={colors['blue-button']} onClick={handleSubmit}>
|
||||||
Daftar Sekarang
|
<Text fz={{ base: 'sm', md: 'md' }} fw={600} c="white">
|
||||||
|
Daftar Sekarang
|
||||||
|
</Text>
|
||||||
</Button>
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default CreatePendaftaran;
|
export default CreatePendaftaran;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import jadwalkegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
|
import jadwalkegiatanState from '@/app/admin/(dashboard)/_state/kesehatan/data_kesehatan_warga/jadwalKegiatan';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Button, Card, Divider, Group, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Button, Card, Divider, Group, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconChevronRight, IconClockHour4, IconMapPin } from '@tabler/icons-react';
|
import { IconChevronRight, IconClockHour4, IconMapPin } from '@tabler/icons-react';
|
||||||
import { useRouter } from 'next/navigation';
|
import { useRouter } from 'next/navigation';
|
||||||
@@ -27,13 +27,13 @@ function JadwalKegiatanPage() {
|
|||||||
<Box>
|
<Box>
|
||||||
<Paper bg={colors['white-trans-1']} p="xl" radius="xl" shadow="md" h="auto" mih="100vh">
|
<Paper bg={colors['white-trans-1']} p="xl" radius="xl" shadow="md" h="auto" mih="100vh">
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<Text ta="center" fw={700} fz="32px" c={colors['blue-button']}>
|
<Title ta="center" order={1} c={colors['blue-button']} fw={700}>
|
||||||
Jadwal Kegiatan Warga
|
Jadwal Kegiatan Warga
|
||||||
</Text>
|
</Title>
|
||||||
<Divider size="sm" color={colors['blue-button']} />
|
<Divider size="sm" color={colors['blue-button']} />
|
||||||
{state.findMany.data.length === 0 ? (
|
{state.findMany.data.length === 0 ? (
|
||||||
<Box py="xl" ta="center">
|
<Box py="xl" ta="center">
|
||||||
<Text fz="lg" c="dimmed">
|
<Text fz={{ base: 'sm', sm: 'md' }} c="dimmed">
|
||||||
Belum ada jadwal kegiatan yang tersedia
|
Belum ada jadwal kegiatan yang tersedia
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -48,11 +48,11 @@ function JadwalKegiatanPage() {
|
|||||||
style={{ backdropFilter: 'blur(8px)' }}
|
style={{ backdropFilter: 'blur(8px)' }}
|
||||||
>
|
>
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Group justify="space-between">
|
<Group justify="space-between" wrap="nowrap">
|
||||||
<Text fw={700} fz="xl" c={colors['blue-button']}>
|
<Title order={2} c={colors['blue-button']} fw={700} fz={{ base: 'md', sm: 'xl' }}>
|
||||||
{item.informasijadwalkegiatan.name}
|
{item.informasijadwalkegiatan.name}
|
||||||
</Text>
|
</Title>
|
||||||
<Text fw={600} fz="sm" c={colors['blue-button']}>
|
<Text fw={600} fz={{ base: 'xs', sm: 'sm' }} c={colors['blue-button']} lh="1.4">
|
||||||
{new Date(item.informasijadwalkegiatan.tanggal).toLocaleDateString('id-ID', {
|
{new Date(item.informasijadwalkegiatan.tanggal).toLocaleDateString('id-ID', {
|
||||||
day: '2-digit',
|
day: '2-digit',
|
||||||
month: 'long',
|
month: 'long',
|
||||||
@@ -63,12 +63,16 @@ function JadwalKegiatanPage() {
|
|||||||
|
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconClockHour4 size={18} />
|
<IconClockHour4 size={18} />
|
||||||
<Text fz="sm">{item.informasijadwalkegiatan.waktu}</Text>
|
<Text fz={{ base: 'xs', sm: 'sm' }} lh="1.5">
|
||||||
|
{item.informasijadwalkegiatan.waktu}
|
||||||
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconMapPin size={18} />
|
<IconMapPin size={18} />
|
||||||
<Text fz="sm">{item.informasijadwalkegiatan.lokasi}</Text>
|
<Text fz={{ base: 'xs', sm: 'sm' }} lh="1.5">
|
||||||
|
{item.informasijadwalkegiatan.lokasi}
|
||||||
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Divider my="sm" />
|
<Divider my="sm" />
|
||||||
@@ -98,4 +102,4 @@ function JadwalKegiatanPage() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default JadwalKegiatanPage;
|
export default JadwalKegiatanPage;
|
||||||
@@ -74,22 +74,22 @@ function DetailInfoWabahPenyakitUser() {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Deskripsi */}
|
{/* Deskripsi */}
|
||||||
<Box>
|
<Stack gap={"xs"}>
|
||||||
{/* Section Title — H2 */}
|
{/* Section Title — H2 */}
|
||||||
<Title order={2} fw="bold" fz={{ base: 'md', md: 'lg' }} lh="1.4">
|
<Title order={3} fw="bold" ta="left">
|
||||||
Deskripsi
|
Deskripsi
|
||||||
</Title>
|
</Title>
|
||||||
<Box pl={20}>
|
<Box pl={20}>
|
||||||
<Text
|
<Text
|
||||||
fz={{ base: 'sm', md: 'md' }}
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
lh="1.6"
|
lh={{ base: '1.5', md: '1.6' }}
|
||||||
c="dimmed"
|
c="dark"
|
||||||
ta={"justify"}
|
ta="justify"
|
||||||
dangerouslySetInnerHTML={{ __html: data.deskripsiLengkap || '-' }}
|
dangerouslySetInnerHTML={{ __html: data.deskripsiLengkap || '-' }}
|
||||||
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ import {
|
|||||||
Skeleton,
|
Skeleton,
|
||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput
|
TextInput,
|
||||||
|
Title
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconInfoCircle, IconSearch } from '@tabler/icons-react';
|
import { IconInfoCircle, IconSearch } from '@tabler/icons-react';
|
||||||
@@ -30,7 +31,7 @@ function Page() {
|
|||||||
const state = useProxy(infoWabahPenyakit);
|
const state = useProxy(infoWabahPenyakit);
|
||||||
const router = useTransitionRouter();
|
const router = useTransitionRouter();
|
||||||
const [search, setSearch] = useState('');
|
const [search, setSearch] = useState('');
|
||||||
const [debouncedSearch] = useDebouncedValue(search, 1000)
|
const [debouncedSearch] = useDebouncedValue(search, 1000);
|
||||||
const { data, page, totalPages, loading, load } = state.findMany;
|
const { data, page, totalPages, loading, load } = state.findMany;
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
@@ -53,15 +54,19 @@ function Page() {
|
|||||||
|
|
||||||
<Grid align="center" px={{ base: 'md', md: 100 }}>
|
<Grid align="center" px={{ base: 'md', md: 100 }}>
|
||||||
<GridCol span={{ base: 12, md: 8 }}>
|
<GridCol span={{ base: 12, md: 8 }}>
|
||||||
<Text
|
<Title
|
||||||
fz={{ base: '1.8rem', md: '2.8rem' }}
|
order={1}
|
||||||
c={colors['blue-button']}
|
c={colors['blue-button']}
|
||||||
fw="bold"
|
fw="bold"
|
||||||
lh={1.2}
|
lh={{ base: 1.2, md: 1.2 }}
|
||||||
>
|
>
|
||||||
Informasi Wabah & Penyakit
|
Informasi Wabah & Penyakit
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="md" mt={4}>
|
<Text
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
lh={{ base: 1.5, md: 1.5 }}
|
||||||
|
mt={4}
|
||||||
|
>
|
||||||
Dapatkan informasi terbaru mengenai wabah dan penyakit yang sedang
|
Dapatkan informasi terbaru mengenai wabah dan penyakit yang sedang
|
||||||
diawasi.
|
diawasi.
|
||||||
</Text>
|
</Text>
|
||||||
@@ -84,9 +89,9 @@ function Page() {
|
|||||||
<Center py="6xl">
|
<Center py="6xl">
|
||||||
<Stack align="center" gap="sm">
|
<Stack align="center" gap="sm">
|
||||||
<IconInfoCircle size={50} color={colors['blue-button']} />
|
<IconInfoCircle size={50} color={colors['blue-button']} />
|
||||||
<Text fz="lg" fw={500} >
|
<Title order={2} fz={{ base: 'md', md: 'lg' }} fw={500}>
|
||||||
Tidak ada data yang cocok dengan pencarian Anda.
|
Tidak ada data yang cocok dengan pencarian Anda.
|
||||||
</Text>
|
</Title>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
) : (
|
) : (
|
||||||
@@ -131,15 +136,24 @@ function Page() {
|
|||||||
|
|
||||||
{/* Judul dan badge */}
|
{/* Judul dan badge */}
|
||||||
<Group justify="space-between" mt="sm">
|
<Group justify="space-between" mt="sm">
|
||||||
<Text fw={700} fz="lg" c={colors['blue-button']}>
|
<Title
|
||||||
|
order={3}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
fw={700}
|
||||||
|
fz={{ base: 'sm', md: 'lg' }}
|
||||||
|
>
|
||||||
{v.name}
|
{v.name}
|
||||||
</Text>
|
</Title>
|
||||||
<Badge color="blue" variant="light" radius="sm">
|
<Badge color="blue" variant="light" radius="sm">
|
||||||
Wabah
|
Wabah
|
||||||
</Badge>
|
</Badge>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Text fz="sm" c="dimmed">
|
<Text
|
||||||
|
fz={{ base: 'xs', md: 'sm' }}
|
||||||
|
c="dimmed"
|
||||||
|
lh={{ base: 1.4, md: 1.4 }}
|
||||||
|
>
|
||||||
Diposting:{' '}
|
Diposting:{' '}
|
||||||
{new Date(v.createdAt).toLocaleDateString('id-ID', {
|
{new Date(v.createdAt).toLocaleDateString('id-ID', {
|
||||||
day: '2-digit',
|
day: '2-digit',
|
||||||
@@ -153,8 +167,8 @@ function Page() {
|
|||||||
{/* Bagian deskripsi dan tombol */}
|
{/* Bagian deskripsi dan tombol */}
|
||||||
<Box style={{ display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
|
<Box style={{ display: 'flex', flexDirection: 'column', flexGrow: 1 }}>
|
||||||
<Text
|
<Text
|
||||||
fz="sm"
|
fz={{ base: 'xs', md: 'sm' }}
|
||||||
lh={1.5}
|
lh={{ base: 1.5, md: 1.5 }}
|
||||||
lineClamp={3}
|
lineClamp={3}
|
||||||
dangerouslySetInnerHTML={{ __html: v.deskripsiSingkat }}
|
dangerouslySetInnerHTML={{ __html: v.deskripsiSingkat }}
|
||||||
style={{ flexGrow: 1 }}
|
style={{ flexGrow: 1 }}
|
||||||
@@ -174,14 +188,11 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
|
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
<Center>
|
<Center>
|
||||||
<Pagination
|
<Pagination
|
||||||
value={page}
|
value={page}
|
||||||
@@ -192,9 +203,8 @@ function Page() {
|
|||||||
mt="lg"
|
mt="lg"
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
|
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import kontakDarurat from '@/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat';
|
import kontakDarurat from '@/app/admin/(dashboard)/_state/kesehatan/kontak-darurat/kontakDarurat';
|
||||||
import colors from '@/con/colors';
|
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, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconArrowBack, IconBrandWhatsapp } from '@tabler/icons-react';
|
import { IconArrowBack, IconBrandWhatsapp } from '@tabler/icons-react';
|
||||||
import { useParams, useRouter } from 'next/navigation';
|
import { useParams, useRouter } from 'next/navigation';
|
||||||
@@ -27,15 +27,16 @@ function Page() {
|
|||||||
const data = state.findUnique.data;
|
const data = state.findUnique.data;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box px={{base: 'md', md: 100}} py={10}>
|
<Box px={{ base: 'md', md: 100 }} py={10}>
|
||||||
{/* Tombol Back */}
|
{/* Tombol Back */}
|
||||||
<Button
|
<Button
|
||||||
variant="subtle"
|
variant="subtle"
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
leftSection={<IconArrowBack size={24} color={colors['blue-button']} />}
|
leftSection={<IconArrowBack size={24} color={colors['blue-button']} />}
|
||||||
mb={15}
|
mb={15}
|
||||||
|
style={{ lineHeight: 1.2 }}
|
||||||
>
|
>
|
||||||
Kembali
|
<Text fz={{ base: 'sm', md: 'md' }} fw={500}>Kembali</Text>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
{/* Wrapper Detail */}
|
{/* Wrapper Detail */}
|
||||||
@@ -48,34 +49,38 @@ function Page() {
|
|||||||
shadow="sm"
|
shadow="sm"
|
||||||
>
|
>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
<Text fz="2xl" fw="bold" c={colors['blue-button']}>
|
<Title order={1} c={colors['blue-button']}>
|
||||||
Detail Kontak Darurat
|
Detail Kontak Darurat
|
||||||
</Text>
|
</Title>
|
||||||
|
|
||||||
<Paper bg="#ECEEF8" p="md" radius="md" shadow="xs">
|
<Paper bg="#ECEEF8" p="md" radius="md" shadow="xs">
|
||||||
<Stack gap="sm">
|
<Stack gap="sm">
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="lg" fw="bold">Judul</Text>
|
<Title order={3}>Judul</Title>
|
||||||
<Text fz="md" c="dimmed">{data.name || '-'}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} c={data.name ? 'black' : 'dimmed'}>
|
||||||
|
{data.name || '-'}
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="lg" fw="bold">Whatsapp</Text>
|
<Title order={3}>Whatsapp</Title>
|
||||||
<Text fz="md" c="dimmed">{data.whatsapp || '-'}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} c={data.whatsapp ? 'black' : 'dimmed'}>
|
||||||
|
{data.whatsapp || '-'}
|
||||||
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="lg" fw="bold">Deskripsi</Text>
|
<Title order={3}>Deskripsi</Title>
|
||||||
<Text
|
<Text
|
||||||
fz="md"
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
c="dimmed"
|
c={data.deskripsi ? 'black' : 'dimmed'}
|
||||||
dangerouslySetInnerHTML={{ __html: data.deskripsi || '-' }}
|
dangerouslySetInnerHTML={{ __html: data.deskripsi || '-' }}
|
||||||
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal', lineHeight: 1.5 }}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box>
|
<Box>
|
||||||
<Text fz="lg" fw="bold">Gambar</Text>
|
<Title order={3}>Gambar</Title>
|
||||||
{data.image?.link ? (
|
{data.image?.link ? (
|
||||||
<Image
|
<Image
|
||||||
src={data.image.link}
|
src={data.image.link}
|
||||||
@@ -85,9 +90,10 @@ function Page() {
|
|||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<Text fz="md" c="dimmed">-</Text>
|
<Text fz={{ base: 'sm', md: 'md' }} c="dimmed">-</Text>
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Group>
|
<Group>
|
||||||
<Button
|
<Button
|
||||||
variant="light"
|
variant="light"
|
||||||
@@ -96,6 +102,7 @@ function Page() {
|
|||||||
href={`https://wa.me/${data.whatsapp.replace(/\D/g, '')}`}
|
href={`https://wa.me/${data.whatsapp.replace(/\D/g, '')}`}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
aria-label="Hubungi WhatsApp"
|
aria-label="Hubungi WhatsApp"
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
>
|
>
|
||||||
WhatsApp
|
WhatsApp
|
||||||
</Button>
|
</Button>
|
||||||
@@ -108,4 +115,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
|
Title,
|
||||||
Tooltip
|
Tooltip
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks';
|
||||||
@@ -52,10 +53,21 @@ function Page() {
|
|||||||
|
|
||||||
<Grid align="center" px={{ base: 'md', md: 100 }} gutter="lg">
|
<Grid align="center" px={{ base: 'md', md: 100 }} gutter="lg">
|
||||||
<GridCol span={{ base: 12, md: 8 }}>
|
<GridCol span={{ base: 12, md: 8 }}>
|
||||||
<Text fz={{ base: '2rem', md: '2.8rem' }} c={colors['blue-button']} fw={800}>
|
<Title
|
||||||
|
order={1}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
fw={800}
|
||||||
|
fz={{ base: '28px', md: '32px' }}
|
||||||
|
lh={{ base: 1.2, md: 1.25 }}
|
||||||
|
>
|
||||||
Kontak Darurat
|
Kontak Darurat
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="md" mt={4}>
|
<Text
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
lh={{ base: 1.5, md: 1.6 }}
|
||||||
|
mt={4}
|
||||||
|
c="dark.9"
|
||||||
|
>
|
||||||
Hubungi layanan penting dengan cepat dan mudah
|
Hubungi layanan penting dengan cepat dan mudah
|
||||||
</Text>
|
</Text>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
@@ -79,10 +91,20 @@ function Page() {
|
|||||||
<Center mih={300}>
|
<Center mih={300}>
|
||||||
<Stack align="center" gap="xs">
|
<Stack align="center" gap="xs">
|
||||||
<IconSearch size={50} color={colors['blue-button']} />
|
<IconSearch size={50} color={colors['blue-button']} />
|
||||||
<Text fz="lg" fw={600} c={colors['blue-button']}>
|
<Title
|
||||||
|
order={2}
|
||||||
|
fw={600}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
fz={{ base: '20px', md: '24px' }}
|
||||||
|
lh={{ base: 1.3, md: 1.35 }}
|
||||||
|
>
|
||||||
Tidak ada kontak ditemukan
|
Tidak ada kontak ditemukan
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="sm" c="dimmed">
|
<Text
|
||||||
|
fz={{ base: 'xs', md: 'sm' }}
|
||||||
|
lh={{ base: 1.4, md: 1.5 }}
|
||||||
|
c="dark.7"
|
||||||
|
>
|
||||||
Coba kata kunci lain untuk pencarian
|
Coba kata kunci lain untuk pencarian
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -102,8 +124,8 @@ function Page() {
|
|||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
justifyContent: 'space-between', // ✅ biar button selalu di bawah
|
justifyContent: 'space-between',
|
||||||
height: '100%', // ✅ bikin tinggi seragam
|
height: '100%',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Stack align="center" gap="sm" style={{ flexGrow: 1 }}>
|
<Stack align="center" gap="sm" style={{ flexGrow: 1 }}>
|
||||||
@@ -131,27 +153,24 @@ function Page() {
|
|||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Text ta="center" fw={700} fz="lg" c={colors['blue-button']}>
|
<Text ta="center" fw={700} fz={{ base: '18px', md: '20px' }} lh={1.3} c={colors['blue-button']}>
|
||||||
{v.name}
|
{v.name}
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Text
|
<Text
|
||||||
fz="sm"
|
fz={{ base: 'xs', md: 'sm' }}
|
||||||
ta="center"
|
ta="center"
|
||||||
lineClamp={3}
|
lineClamp={3}
|
||||||
lh={1.6}
|
lh={{ base: 1.5, md: 1.6 }}
|
||||||
style={{
|
style={{
|
||||||
minHeight: '4.8em', // tinggi tetap 3 baris
|
minHeight: '4.8em',
|
||||||
|
wordBreak: 'break-word',
|
||||||
|
whiteSpace: 'normal',
|
||||||
}}
|
}}
|
||||||
>
|
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
||||||
<span
|
/>
|
||||||
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
|
||||||
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
|
||||||
/>
|
|
||||||
</Text>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
{/* ✅ Tombol selalu di bagian bawah card */}
|
|
||||||
<Group mt="md" justify='center'>
|
<Group mt="md" justify='center'>
|
||||||
<Button
|
<Button
|
||||||
bg={colors['blue-button']}
|
bg={colors['blue-button']}
|
||||||
@@ -161,8 +180,6 @@ function Page() {
|
|||||||
</Button>
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
|
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
)}
|
)}
|
||||||
@@ -186,4 +203,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client';
|
'use client';
|
||||||
import penangananDarurat from '@/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat';
|
import penangananDarurat from '@/app/admin/(dashboard)/_state/kesehatan/penanganan-darurat/penangananDarurat';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Image, Paper, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Center, Image, Paper, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
@@ -31,48 +31,55 @@ function DetailPenangananDaruratUser() {
|
|||||||
<Box py={20}>
|
<Box py={20}>
|
||||||
{/* Tombol Back */}
|
{/* Tombol Back */}
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton/>
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
{/* Wrapper Detail */}
|
{/* Wrapper Detail */}
|
||||||
<Paper
|
<Box pt={20} px={{ base: 'md', md: 100 }}>
|
||||||
withBorder
|
<Paper
|
||||||
w={{ base: '100%', md: '70%', lg: '60%' }}
|
withBorder
|
||||||
mx="auto"
|
w={'100%'}
|
||||||
bg={colors['white-1']}
|
bg={colors['white-1']}
|
||||||
p="xl"
|
p="xl"
|
||||||
radius="lg"
|
radius="lg"
|
||||||
shadow="sm"
|
shadow="sm"
|
||||||
>
|
>
|
||||||
<Stack gap="md" align="center" ta="center">
|
<Stack gap="md">
|
||||||
<Text fz="xl" fw={700} c={colors['blue-button']}>
|
<Title
|
||||||
{data.name || 'Penanganan Darurat'}
|
ta={"center"}
|
||||||
</Text>
|
order={1}
|
||||||
|
fw={700}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
style={{ wordBreak: 'break-word' }}
|
||||||
|
>
|
||||||
|
{data.name || 'Penanganan Darurat'}
|
||||||
|
</Title>
|
||||||
|
<Center>
|
||||||
|
{data.image?.link && (
|
||||||
|
<Image
|
||||||
|
src={data.image.link}
|
||||||
|
alt={data.name}
|
||||||
|
radius="md"
|
||||||
|
mah={300}
|
||||||
|
fit="contain"
|
||||||
|
loading="lazy"
|
||||||
|
mb="md"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</Center>
|
||||||
|
|
||||||
{data.image?.link && (
|
<Box >
|
||||||
<Image
|
<Text
|
||||||
src={data.image.link}
|
ta="justify"
|
||||||
alt={data.name}
|
dangerouslySetInnerHTML={{ __html: data.deskripsi }}
|
||||||
radius="md"
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
mah={300}
|
/>
|
||||||
fit="contain"
|
</Box>
|
||||||
loading="lazy"
|
</Stack>
|
||||||
mb="md"
|
</Paper>
|
||||||
/>
|
</Box>
|
||||||
)}
|
|
||||||
|
|
||||||
<Box>
|
|
||||||
<Text
|
|
||||||
fz="md"
|
|
||||||
ta="justify"
|
|
||||||
dangerouslySetInnerHTML={{ __html: data.deskripsi }}
|
|
||||||
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default DetailPenangananDaruratUser;
|
export default DetailPenangananDaruratUser;
|
||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
|
Title,
|
||||||
Tooltip
|
Tooltip
|
||||||
} from '@mantine/core'
|
} from '@mantine/core'
|
||||||
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks'
|
import { useDebouncedValue, useShallowEffect } from '@mantine/hooks'
|
||||||
@@ -49,10 +50,19 @@ function Page() {
|
|||||||
|
|
||||||
<Grid align="center" px={{ base: 'md', md: 100 }} mb="lg">
|
<Grid align="center" px={{ base: 'md', md: 100 }} mb="lg">
|
||||||
<GridCol span={{ base: 12, md: 9 }}>
|
<GridCol span={{ base: 12, md: 9 }}>
|
||||||
<Text fz={{ base: 30, md: 40 }} c={colors['blue-button']} fw={800} lh={1.2}>
|
<Title
|
||||||
|
order={1}
|
||||||
|
c={colors['blue-button']}
|
||||||
|
fw={800}
|
||||||
|
lh={{ base: 1.3, md: 1.2 }}
|
||||||
|
>
|
||||||
Penanganan Darurat
|
Penanganan Darurat
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="md" mt={4}>
|
<Text
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
mt={4}
|
||||||
|
lh={{ base: 1.5, md: 1.5 }}
|
||||||
|
>
|
||||||
Informasi cepat dan jelas untuk situasi darurat kesehatan
|
Informasi cepat dan jelas untuk situasi darurat kesehatan
|
||||||
</Text>
|
</Text>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
@@ -74,10 +84,10 @@ function Page() {
|
|||||||
{data.length === 0 ? (
|
{data.length === 0 ? (
|
||||||
<Center py={100}>
|
<Center py={100}>
|
||||||
<Stack align="center" gap="xs">
|
<Stack align="center" gap="xs">
|
||||||
<Text fz="lg" fw={600} c={colors['blue-button']}>
|
<Title order={2} fw={600} c={colors['blue-button']}>
|
||||||
Tidak ada data ditemukan
|
Tidak ada data ditemukan
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="sm" c="dimmed">
|
<Text fz={{ base: 'xs', md: 'sm' }}>
|
||||||
Coba gunakan kata kunci lain
|
Coba gunakan kata kunci lain
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -128,18 +138,21 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Stack gap={4} w="100%">
|
<Stack gap={4} w="100%">
|
||||||
<Text
|
<Title
|
||||||
fz="lg"
|
order={3}
|
||||||
fw={700}
|
fw={700}
|
||||||
c={colors['blue-button']}
|
c={colors['blue-button']}
|
||||||
ta="center"
|
ta="center"
|
||||||
lineClamp={2}
|
lineClamp={2}
|
||||||
|
fz={{ base: 'sm', md: 'lg' }}
|
||||||
|
lh={{ base: 1.4, md: 1.4 }}
|
||||||
>
|
>
|
||||||
{v.name}
|
{v.name}
|
||||||
</Text>
|
</Title>
|
||||||
<Box>
|
<Box>
|
||||||
<Text
|
<Text
|
||||||
fz="md"
|
fz={{ base: 'xs', md: 'md' }}
|
||||||
|
lh={{ base: 1.5, md: 1.5 }}
|
||||||
lineClamp={3}
|
lineClamp={3}
|
||||||
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
||||||
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
||||||
@@ -177,12 +190,10 @@ function Page() {
|
|||||||
'&:hover': { backgroundColor: colors['blue-button'], color: 'white' },
|
'&:hover': { backgroundColor: colors['blue-button'], color: 'white' },
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
/>
|
/>
|
||||||
</Center>
|
</Center>
|
||||||
|
|
||||||
</Stack>
|
</Stack>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page
|
export default Page
|
||||||
@@ -88,7 +88,11 @@ export default function DetailPosyanduUser() {
|
|||||||
</Center>
|
</Center>
|
||||||
) : (
|
) : (
|
||||||
<Center>
|
<Center>
|
||||||
<Text fz={{ base: 'xs', md: 'sm' }} c="dimmed">
|
<Text
|
||||||
|
fz={{ base: 'xs', md: 'sm' }}
|
||||||
|
c="dimmed"
|
||||||
|
ta="center"
|
||||||
|
>
|
||||||
Tidak ada gambar
|
Tidak ada gambar
|
||||||
</Text>
|
</Text>
|
||||||
</Center>
|
</Center>
|
||||||
@@ -99,8 +103,8 @@ export default function DetailPosyanduUser() {
|
|||||||
<Flex align="center" gap="xs">
|
<Flex align="center" gap="xs">
|
||||||
<IconPhone size={18} stroke={1.5} />
|
<IconPhone size={18} stroke={1.5} />
|
||||||
<Text
|
<Text
|
||||||
fz={{ base: 'xs', md: 'sm' }}
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
c="dimmed"
|
c="black"
|
||||||
lh={{ base: 1.5, md: 1.6 }}
|
lh={{ base: 1.5, md: 1.6 }}
|
||||||
>
|
>
|
||||||
{data.nomor || 'Nomor tidak tersedia'}
|
{data.nomor || 'Nomor tidak tersedia'}
|
||||||
@@ -110,8 +114,8 @@ export default function DetailPosyanduUser() {
|
|||||||
<Flex align="center" gap="xs">
|
<Flex align="center" gap="xs">
|
||||||
<IconCalendar size={18} stroke={1.5} />
|
<IconCalendar size={18} stroke={1.5} />
|
||||||
<Text
|
<Text
|
||||||
fz={{ base: 'xs', md: 'sm' }}
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
c="dimmed"
|
c="black"
|
||||||
lh={{ base: 1.5, md: 1.6 }}
|
lh={{ base: 1.5, md: 1.6 }}
|
||||||
dangerouslySetInnerHTML={{ __html: data.jadwalPelayanan || '-' }}
|
dangerouslySetInnerHTML={{ __html: data.jadwalPelayanan || '-' }}
|
||||||
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
@@ -121,8 +125,8 @@ export default function DetailPosyanduUser() {
|
|||||||
<Flex align="center" gap="xs">
|
<Flex align="center" gap="xs">
|
||||||
<IconInfoCircle size={18} stroke={1.5} />
|
<IconInfoCircle size={18} stroke={1.5} />
|
||||||
<Text
|
<Text
|
||||||
fz={{ base: 'xs', md: 'sm' }}
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
c="dimmed"
|
c="black"
|
||||||
lh={{ base: 1.5, md: 1.6 }}
|
lh={{ base: 1.5, md: 1.6 }}
|
||||||
dangerouslySetInnerHTML={{ __html: data.deskripsi || '-' }}
|
dangerouslySetInnerHTML={{ __html: data.deskripsi || '-' }}
|
||||||
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
|
|||||||
@@ -135,32 +135,36 @@ export default function Page() {
|
|||||||
</Center>
|
</Center>
|
||||||
<Flex align="flex-start" gap="xs">
|
<Flex align="flex-start" gap="xs">
|
||||||
<IconPhone size={18} stroke={1.5} style={{ marginTop: 3 }} />
|
<IconPhone size={18} stroke={1.5} style={{ marginTop: 3 }} />
|
||||||
<Box>
|
<Text
|
||||||
<Text fz={{ base: "xs", md: "sm" }} c="dimmed" lh={1.4}>
|
fz={{ base: "sm", md: "md" }}
|
||||||
{v.nomor || "Tidak tersedia"}
|
c="black"
|
||||||
</Text>
|
lh={{ base: 1.4, md: 1.5 }}
|
||||||
</Box>
|
>
|
||||||
|
{v.nomor || "Tidak tersedia"}
|
||||||
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex align="flex-start" gap="xs">
|
<Flex align="flex-start" gap="xs">
|
||||||
<IconCalendar size={18} stroke={1.5} style={{ marginTop: 3 }} />
|
<IconCalendar size={18} stroke={1.5} style={{ marginTop: 3 }} />
|
||||||
<Box>
|
<Text
|
||||||
<Text fz={{ base: "xs", md: "sm" }} c="dimmed" lh={1.4}>
|
fz={{ base: "sm", md: "md" }}
|
||||||
<strong>Jadwal:</strong>{" "}
|
c="black"
|
||||||
<span
|
lh={{ base: 1.4, md: 1.5 }}
|
||||||
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
>
|
||||||
dangerouslySetInnerHTML={{ __html: v.jadwalPelayanan }}
|
<strong>Jadwal:</strong>{" "}
|
||||||
/>
|
<span
|
||||||
</Text>
|
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
||||||
</Box>
|
dangerouslySetInnerHTML={{ __html: v.jadwalPelayanan }}
|
||||||
|
/>
|
||||||
|
</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|
||||||
<Flex align="flex-start" gap="xs">
|
<Flex align="flex-start" gap="xs">
|
||||||
<IconInfoCircle size={18} stroke={1.5} style={{ marginTop: 3 }} />
|
<IconInfoCircle size={18} stroke={1.5} style={{ marginTop: 3 }} />
|
||||||
<Text
|
<Text
|
||||||
fz={{ base: "xs", md: "sm" }}
|
fz={{ base: "sm", md: "md" }}
|
||||||
lh={1.5}
|
lh={{ base: 1.4, md: 1.5 }}
|
||||||
c="dimmed"
|
c="black"
|
||||||
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
||||||
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
||||||
lineClamp={3}
|
lineClamp={3}
|
||||||
@@ -196,7 +200,7 @@ export default function Page() {
|
|||||||
Layanan Utama Posyandu
|
Layanan Utama Posyandu
|
||||||
</Title>
|
</Title>
|
||||||
</Flex>
|
</Flex>
|
||||||
<List spacing="xs" fz={{ base: "xs", md: "sm" }} center>
|
<List spacing="xs" fz={{ base: "sm", md: "md" }} lh={{ base: 1.4, md: 1.5 }} c="black">
|
||||||
<ListItem>Penimbangan bayi dan balita</ListItem>
|
<ListItem>Penimbangan bayi dan balita</ListItem>
|
||||||
<ListItem>Pemantauan status gizi</ListItem>
|
<ListItem>Pemantauan status gizi</ListItem>
|
||||||
<ListItem>Imunisasi dasar lengkap</ListItem>
|
<ListItem>Imunisasi dasar lengkap</ListItem>
|
||||||
@@ -208,4 +212,4 @@ export default function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import programKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan';
|
import programKesehatan from '@/app/admin/(dashboard)/_state/kesehatan/program-kesehatan/programKesehatan';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Center, Group, Image, Loader, Paper, Skeleton, Stack, Text, Tooltip } from '@mantine/core';
|
import { Box, Center, Group, Image, Loader, Paper, Skeleton, Stack, Text, Title, Tooltip } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconCalendar, IconUser } from '@tabler/icons-react';
|
import { IconCalendar, IconUser } from '@tabler/icons-react';
|
||||||
import { useParams } from 'next/navigation';
|
import { useParams } from 'next/navigation';
|
||||||
@@ -9,12 +9,12 @@ import { useProxy } from 'valtio/utils';
|
|||||||
import BackButton from '../../../desa/layanan/_com/BackButto';
|
import BackButton from '../../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const state = useProxy(programKesehatan)
|
const state = useProxy(programKesehatan);
|
||||||
const params = useParams()
|
const params = useParams();
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
state.findUnique.load(params.id as string)
|
state.findUnique.load(params.id as string);
|
||||||
}, [params.id])
|
}, [params.id]);
|
||||||
|
|
||||||
if (!state.findUnique.data) {
|
if (!state.findUnique.data) {
|
||||||
return (
|
return (
|
||||||
@@ -24,7 +24,7 @@ function Page() {
|
|||||||
<Text c="dimmed" fz="sm">Memuat data program kesehatan...</Text>
|
<Text c="dimmed" fz="sm">Memuat data program kesehatan...</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -33,68 +33,73 @@ function Page() {
|
|||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<Paper
|
<Paper
|
||||||
px={{ base: 'md', md: 100 }}
|
px={{ base: 'md', md: 100 }}
|
||||||
py="xl"
|
py="xl"
|
||||||
radius="xl"
|
radius="xl"
|
||||||
shadow="md"
|
shadow="md"
|
||||||
bg={colors["white-trans-1"]}
|
bg={colors["white-trans-1"]}
|
||||||
>
|
>
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<Center>
|
<Center>
|
||||||
{state.findUnique.data.image?.link ? (
|
{state.findUnique.data.image?.link ? (
|
||||||
<Image
|
<Image
|
||||||
radius="xl"
|
src={state.findUnique.data.image?.link}
|
||||||
src={state.findUnique.data.image?.link}
|
alt={state.findUnique.data.name}
|
||||||
alt={state.findUnique.data.name}
|
radius="md"
|
||||||
w="100%"
|
mah={300}
|
||||||
maw={800}
|
fit="contain"
|
||||||
fit="cover"
|
loading="lazy"
|
||||||
loading="lazy"
|
/>
|
||||||
|
) : (
|
||||||
|
<Skeleton h={300} w="100%" radius="xl" />
|
||||||
|
)}
|
||||||
|
</Center>
|
||||||
|
<Box pl={20}>
|
||||||
|
<Title
|
||||||
|
order={1}
|
||||||
|
pb="sm"
|
||||||
|
c={colors["blue-button"]}
|
||||||
|
fw="bold"
|
||||||
|
lh={{ base: 1.2, md: 1.15 }}
|
||||||
|
>
|
||||||
|
{state.findUnique.data.name}
|
||||||
|
</Title>
|
||||||
|
<Text
|
||||||
|
ta="justify"
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
lh={{ base: 1.5, md: 1.6 }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsi }}
|
||||||
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
/>
|
/>
|
||||||
) : (
|
</Box>
|
||||||
<Skeleton h={300} w="100%" radius="xl" />
|
<Group gap="xl">
|
||||||
)}
|
<Group gap="xs">
|
||||||
</Center>
|
<Tooltip label="Tanggal dibuat" withArrow>
|
||||||
<Box>
|
<IconCalendar color="gray" size={20} stroke={1.5} />
|
||||||
<Text pb="sm" c={colors["blue-button"]} fw="bold" fz={{ base: 24, md: 32 }} lh={1.2}>
|
</Tooltip>
|
||||||
{state.findUnique.data.name}
|
<Text fz={{ base: 'xs', md: 'sm' }} c="dimmed">
|
||||||
</Text>
|
{state.findUnique.data.createdAt
|
||||||
<Text
|
? new Date(state.findUnique.data.createdAt).toLocaleDateString('id-ID', {
|
||||||
ta="justify"
|
|
||||||
fz="md"
|
|
||||||
lh={1.6}
|
|
||||||
dangerouslySetInnerHTML={{ __html: state.findUnique.data.deskripsi }}
|
|
||||||
style={{wordBreak: "break-word", whiteSpace: "normal"}}
|
|
||||||
/>
|
|
||||||
</Box>
|
|
||||||
<Group gap="xl">
|
|
||||||
<Group gap="xs">
|
|
||||||
<Tooltip label="Tanggal dibuat" withArrow>
|
|
||||||
<IconCalendar color='gray' size={20} stroke={1.5} />
|
|
||||||
</Tooltip>
|
|
||||||
<Text size="sm" c="dimmed">
|
|
||||||
{state.findUnique.data.createdAt
|
|
||||||
? new Date(state.findUnique.data.createdAt).toLocaleDateString('id-ID', {
|
|
||||||
day: 'numeric',
|
day: 'numeric',
|
||||||
month: 'long',
|
month: 'long',
|
||||||
year: 'numeric',
|
year: 'numeric',
|
||||||
})
|
})
|
||||||
: 'Tanggal tidak tersedia'}
|
: 'Tanggal tidak tersedia'}
|
||||||
</Text>
|
</Text>
|
||||||
|
</Group>
|
||||||
|
<Group gap="xs">
|
||||||
|
<Tooltip label="Dibuat oleh" withArrow>
|
||||||
|
<IconUser color="gray" size={20} stroke={1.5} />
|
||||||
|
</Tooltip>
|
||||||
|
<Text fz={{ base: 'xs', md: 'sm' }} c="dimmed">Admin Desa</Text>
|
||||||
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
</Stack>
|
||||||
<Tooltip label="Dibuat oleh" withArrow>
|
</Paper>
|
||||||
<IconUser color='gray' size={20} stroke={1.5} />
|
|
||||||
</Tooltip>
|
|
||||||
<Text size="sm" c="dimmed">Admin Desa</Text>
|
|
||||||
</Group>
|
|
||||||
</Group>
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -16,6 +16,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
TextInput,
|
TextInput,
|
||||||
|
Title,
|
||||||
Transition
|
Transition
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
import { useDebouncedValue, useShallowEffect } from "@mantine/hooks";
|
import { useDebouncedValue, useShallowEffect } from "@mantine/hooks";
|
||||||
@@ -57,7 +58,7 @@ export default function Page() {
|
|||||||
const state = useProxy(programKesehatan);
|
const state = useProxy(programKesehatan);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const [search, setSearch] = useState("");
|
const [search, setSearch] = useState("");
|
||||||
const [debouncedSearch] = useDebouncedValue(search, 1000); // 500ms delay
|
const [debouncedSearch] = useDebouncedValue(search, 1000);
|
||||||
const { data, page, totalPages, loading, load } = state.findMany;
|
const { data, page, totalPages, loading, load } = state.findMany;
|
||||||
|
|
||||||
useShallowEffect(() => {
|
useShallowEffect(() => {
|
||||||
@@ -80,14 +81,19 @@ export default function Page() {
|
|||||||
|
|
||||||
<Grid px={{ base: "md", md: 100 }} align="center" gutter="lg">
|
<Grid px={{ base: "md", md: 100 }} align="center" gutter="lg">
|
||||||
<GridCol span={{ base: 12, md: 8 }}>
|
<GridCol span={{ base: 12, md: 8 }}>
|
||||||
<Text
|
<Title
|
||||||
fz={{ base: "2rem", md: "2.8rem" }}
|
order={1}
|
||||||
c={colors["blue-button"]}
|
c={colors["blue-button"]}
|
||||||
fw="bold"
|
fw="bold"
|
||||||
|
fz={{ base: '28px', md: '32px' }}
|
||||||
>
|
>
|
||||||
Program Kesehatan Desa
|
Program Kesehatan Desa
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="lg" mt="xs">
|
<Text
|
||||||
|
fz={{ base: '14px', md: '16px' }}
|
||||||
|
lh={{ base: '1.5', md: '1.6' }}
|
||||||
|
mt="xs"
|
||||||
|
>
|
||||||
Temukan berbagai program kesehatan untuk mendukung kualitas hidup
|
Temukan berbagai program kesehatan untuk mendukung kualitas hidup
|
||||||
masyarakat Darmasaba.
|
masyarakat Darmasaba.
|
||||||
</Text>
|
</Text>
|
||||||
@@ -129,11 +135,9 @@ export default function Page() {
|
|||||||
<Box
|
<Box
|
||||||
style={{
|
style={{
|
||||||
width: '100%',
|
width: '100%',
|
||||||
height: 180, // 🔥 tinggi fix biar semua seragam
|
aspectRatio: '16/9', // thumbnail landscape aman untuk portrait/landscape
|
||||||
borderRadius: 12,
|
borderRadius: 12,
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
position: 'relative',
|
|
||||||
backgroundColor: '#f0f2f5', // fallback kalau gambar loading
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Image
|
<Image
|
||||||
@@ -142,32 +146,28 @@ export default function Page() {
|
|||||||
fit="cover"
|
fit="cover"
|
||||||
width="100%"
|
width="100%"
|
||||||
height="100%"
|
height="100%"
|
||||||
|
style={{ objectFit: 'cover', objectPosition: 'center' }}
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
style={{
|
|
||||||
objectFit: 'cover',
|
|
||||||
objectPosition: 'center',
|
|
||||||
transition: 'transform 0.4s ease',
|
|
||||||
}}
|
|
||||||
onMouseEnter={(e) => (e.currentTarget.style.transform = 'scale(1.05)')}
|
onMouseEnter={(e) => (e.currentTarget.style.transform = 'scale(1.05)')}
|
||||||
onMouseLeave={(e) => (e.currentTarget.style.transform = 'scale(1)')}
|
onMouseLeave={(e) => (e.currentTarget.style.transform = 'scale(1)')}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|
||||||
</Center>
|
</Center>
|
||||||
|
|
||||||
<Box px="lg" pb="lg">
|
<Box px="lg" pb="lg">
|
||||||
<Text
|
<Title
|
||||||
fw="bold"
|
order={3}
|
||||||
fz="xl"
|
|
||||||
c={colors["blue-button"]}
|
c={colors["blue-button"]}
|
||||||
|
fw="bold"
|
||||||
|
fz={{ base: '18px', md: '20px' }}
|
||||||
mb="xs"
|
mb="xs"
|
||||||
>
|
>
|
||||||
{v.name}
|
{v.name}
|
||||||
</Text>
|
</Title>
|
||||||
<Text
|
<Text
|
||||||
fz="sm"
|
fz={{ base: '13px', md: '14px' }}
|
||||||
ta={"justify"}
|
lh="1.6"
|
||||||
|
ta="justify"
|
||||||
lineClamp={3}
|
lineClamp={3}
|
||||||
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
dangerouslySetInnerHTML={{ __html: v.deskripsi }}
|
||||||
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
style={{ wordBreak: "break-word", whiteSpace: "normal" }}
|
||||||
@@ -175,7 +175,10 @@ export default function Page() {
|
|||||||
<Group justify="space-between" mt="md">
|
<Group justify="space-between" mt="md">
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconCalendar size={18} />
|
<IconCalendar size={18} />
|
||||||
<Text size="sm">
|
<Text
|
||||||
|
fz={{ base: '12px', md: '14px' }}
|
||||||
|
lh="1.5"
|
||||||
|
>
|
||||||
{v.createdAt
|
{v.createdAt
|
||||||
? new Date(v.createdAt).toLocaleDateString(
|
? new Date(v.createdAt).toLocaleDateString(
|
||||||
"id-ID",
|
"id-ID",
|
||||||
@@ -190,25 +193,30 @@ export default function Page() {
|
|||||||
</Group>
|
</Group>
|
||||||
<Group gap="xs">
|
<Group gap="xs">
|
||||||
<IconUser size={18} />
|
<IconUser size={18} />
|
||||||
<Text size="sm">Admin Desa</Text>
|
<Text
|
||||||
|
fz={{ base: '12px', md: '14px' }}
|
||||||
|
lh="1.5"
|
||||||
|
>
|
||||||
|
Admin Desa
|
||||||
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Group>
|
</Group>
|
||||||
<Button
|
<Button
|
||||||
mt="lg"
|
mt="lg"
|
||||||
fullWidth
|
fullWidth
|
||||||
radius="lg"
|
radius="lg"
|
||||||
size="md"
|
size="md"
|
||||||
fw="bold"
|
fw="bold"
|
||||||
variant="gradient"
|
variant="gradient"
|
||||||
gradient={{ from: colors["blue-button"], to: "#4dabf7" }}
|
gradient={{ from: colors["blue-button"], to: "#4dabf7" }}
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
router.push(
|
router.push(
|
||||||
`/darmasaba/kesehatan/program-kesehatan/${v.id}`
|
`/darmasaba/kesehatan/program-kesehatan/${v.id}`
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
Lihat Detail
|
Lihat Detail
|
||||||
</Button>
|
</Button>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -239,14 +247,19 @@ export default function Page() {
|
|||||||
|
|
||||||
<Box px={{ base: "md", md: 100 }} py="xl">
|
<Box px={{ base: "md", md: 100 }} py="xl">
|
||||||
<Stack gap="sm" mb="lg">
|
<Stack gap="sm" mb="lg">
|
||||||
<Text
|
<Title
|
||||||
fz={{ base: "2rem", md: "2.5rem" }}
|
order={2}
|
||||||
c={colors["blue-button"]}
|
c={colors["blue-button"]}
|
||||||
fw="bold"
|
fw="bold"
|
||||||
|
fz={{ base: '24px', md: '28px' }}
|
||||||
>
|
>
|
||||||
Manfaat Program Kesehatan
|
Manfaat Program Kesehatan
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="lg" maw={700}>
|
<Text
|
||||||
|
fz={{ base: '14px', md: '16px' }}
|
||||||
|
lh={{ base: '1.5', md: '1.6' }}
|
||||||
|
maw={700}
|
||||||
|
>
|
||||||
Program kesehatan Desa Darmasaba berperan penting dalam meningkatkan
|
Program kesehatan Desa Darmasaba berperan penting dalam meningkatkan
|
||||||
kesejahteraan dan kualitas hidup warganya.
|
kesejahteraan dan kualitas hidup warganya.
|
||||||
</Text>
|
</Text>
|
||||||
@@ -273,10 +286,20 @@ export default function Page() {
|
|||||||
>
|
>
|
||||||
<Center>{v.icon}</Center>
|
<Center>{v.icon}</Center>
|
||||||
</Paper>
|
</Paper>
|
||||||
<Text ta="center" fw="bold" fz="xl" c={colors["blue-button"]}>
|
<Title
|
||||||
|
order={3}
|
||||||
|
ta="center"
|
||||||
|
fw="bold"
|
||||||
|
c={colors["blue-button"]}
|
||||||
|
fz={{ base: '18px', md: '20px' }}
|
||||||
|
>
|
||||||
{v.title}
|
{v.title}
|
||||||
</Text>
|
</Title>
|
||||||
<Text ta="center" fz="sm">
|
<Text
|
||||||
|
ta="center"
|
||||||
|
fz={{ base: '13px', md: '14px' }}
|
||||||
|
lh="1.5"
|
||||||
|
>
|
||||||
{v.desc}
|
{v.desc}
|
||||||
</Text>
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -286,4 +309,4 @@ export default function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -59,12 +59,16 @@ function Page() {
|
|||||||
left={20}
|
left={20}
|
||||||
gap={6}
|
gap={6}
|
||||||
>
|
>
|
||||||
<Text fw="bold" fz={{ base: 'lg', md: 'h2' }} c={colors['white-1']}>
|
<Title
|
||||||
|
order={1}
|
||||||
|
c={colors['white-1']}
|
||||||
|
fz={{ base: 'lg', md: 'xl' }}
|
||||||
|
>
|
||||||
{data.name}
|
{data.name}
|
||||||
</Text>
|
</Title>
|
||||||
<Group gap={6}>
|
<Group gap={6}>
|
||||||
<IconMapPin size={20} color="white" />
|
<IconMapPin size={20} color="white" />
|
||||||
<Text fz={{ base: 'sm', md: 'md' }} c={colors['white-1']}>
|
<Text fz={{ base: 'xs', md: 'sm' }} c={colors['white-1']}>
|
||||||
{data.alamat}
|
{data.alamat}
|
||||||
</Text>
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
@@ -75,37 +79,45 @@ function Page() {
|
|||||||
<GridCol span={{ base: 12, md: 6 }}>
|
<GridCol span={{ base: 12, md: 6 }}>
|
||||||
<Stack gap="lg">
|
<Stack gap="lg">
|
||||||
<Box>
|
<Box>
|
||||||
<Title order={3} mb={10}>Informasi Kontak</Title>
|
<Title order={2} mb="md">Informasi Kontak</Title>
|
||||||
<Stack gap={8}>
|
<Stack gap={8}>
|
||||||
<Group gap={8}>
|
<Group gap={8}>
|
||||||
<IconPhone size={18} />
|
<IconPhone size={18} />
|
||||||
<Text fz="md">{data.kontak.kontakPuskesmas || '-'}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }}>
|
||||||
|
{data.kontak.kontakPuskesmas || '-'}
|
||||||
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
<Group gap={8}>
|
<Group gap={8}>
|
||||||
<IconMail size={18} />
|
<IconMail size={18} />
|
||||||
<Text fz="md">{data.kontak.email || '-'}</Text>
|
<Text fz={{ base: 'sm', md: 'md' }}>
|
||||||
|
{data.kontak.email || '-'}
|
||||||
|
</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
|
|
||||||
<Stack gap={"xs"}>
|
<Stack gap="xs">
|
||||||
<Title order={3} mb={10}>Jam Operasional</Title>
|
<Title order={2} mb="md">Jam Operasional</Title>
|
||||||
<Text fw="bold" fz="md">Senin - Jumat</Text>
|
<Text fw="bold" fz={{ base: 'sm', md: 'md' }}>Senin - Jumat</Text>
|
||||||
<Group gap={8}>
|
<Group gap={8}>
|
||||||
<IconClock size={18} />
|
<IconClock size={18} />
|
||||||
<Text fw="bold" fz="md">{data.jam.workDays} - {data.jam.weekDays}</Text>
|
<Text fw="bold" fz={{ base: 'sm', md: 'md' }}>
|
||||||
|
{data.jam.workDays} – {data.jam.weekDays}
|
||||||
|
</Text>
|
||||||
<Tooltip label="Hari aktif pelayanan puskesmas" position="top" withArrow>
|
<Tooltip label="Hari aktif pelayanan puskesmas" position="top" withArrow>
|
||||||
<Badge size="sm" variant="light" color="blue">Aktif</Badge>
|
<Badge size="sm" variant="light" color="blue">Aktif</Badge>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Group>
|
</Group>
|
||||||
<Text fw="bold" fz="md">Sabtu - Minggu / Hari Libur</Text>
|
<Text fw="bold" fz={{ base: 'sm', md: 'md' }}>Sabtu – Minggu / Hari Libur</Text>
|
||||||
<Group gap={8}>
|
<Group gap={8}>
|
||||||
<IconClock size={18} />
|
<IconClock size={18} />
|
||||||
<Text fw="bold" fz="md">{data.jam.holiday}</Text>
|
<Text fw="bold" fz={{ base: 'sm', md: 'md' }}>
|
||||||
|
{data.jam.holiday}
|
||||||
|
</Text>
|
||||||
<Tooltip label="Hari aktif pelayanan puskesmas" position="top" withArrow>
|
<Tooltip label="Hari aktif pelayanan puskesmas" position="top" withArrow>
|
||||||
<Badge size="sm" variant="light" color="blue">Aktif</Badge>
|
<Badge size="sm" variant="light" color="blue">Aktif</Badge>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
@@ -114,20 +126,24 @@ function Page() {
|
|||||||
|
|
||||||
<GridCol span={{ base: 12, md: 6 }}>
|
<GridCol span={{ base: 12, md: 6 }}>
|
||||||
<Paper p="xl" radius="lg" bg="linear-gradient(135deg, #EAF0FB, #BFD4F5)" shadow="sm">
|
<Paper p="xl" radius="lg" bg="linear-gradient(135deg, #EAF0FB, #BFD4F5)" shadow="sm">
|
||||||
<Title order={3} mb="lg" ta="center" c="dark">Layanan Unggulan</Title>
|
<Title order={2} mb="lg" ta="center" c="dark">Layanan Unggulan</Title>
|
||||||
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="lg">
|
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="lg">
|
||||||
<Paper p="lg" radius="lg" withBorder bg={colors['white-trans-1']} shadow="xs">
|
<Paper p="lg" radius="lg" withBorder bg={colors['white-trans-1']} shadow="xs">
|
||||||
<Stack align="center" gap={8}>
|
<Stack align="center" gap={8}>
|
||||||
<IconBuildingHospital size={36} color={colors['blue-button']} />
|
<IconBuildingHospital size={36} color={colors['blue-button']} />
|
||||||
<Text fw="bold" fz="lg">Poliklinik Umum</Text>
|
<Text fw="bold" fz={{ base: 'sm', md: 'md' }}>Poliklinik Umum</Text>
|
||||||
<Text fz={{ base: 36, md: 48 }} fw="bold" c={colors['blue-button']}>26</Text>
|
<Text fz={{ base: 'h1', md: 'h1' }} fw="bold" c={colors['blue-button']} lh={1}>
|
||||||
|
26
|
||||||
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
<Paper p="lg" radius="lg" withBorder bg={colors['white-trans-1']} shadow="xs">
|
<Paper p="lg" radius="lg" withBorder bg={colors['white-trans-1']} shadow="xs">
|
||||||
<Stack align="center" gap={8}>
|
<Stack align="center" gap={8}>
|
||||||
<IconBuildingHospital size={36} color={colors['blue-button']} />
|
<IconBuildingHospital size={36} color={colors['blue-button']} />
|
||||||
<Text fw="bold" fz="lg">Poli Gigi</Text>
|
<Text fw="bold" fz={{ base: 'sm', md: 'md' }}>Poli Gigi</Text>
|
||||||
<Text fz={{ base: 36, md: 48 }} fw="bold" c={colors['blue-button']}>26</Text>
|
<Text fz={{ base: 'h1', md: 'h1' }} fw="bold" c={colors['blue-button']} lh={1}>
|
||||||
|
26
|
||||||
|
</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
@@ -141,4 +157,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import puskesmasState from '@/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas';
|
import puskesmasState from '@/app/admin/(dashboard)/_state/kesehatan/puskesmas/puskesmas';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Anchor, Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Badge, Group } from '@mantine/core';
|
import { Anchor, Box, Center, Grid, GridCol, Image, Pagination, Paper, SimpleGrid, Skeleton, Stack, Text, TextInput, Badge, Group, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconSearch, IconMapPin, IconPhone, IconMail } from '@tabler/icons-react';
|
import { IconSearch, IconMapPin, IconPhone, IconMail } from '@tabler/icons-react';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
@@ -42,10 +42,10 @@ function Page() {
|
|||||||
|
|
||||||
<Grid align="center" px={{ base: 'md', md: 100 }} mb="md">
|
<Grid align="center" px={{ base: 'md', md: 100 }} mb="md">
|
||||||
<GridCol span={{ base: 12, md: 8 }}>
|
<GridCol span={{ base: 12, md: 8 }}>
|
||||||
<Text fz={{ base: "2rem", md: "2.5rem" }} c={colors["blue-button"]} fw="bold">
|
<Title order={1} c={colors["blue-button"]}>
|
||||||
Daftar Puskesmas
|
Daftar Puskesmas
|
||||||
</Text>
|
</Title>
|
||||||
<Text fz="md">
|
<Text fz={{ base: "sm", md: "md" }} ta="start">
|
||||||
Temukan informasi lengkap mengenai layanan, kontak, dan lokasi Puskesmas Darmasaba
|
Temukan informasi lengkap mengenai layanan, kontak, dan lokasi Puskesmas Darmasaba
|
||||||
</Text>
|
</Text>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
@@ -65,8 +65,8 @@ function Page() {
|
|||||||
{data.length === 0 ? (
|
{data.length === 0 ? (
|
||||||
<Center py="xl">
|
<Center py="xl">
|
||||||
<Stack align="center" gap="xs">
|
<Stack align="center" gap="xs">
|
||||||
<Text fz="lg" fw={500} c="dimmed">Tidak ada data ditemukan</Text>
|
<Title order={2} fw={500} c="dimmed">Tidak ada data ditemukan</Title>
|
||||||
<Text fz="sm" c="dimmed">Coba gunakan kata kunci pencarian yang berbeda</Text>
|
<Text fz={{ base: "xs", md: "sm" }} c="dimmed">Coba gunakan kata kunci pencarian yang berbeda</Text>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Center>
|
</Center>
|
||||||
) : (
|
) : (
|
||||||
@@ -92,29 +92,29 @@ function Page() {
|
|||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
<Group justify="space-between">
|
<Group justify="space-between">
|
||||||
<Text fw={600} fz="lg" lineClamp={1}>{v.name}</Text>
|
<Title order={3} fw={600} lineClamp={1}>{v.name}</Title>
|
||||||
<Badge color="blue" variant="light" radius="sm" fz="xs">Aktif</Badge>
|
<Badge color="blue" variant="light" radius="sm" fz="xs">Aktif</Badge>
|
||||||
</Group>
|
</Group>
|
||||||
<Stack gap={6}>
|
<Stack gap={6}>
|
||||||
<Group gap="xs" align="flex-start" wrap="nowrap">
|
<Group gap="xs" align="flex-start" wrap="nowrap">
|
||||||
<Box pt={2}><IconMapPin size={20} /></Box>
|
<Box pt={2}><IconMapPin size={20} /></Box>
|
||||||
<Text fz="sm" c="dimmed">{v.alamat}</Text>
|
<Text fz={{ base: "sm", md: "md" }}>{v.alamat}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group gap="xs" align="flex-start" wrap="nowrap">
|
<Group gap="xs" align="flex-start" wrap="nowrap">
|
||||||
<Box pt={2}><IconPhone size={20} /></Box>
|
<Box pt={2}><IconPhone size={20} /></Box>
|
||||||
<Text fz="sm" c="dimmed">{v.kontak.kontakPuskesmas}</Text>
|
<Text fz={{ base: "sm", md: "md" }}>{v.kontak.kontakPuskesmas}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Group gap="xs" align="flex-start" wrap="nowrap">
|
<Group gap="xs" align="flex-start" wrap="nowrap">
|
||||||
<Box pt={2}><IconMail size={20} /></Box>
|
<Box pt={2}><IconMail size={20} /></Box>
|
||||||
<Text fz="sm" c="dimmed">{v.kontak.email}</Text>
|
<Text fz={{ base: "sm", md: "md" }}>{v.kontak.email}</Text>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
|
|
||||||
<Anchor
|
<Anchor
|
||||||
href={`/darmasaba/kesehatan/puskesmas/${v.id}`}
|
href={`/darmasaba/kesehatan/puskesmas/${v.id}`}
|
||||||
fz="sm"
|
fz={{ base: "sm", md: "md" }}
|
||||||
fw={500}
|
fw={500}
|
||||||
c={colors['blue-button']}
|
c={colors['blue-button']}
|
||||||
>
|
>
|
||||||
@@ -143,4 +143,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -64,14 +64,14 @@ function Page() {
|
|||||||
</Text>
|
</Text>
|
||||||
<TextInput
|
<TextInput
|
||||||
radius="xl"
|
radius="xl"
|
||||||
w={'30%'}
|
w={{base: "100%", md: "30%"}}
|
||||||
placeholder="Cari Data Lingkungan Desa"
|
placeholder="Cari Data Lingkungan Desa"
|
||||||
leftSection={<IconSearch size={20} />}
|
leftSection={<IconSearch size={20} />}
|
||||||
value={search}
|
value={search}
|
||||||
onChange={(e) => setSearch(e.currentTarget.value)}
|
onChange={(e) => setSearch(e.currentTarget.value)}
|
||||||
/>
|
/>
|
||||||
</Group>
|
</Group>
|
||||||
<Text fz="md" >
|
<Text fz="md" pt={20}>
|
||||||
Desa Darmasaba menjaga dan mengembangkan lingkungan demi kesejahteraan warganya.
|
Desa Darmasaba menjaga dan mengembangkan lingkungan demi kesejahteraan warganya.
|
||||||
</Text>
|
</Text>
|
||||||
<Text fz="md">
|
<Text fz="md">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Create a new component: components/EdukasiCard.tsx
|
// components/EdukasiCard.tsx
|
||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Box, Paper, Stack, Text } from '@mantine/core';
|
import { Box, Paper, Stack, Text, Title } from '@mantine/core';
|
||||||
import { ReactNode } from 'react';
|
import { ReactNode } from 'react';
|
||||||
|
|
||||||
interface EdukasiCardProps {
|
interface EdukasiCardProps {
|
||||||
@@ -18,7 +18,7 @@ export function EdukasiCard({ icon, title, description, color = '#1e88e5' }: Edu
|
|||||||
radius="md"
|
radius="md"
|
||||||
shadow="sm"
|
shadow="sm"
|
||||||
withBorder
|
withBorder
|
||||||
style={{
|
style={{
|
||||||
height: '100%',
|
height: '100%',
|
||||||
transition: 'transform 0.2s, box-shadow 0.2s',
|
transition: 'transform 0.2s, box-shadow 0.2s',
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
@@ -31,32 +31,35 @@ export function EdukasiCard({ icon, title, description, color = '#1e88e5' }: Edu
|
|||||||
<Box>
|
<Box>
|
||||||
<Stack align="center" gap="xs" mb="md">
|
<Stack align="center" gap="xs" mb="md">
|
||||||
<Box style={{ color }}>{icon}</Box>
|
<Box style={{ color }}>{icon}</Box>
|
||||||
<Text
|
<Title
|
||||||
fz={{ base: 'h5', md: 'h4' }}
|
order={3}
|
||||||
fw={700}
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
c={color}
|
c={color}
|
||||||
ta="center"
|
ta="center"
|
||||||
lineClamp={2}
|
lineClamp={2}
|
||||||
style={{
|
style={{
|
||||||
wordBreak: 'break-word',
|
wordBreak: 'break-word',
|
||||||
minHeight: '3.5rem',
|
minHeight: '3.5rem',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
justifyContent: 'center'
|
justifyContent: 'center',
|
||||||
}}
|
lineHeight: 1.2
|
||||||
dangerouslySetInnerHTML={{ __html: title }}
|
}}
|
||||||
/>
|
dangerouslySetInnerHTML={{ __html: title }}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
<Text
|
<Box pl={20}>
|
||||||
size="sm"
|
<Text
|
||||||
pl={20}
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
style={{
|
lh={1.5}
|
||||||
wordBreak: 'break-word',
|
c="gray.7"
|
||||||
lineHeight: 1.6,
|
ta="justify"
|
||||||
color: 'var(--mantine-color-gray-7)'
|
style={{
|
||||||
}}
|
wordBreak: 'break-word'
|
||||||
dangerouslySetInnerHTML={{ __html: description }}
|
}}
|
||||||
/>
|
dangerouslySetInnerHTML={{ __html: description }}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
'use client';
|
'use client';
|
||||||
|
|
||||||
import { Box, Container, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Container, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { IconLeaf, IconPlant2, IconRecycle } from '@tabler/icons-react';
|
import { IconLeaf, IconPlant2, IconRecycle } from '@tabler/icons-react';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
@@ -51,19 +51,21 @@ export default function EdukasiLingkunganPage() {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Container size="lg" ta="center">
|
<Container size="lg" ta="center">
|
||||||
<Text
|
<Title
|
||||||
component="h1"
|
order={1}
|
||||||
fz={{ base: 'h2', md: '2.5rem' }}
|
|
||||||
c={colors['blue-button']}
|
c={colors['blue-button']}
|
||||||
fw={700}
|
fw={700}
|
||||||
mb="md"
|
mb="md"
|
||||||
|
lh={1.15}
|
||||||
>
|
>
|
||||||
Edukasi Lingkungan
|
Edukasi Lingkungan
|
||||||
</Text>
|
</Title>
|
||||||
<Text
|
<Text
|
||||||
fz={{ base: 'md', md: 'lg' }}
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
lh={1.5}
|
||||||
maw={800}
|
maw={800}
|
||||||
mx="auto"
|
mx="auto"
|
||||||
|
c="dark.9"
|
||||||
>
|
>
|
||||||
Program edukasi ini membimbing masyarakat untuk peduli dan bertanggung jawab terhadap alam,
|
Program edukasi ini membimbing masyarakat untuk peduli dan bertanggung jawab terhadap alam,
|
||||||
meningkatkan kesehatan, kenyamanan, dan keberlanjutan hidup bersama.
|
meningkatkan kesehatan, kenyamanan, dan keberlanjutan hidup bersama.
|
||||||
|
|||||||
@@ -41,23 +41,23 @@ function DetailKegiatanDesaUser() {
|
|||||||
shadow="sm"
|
shadow="sm"
|
||||||
maw={900}
|
maw={900}
|
||||||
mx="auto"
|
mx="auto"
|
||||||
>
|
>
|
||||||
<Stack gap="md">
|
<Stack gap="md">
|
||||||
{data.image?.link && (
|
|
||||||
<Image
|
|
||||||
src={data.image.link}
|
|
||||||
alt={data.judul || 'Kegiatan Desa'}
|
|
||||||
radius="md"
|
|
||||||
fit="cover"
|
|
||||||
h={300}
|
|
||||||
mb="xl"
|
|
||||||
style={{ objectPosition: 'center', width: '100%' }}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{/* Judul */}
|
{/* Judul */}
|
||||||
<Title order={2} c={colors['blue-button']}>
|
<Title order={1} ta={"center"} c={colors['blue-button']}>
|
||||||
{data.judul || 'Kegiatan Desa'}
|
{data.judul || 'Kegiatan Desa'}
|
||||||
</Title>
|
</Title>
|
||||||
|
{data.image?.link && (
|
||||||
|
<Image
|
||||||
|
src={data.image.link}
|
||||||
|
alt={data.judul || 'Kegiatan Desa'}
|
||||||
|
radius="md"
|
||||||
|
fit="cover"
|
||||||
|
h={300}
|
||||||
|
mb="xl"
|
||||||
|
style={{ objectPosition: 'center', width: '100%' }}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Meta Info */}
|
{/* Meta Info */}
|
||||||
<Group gap="xl" c="dimmed">
|
<Group gap="xl" c="dimmed">
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
// app/desa/berita/BeritaLayoutClient.tsx
|
// app/desa/berita/BeritaLayoutClient.tsx
|
||||||
'use client'
|
'use client'
|
||||||
|
import colors from '@/con/colors';
|
||||||
|
import { Box } from '@mantine/core';
|
||||||
import dynamic from 'next/dynamic';
|
import dynamic from 'next/dynamic';
|
||||||
|
import { usePathname } from 'next/navigation';
|
||||||
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
const LayoutTabsGotongRoyong = dynamic(
|
const LayoutTabsGotongRoyong = dynamic(
|
||||||
() => import('./_lib/layoutTabs'),
|
() => import('./_lib/layoutTabs'),
|
||||||
@@ -8,5 +12,21 @@ const LayoutTabsGotongRoyong = dynamic(
|
|||||||
);
|
);
|
||||||
|
|
||||||
export default function GotongRoyongLayoutClient({ children }: { children: React.ReactNode }) {
|
export default function GotongRoyongLayoutClient({ children }: { children: React.ReactNode }) {
|
||||||
|
const pathname = usePathname()
|
||||||
|
const segments = pathname.split('/').filter(Boolean)
|
||||||
|
const isDetailPage = segments.length === 5;
|
||||||
|
|
||||||
|
if (isDetailPage) {
|
||||||
|
// Tampilkan tanpa tab menu
|
||||||
|
return (
|
||||||
|
<Box bg={colors.Bg}>
|
||||||
|
<Box pt={33} px={{ base: 'md', md: 100 }}>
|
||||||
|
<BackButton />
|
||||||
|
</Box>
|
||||||
|
{children}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return <LayoutTabsGotongRoyong>{children}</LayoutTabsGotongRoyong>;
|
return <LayoutTabsGotongRoyong>{children}</LayoutTabsGotongRoyong>;
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
Center,
|
Center,
|
||||||
Container,
|
Container,
|
||||||
Divider,
|
Divider,
|
||||||
Flex,
|
|
||||||
Grid,
|
Grid,
|
||||||
GridCol,
|
GridCol,
|
||||||
Group,
|
Group,
|
||||||
@@ -23,7 +22,7 @@ import {
|
|||||||
Stack,
|
Stack,
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title,
|
||||||
Transition,
|
Transition
|
||||||
} from '@mantine/core';
|
} from '@mantine/core';
|
||||||
import { IconArrowRight, IconCalendar } from '@tabler/icons-react';
|
import { IconArrowRight, IconCalendar } from '@tabler/icons-react';
|
||||||
import { motion } from 'framer-motion';
|
import { motion } from 'framer-motion';
|
||||||
@@ -46,7 +45,7 @@ export default function Page() {
|
|||||||
// Load featured data once on component mount
|
// Load featured data once on component mount
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let mounted = true;
|
let mounted = true;
|
||||||
|
|
||||||
const loadFeatured = async () => {
|
const loadFeatured = async () => {
|
||||||
try {
|
try {
|
||||||
if (!featured.data && !loadingFeatured) {
|
if (!featured.data && !loadingFeatured) {
|
||||||
@@ -68,7 +67,7 @@ export default function Page() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let mounted = true;
|
let mounted = true;
|
||||||
|
|
||||||
const loadData = async () => {
|
const loadData = async () => {
|
||||||
try {
|
try {
|
||||||
const limit = 3;
|
const limit = 3;
|
||||||
@@ -92,7 +91,7 @@ export default function Page() {
|
|||||||
if (search) url.set('search', search);
|
if (search) url.set('search', search);
|
||||||
if (newPage > 1) url.set('page', newPage.toString());
|
if (newPage > 1) url.set('page', newPage.toString());
|
||||||
else url.delete('page');
|
else url.delete('page');
|
||||||
|
|
||||||
// Use push instead of replace to keep browser history
|
// Use push instead of replace to keep browser history
|
||||||
router.push(`?${url.toString()}`, { scroll: false });
|
router.push(`?${url.toString()}`, { scroll: false });
|
||||||
};
|
};
|
||||||
@@ -139,7 +138,6 @@ export default function Page() {
|
|||||||
height={400}
|
height={400}
|
||||||
fit="cover"
|
fit="cover"
|
||||||
radius="md"
|
radius="md"
|
||||||
style={{ borderBottomRightRadius: 0, borderTopRightRadius: 0 }}
|
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
</GridCol>
|
</GridCol>
|
||||||
@@ -222,6 +220,7 @@ export default function Page() {
|
|||||||
alt={item.judul}
|
alt={item.judul}
|
||||||
fit="cover"
|
fit="cover"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
|
radius={"md"}
|
||||||
/>
|
/>
|
||||||
</Card.Section>
|
</Card.Section>
|
||||||
|
|
||||||
@@ -241,14 +240,17 @@ export default function Page() {
|
|||||||
dangerouslySetInnerHTML={{ __html: item.deskripsiSingkat }}
|
dangerouslySetInnerHTML={{ __html: item.deskripsiSingkat }}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Flex align="center" justify="apart" mt="md" gap="xs">
|
<Group justify="apart" mt="auto">
|
||||||
<Text size="xs" c="dimmed">
|
<Group gap="xs">
|
||||||
{new Date(item.createdAt).toLocaleDateString('id-ID', {
|
<IconCalendar size={18} />
|
||||||
day: 'numeric',
|
<Text size="xs" c="dimmed">
|
||||||
month: 'short',
|
{new Date(item.createdAt).toLocaleDateString('id-ID', {
|
||||||
year: 'numeric',
|
day: 'numeric',
|
||||||
})}
|
month: 'short',
|
||||||
</Text>
|
year: 'numeric',
|
||||||
|
})}
|
||||||
|
</Text>
|
||||||
|
</Group>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
p="xs"
|
p="xs"
|
||||||
@@ -262,7 +264,7 @@ export default function Page() {
|
|||||||
>
|
>
|
||||||
Baca Selengkapnya
|
Baca Selengkapnya
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Group>
|
||||||
</Card>
|
</Card>
|
||||||
))}
|
))}
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
'use client'
|
'use client'
|
||||||
import stateKonservasiAdatBali from '@/app/admin/(dashboard)/_state/lingkungan/konservasi-adat-bali';
|
import stateKonservasiAdatBali from '@/app/admin/(dashboard)/_state/lingkungan/konservasi-adat-bali';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
import { Box, Center, Paper, SimpleGrid, Skeleton, Stack, Text } from '@mantine/core';
|
import { Box, Center, Paper, SimpleGrid, Skeleton, Stack, Text, Title } from '@mantine/core';
|
||||||
import { useShallowEffect } from '@mantine/hooks';
|
import { useShallowEffect } from '@mantine/hooks';
|
||||||
import { useProxy } from 'valtio/utils';
|
import { useProxy } from 'valtio/utils';
|
||||||
import BackButton from '../../desa/layanan/_com/BackButto';
|
import BackButton from '../../desa/layanan/_com/BackButto';
|
||||||
|
|
||||||
|
|
||||||
function Page() {
|
function Page() {
|
||||||
const filosofi = useProxy(stateKonservasiAdatBali.stateFilosofiTriHita.findById)
|
const filosofi = useProxy(stateKonservasiAdatBali.stateFilosofiTriHita.findById)
|
||||||
const nilai = useProxy(stateKonservasiAdatBali.stateNilaiKonservasiAdat.findById)
|
const nilai = useProxy(stateKonservasiAdatBali.stateNilaiKonservasiAdat.findById)
|
||||||
@@ -30,11 +31,24 @@ function Page() {
|
|||||||
<Box px={{ base: 'md', md: 100 }}>
|
<Box px={{ base: 'md', md: 100 }}>
|
||||||
<BackButton />
|
<BackButton />
|
||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: 'md', md: 100 }} pb={30}>
|
<Box px={{ base: 'md', md: 100 }} >
|
||||||
<Text ta="center" fz={{ base: '2xl', md: '3rem' }} c={colors['blue-button']} fw="bold">
|
<Title
|
||||||
|
order={1}
|
||||||
|
ta="center"
|
||||||
|
c={colors['blue-button']}
|
||||||
|
fw="bold"
|
||||||
|
style={{ lineHeight: 1.15 }}
|
||||||
|
|
||||||
|
>
|
||||||
Konservasi Adat Bali
|
Konservasi Adat Bali
|
||||||
</Text>
|
</Title>
|
||||||
<Text px={20} ta="center" fz="lg" c="black">
|
<Text
|
||||||
|
px={20}
|
||||||
|
ta="center"
|
||||||
|
fz={{ base: 'sm', md: 'lg' }}
|
||||||
|
c="black"
|
||||||
|
style={{ lineHeight: 1.55 }}
|
||||||
|
>
|
||||||
Pelestarian lingkungan di Bali yang berpijak pada kearifan lokal, menjaga harmoni antara alam, budaya, dan manusia.
|
Pelestarian lingkungan di Bali yang berpijak pada kearifan lokal, menjaga harmoni antara alam, budaya, dan manusia.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -54,53 +68,31 @@ function Page() {
|
|||||||
>
|
>
|
||||||
<Stack gap="md" px={20} style={{ height: '100%' }}>
|
<Stack gap="md" px={20} style={{ height: '100%' }}>
|
||||||
<Center>
|
<Center>
|
||||||
<Text fz="xl" fw="bold" c="black">
|
<Title
|
||||||
|
order={3}
|
||||||
|
c="black"
|
||||||
|
fw="bold"
|
||||||
|
style={{ lineHeight: 1.15 }}
|
||||||
|
>
|
||||||
{filosofi.data?.judul}
|
{filosofi.data?.judul}
|
||||||
</Text>
|
</Title>
|
||||||
</Center>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
wordBreak: "break-word",
|
|
||||||
whiteSpace: "normal",
|
|
||||||
flexGrow: 1
|
|
||||||
}}
|
|
||||||
dangerouslySetInnerHTML={{ __html: filosofi.data?.deskripsi || '' }}
|
|
||||||
/>
|
|
||||||
</Stack>
|
|
||||||
</Paper>
|
|
||||||
</Box>
|
|
||||||
{/* Nilai */}
|
|
||||||
<Box style={{ display: 'flex', height: '100%' }}>
|
|
||||||
<Paper
|
|
||||||
p="lg"
|
|
||||||
style={{
|
|
||||||
borderRadius: 16,
|
|
||||||
width: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
flexDirection: 'column',
|
|
||||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Stack gap="md" px={20} style={{ height: '100%' }}>
|
|
||||||
<Center>
|
|
||||||
<Text fz="xl" fw="bold" c="black">
|
|
||||||
{nilai.data?.judul}
|
|
||||||
</Text>
|
|
||||||
</Center>
|
</Center>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
wordBreak: "break-word",
|
wordBreak: "break-word",
|
||||||
whiteSpace: "normal",
|
whiteSpace: "normal",
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
minHeight: 0
|
fontSize: '14px',
|
||||||
|
lineHeight: 1.55,
|
||||||
|
color: 'black'
|
||||||
}}
|
}}
|
||||||
dangerouslySetInnerHTML={{ __html: nilai.data?.deskripsi || '' }}
|
dangerouslySetInnerHTML={{ __html: filosofi.data?.deskripsi || '' }}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
{/* Bentuk */}
|
{/* Nilai */}
|
||||||
<Box>
|
<Box style={{ display: 'flex', height: '100%' }}>
|
||||||
<Paper
|
<Paper
|
||||||
p="lg"
|
p="lg"
|
||||||
style={{
|
style={{
|
||||||
@@ -113,26 +105,72 @@ function Page() {
|
|||||||
>
|
>
|
||||||
<Stack gap="md" px={20} style={{ height: '100%' }}>
|
<Stack gap="md" px={20} style={{ height: '100%' }}>
|
||||||
<Center>
|
<Center>
|
||||||
<Text fz="xl" fw="bold" c="black">
|
<Title
|
||||||
{bentuk.data?.judul}
|
order={3}
|
||||||
</Text>
|
c="black"
|
||||||
|
fw="bold"
|
||||||
|
style={{ lineHeight: 1.15 }}
|
||||||
|
>
|
||||||
|
{nilai.data?.judul}
|
||||||
|
</Title>
|
||||||
</Center>
|
</Center>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
wordBreak: "break-word",
|
wordBreak: "break-word",
|
||||||
whiteSpace: "normal",
|
whiteSpace: "normal",
|
||||||
flexGrow: 1,
|
flexGrow: 1,
|
||||||
minHeight: 0
|
minHeight: 0,
|
||||||
|
fontSize: '14px',
|
||||||
|
lineHeight: 1.55,
|
||||||
|
color: 'black'
|
||||||
|
}}
|
||||||
|
dangerouslySetInnerHTML={{ __html: nilai.data?.deskripsi || '' }}
|
||||||
|
/>
|
||||||
|
</Stack>
|
||||||
|
</Paper>
|
||||||
|
</Box>
|
||||||
|
{/* Bentuk */}
|
||||||
|
<Box>
|
||||||
|
<Paper
|
||||||
|
p="lg"
|
||||||
|
style={{
|
||||||
|
borderRadius: 16,
|
||||||
|
width: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.1)'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Stack gap="md" px={20} style={{ height: '100%' }}>
|
||||||
|
<Center>
|
||||||
|
<Title
|
||||||
|
order={3}
|
||||||
|
c="black"
|
||||||
|
fw="bold"
|
||||||
|
style={{ lineHeight: 1.15 }}
|
||||||
|
>
|
||||||
|
{bentuk.data?.judul}
|
||||||
|
</Title>
|
||||||
|
</Center>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
wordBreak: "break-word",
|
||||||
|
whiteSpace: "normal",
|
||||||
|
flexGrow: 1,
|
||||||
|
minHeight: 0,
|
||||||
|
fontSize: '14px',
|
||||||
|
lineHeight: 1.55,
|
||||||
|
color: 'black'
|
||||||
}}
|
}}
|
||||||
dangerouslySetInnerHTML={{ __html: bentuk.data?.deskripsi || '' }}
|
dangerouslySetInnerHTML={{ __html: bentuk.data?.deskripsi || '' }}
|
||||||
/>
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Box>
|
</Box>
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
</Box>
|
</Box>
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
Button,
|
Button,
|
||||||
Container,
|
Container,
|
||||||
Divider,
|
Divider,
|
||||||
|
Flex,
|
||||||
Group,
|
Group,
|
||||||
Modal,
|
Modal,
|
||||||
Paper,
|
Paper,
|
||||||
@@ -23,11 +24,11 @@ import { useProxy } from 'valtio/utils';
|
|||||||
import beasiswaDesaState from '@/app/admin/(dashboard)/_state/pendidikan/beasiswa-desa';
|
import beasiswaDesaState from '@/app/admin/(dashboard)/_state/pendidikan/beasiswa-desa';
|
||||||
import colors from '@/con/colors';
|
import colors from '@/con/colors';
|
||||||
|
|
||||||
|
|
||||||
export default function BeasiswaPage() {
|
export default function BeasiswaPage() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const beasiswaDesa = useProxy(beasiswaDesaState.beasiswaPendaftar)
|
const beasiswaDesa = useProxy(beasiswaDesaState.beasiswaPendaftar);
|
||||||
const [opened, { open, close }] = useDisclosure(false);
|
const [opened, { open, close }] = useDisclosure(false);
|
||||||
|
|
||||||
const resetForm = () => {
|
const resetForm = () => {
|
||||||
beasiswaDesa.create.form = {
|
beasiswaDesa.create.form = {
|
||||||
namaLengkap: "",
|
namaLengkap: "",
|
||||||
@@ -61,6 +62,7 @@ export default function BeasiswaPage() {
|
|||||||
leftSection={<IconArrowLeft size={18} />}
|
leftSection={<IconArrowLeft size={18} />}
|
||||||
onClick={() => router.back()}
|
onClick={() => router.back()}
|
||||||
mb="lg"
|
mb="lg"
|
||||||
|
style={{ fontSize: '1rem', fontWeight: 500 }}
|
||||||
>
|
>
|
||||||
Kembali
|
Kembali
|
||||||
</Button>
|
</Button>
|
||||||
@@ -69,11 +71,18 @@ export default function BeasiswaPage() {
|
|||||||
{/* Hero Section */}
|
{/* Hero Section */}
|
||||||
<Container size="lg" py="xl">
|
<Container size="lg" py="xl">
|
||||||
<Stack gap="md" maw={600}>
|
<Stack gap="md" maw={600}>
|
||||||
<Group>
|
<Flex gap={"md"} justify={"flex-start"} align={"center"}>
|
||||||
<IconSchool size={30} color={colors["blue-button"]} />
|
<IconSchool size={30} color={colors["blue-button"]} />
|
||||||
<Title order={2} c={colors["blue-button"]}>Program Beasiswa Pendidikan Desa Darmasaba</Title>
|
<Title
|
||||||
</Group>
|
order={1}
|
||||||
<Text>
|
fz={{ base: '1.125rem', md: '1.375rem' }}
|
||||||
|
lh={1.15}
|
||||||
|
c={colors["blue-button"]}
|
||||||
|
>
|
||||||
|
Program Beasiswa Pendidikan Desa Darmasaba
|
||||||
|
</Title>
|
||||||
|
</Flex>
|
||||||
|
<Text fz={{ base: '0.875rem', md: '1rem' }} lh={1.55}>
|
||||||
Program ini bertujuan untuk mendukung pendidikan generasi muda di Desa Darmasaba
|
Program ini bertujuan untuk mendukung pendidikan generasi muda di Desa Darmasaba
|
||||||
agar dapat melanjutkan studi ke jenjang lebih tinggi dengan dukungan finansial dan pendampingan.
|
agar dapat melanjutkan studi ke jenjang lebih tinggi dengan dukungan finansial dan pendampingan.
|
||||||
</Text>
|
</Text>
|
||||||
@@ -84,20 +93,22 @@ export default function BeasiswaPage() {
|
|||||||
<Container size="lg" py="xl">
|
<Container size="lg" py="xl">
|
||||||
<Group mb="sm">
|
<Group mb="sm">
|
||||||
<IconInfoCircle size={24} color={colors["blue-button"]} />
|
<IconInfoCircle size={24} color={colors["blue-button"]} />
|
||||||
<Title order={3} c={colors["blue-button"]}>Tentang Program</Title>
|
<Title order={3} fz={{ base: '1.125rem', md: '1.375rem' }} lh={1.15} c={colors["blue-button"]}>
|
||||||
|
Tentang Program
|
||||||
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
<Text>
|
<Text fz={{ base: '0.875rem', md: '1rem' }} lh={1.55}>
|
||||||
Program Beasiswa Desa Darmasaba adalah inisiatif pemerintah desa untuk meningkatkan akses
|
Program Beasiswa Desa Darmasaba adalah inisiatif pemerintah desa untuk meningkatkan akses
|
||||||
pendidikan bagi siswa berprestasi dan kurang mampu. Melalui program ini, desa memberikan bantuan
|
pendidikan bagi siswa berprestasi dan kurang mampu. Melalui program ini, desa memberikan bantuan
|
||||||
biaya sekolah, bimbingan akademik, serta pelatihan soft skill bagi peserta terpilih.
|
biaya sekolah, bimbingan akademik, serta pelatihan soft skill bagi peserta terpilih.
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
{/* Tambahkan info tahun berjalan di sini */}
|
{/* Periode Beasiswa */}
|
||||||
<Paper mt="md" p="md" radius="lg" shadow="xs" bg="#f8fbff" withBorder>
|
<Paper mt="md" p="md" radius="lg" shadow="xs" bg="#f8fbff" withBorder>
|
||||||
<Text fw={500}>
|
<Text fz={{ base: '1rem', md: '1.125rem' }} fw={600} lh={1.4}>
|
||||||
Periode Beasiswa Tahun 2025
|
Periode Beasiswa Tahun 2025
|
||||||
</Text>
|
</Text>
|
||||||
<Text fz="sm" c="dimmed">
|
<Text fz={{ base: '0.8125rem', md: '0.875rem' }} c="dimmed" lh={1.5}>
|
||||||
Pendaftaran beasiswa dibuka mulai <strong>1 Januari 2025</strong> dan ditutup pada <strong>31 Mei 2025</strong>.
|
Pendaftaran beasiswa dibuka mulai <strong>1 Januari 2025</strong> dan ditutup pada <strong>31 Mei 2025</strong>.
|
||||||
Pengumuman hasil seleksi akan diumumkan pada pertengahan Juni 2025 melalui website resmi Desa Darmasaba.
|
Pengumuman hasil seleksi akan diumumkan pada pertengahan Juni 2025 melalui website resmi Desa Darmasaba.
|
||||||
</Text>
|
</Text>
|
||||||
@@ -108,27 +119,35 @@ export default function BeasiswaPage() {
|
|||||||
<Container size="lg" py="xl">
|
<Container size="lg" py="xl">
|
||||||
<Group mb="sm">
|
<Group mb="sm">
|
||||||
<IconChecklist size={24} color={colors["blue-button"]} />
|
<IconChecklist size={24} color={colors["blue-button"]} />
|
||||||
<Title order={3} c={colors["blue-button"]}>Syarat Pendaftaran</Title>
|
<Title order={3} fz={{ base: '1.125rem', md: '1.375rem' }} lh={1.15} c={colors["blue-button"]}>
|
||||||
|
Syarat Pendaftaran
|
||||||
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg">
|
<SimpleGrid cols={{ base: 1, sm: 2, md: 3 }} spacing="lg">
|
||||||
<Paper shadow="sm" p="md" radius="lg" withBorder>
|
<Paper shadow="sm" p="md" radius="lg" withBorder>
|
||||||
<Text fw={500}>Domisili Desa Darmasaba</Text>
|
<Text fz={{ base: '1rem', md: '1.125rem' }} fw={600} lh={1.4}>
|
||||||
<Text c="dimmed" fz="sm">
|
Domisili Desa Darmasaba
|
||||||
|
</Text>
|
||||||
|
<Text c="dimmed" fz={{ base: '0.8125rem', md: '0.875rem' }} lh={1.5}>
|
||||||
Peserta harus merupakan warga desa yang berdomisili minimal 2 tahun.
|
Peserta harus merupakan warga desa yang berdomisili minimal 2 tahun.
|
||||||
</Text>
|
</Text>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
<Paper shadow="sm" p="md" radius="lg" withBorder>
|
<Paper shadow="sm" p="md" radius="lg" withBorder>
|
||||||
<Text fw={500}>Nilai Akademik</Text>
|
<Text fz={{ base: '1rem', md: '1.125rem' }} fw={600} lh={1.4}>
|
||||||
<Text c="dimmed" fz="sm">
|
Nilai Akademik
|
||||||
|
</Text>
|
||||||
|
<Text c="dimmed" fz={{ base: '0.8125rem', md: '0.875rem' }} lh={1.5}>
|
||||||
Rata-rata nilai raport minimal 80 atau setara.
|
Rata-rata nilai raport minimal 80 atau setara.
|
||||||
</Text>
|
</Text>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
<Paper shadow="sm" p="md" radius="lg" withBorder>
|
<Paper shadow="sm" p="md" radius="lg" withBorder>
|
||||||
<Text fw={500}>Surat Rekomendasi</Text>
|
<Text fz={{ base: '1rem', md: '1.125rem' }} fw={600} lh={1.4}>
|
||||||
<Text c="dimmed" fz="sm">
|
Surat Rekomendasi
|
||||||
|
</Text>
|
||||||
|
<Text c="dimmed" fz={{ base: '0.8125rem', md: '0.875rem' }} lh={1.5}>
|
||||||
Diperlukan surat rekomendasi dari sekolah atau guru wali kelas.
|
Diperlukan surat rekomendasi dari sekolah atau guru wali kelas.
|
||||||
</Text>
|
</Text>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -139,75 +158,102 @@ export default function BeasiswaPage() {
|
|||||||
<Container size="lg" py="xl">
|
<Container size="lg" py="xl">
|
||||||
<Group mb="sm">
|
<Group mb="sm">
|
||||||
<IconTimeline size={24} color={colors["blue-button"]} />
|
<IconTimeline size={24} color={colors["blue-button"]} />
|
||||||
<Title order={3} c={colors["blue-button"]}>Proses Seleksi</Title>
|
<Title order={3} fz={{ base: '1.125rem', md: '1.375rem' }} lh={1.15} c={colors["blue-button"]}>
|
||||||
|
Proses Seleksi
|
||||||
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Timeline active={4} bulletSize={24} lineWidth={2}>
|
<Timeline active={4} bulletSize={24} lineWidth={2}>
|
||||||
<Timeline.Item title="Pendaftaran Online">
|
<Timeline.Item
|
||||||
<Text c="dimmed" size="sm">
|
title={
|
||||||
|
<Text fz={{ base: '1rem', md: '1.125rem' }} fw={600} lh={1.4}>
|
||||||
|
Pendaftaran Online
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text c="dimmed" fz={{ base: '0.8125rem', md: '0.875rem' }} lh={1.5}>
|
||||||
Calon peserta mengisi formulir pendaftaran dan mengunggah dokumen pendukung.
|
Calon peserta mengisi formulir pendaftaran dan mengunggah dokumen pendukung.
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" fw={500} mt={4}>
|
<Text fz={{ base: '0.8125rem', md: '0.875rem' }} fw={600} mt={4} lh={1.4}>
|
||||||
Estimasi waktu: 1 Februari – 31 Mei 2025
|
Estimasi waktu: 1 Februari – 31 Mei 2025
|
||||||
</Text>
|
</Text>
|
||||||
</Timeline.Item>
|
</Timeline.Item>
|
||||||
|
|
||||||
<Timeline.Item title="Seleksi Administrasi">
|
<Timeline.Item
|
||||||
<Text c="dimmed" size="sm">
|
title={
|
||||||
|
<Text fz={{ base: '1rem', md: '1.125rem' }} fw={600} lh={1.4}>
|
||||||
|
Seleksi Administrasi
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text c="dimmed" fz={{ base: '0.8125rem', md: '0.875rem' }} lh={1.5}>
|
||||||
Panitia memverifikasi kelengkapan dan validitas berkas.
|
Panitia memverifikasi kelengkapan dan validitas berkas.
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" fw={500} mt={4}>
|
<Text fz={{ base: '0.8125rem', md: '0.875rem' }} fw={600} mt={4} lh={1.4}>
|
||||||
Estimasi waktu: 5–7 hari kerja setelah penutupan pendaftaran
|
Estimasi waktu: 5–7 hari kerja setelah penutupan pendaftaran
|
||||||
</Text>
|
</Text>
|
||||||
</Timeline.Item>
|
</Timeline.Item>
|
||||||
|
|
||||||
<Timeline.Item title="Wawancara dan Penilaian">
|
<Timeline.Item
|
||||||
<Text c="dimmed" size="sm">
|
title={
|
||||||
|
<Text fz={{ base: '1rem', md: '1.125rem' }} fw={600} lh={1.4}>
|
||||||
|
Wawancara dan Penilaian
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text c="dimmed" fz={{ base: '0.8125rem', md: '0.875rem' }} lh={1.5}>
|
||||||
Peserta yang lolos administrasi akan diundang untuk wawancara langsung dengan tim seleksi.
|
Peserta yang lolos administrasi akan diundang untuk wawancara langsung dengan tim seleksi.
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" fw={500} mt={4}>
|
<Text fz={{ base: '0.8125rem', md: '0.875rem' }} fw={600} mt={4} lh={1.4}>
|
||||||
Estimasi waktu: 7–10 hari kerja setelah pengumuman seleksi administrasi
|
Estimasi waktu: 7–10 hari kerja setelah pengumuman seleksi administrasi
|
||||||
</Text>
|
</Text>
|
||||||
</Timeline.Item>
|
</Timeline.Item>
|
||||||
|
|
||||||
<Timeline.Item title="Pengumuman Penerima">
|
<Timeline.Item
|
||||||
<Text c="dimmed" size="sm">
|
title={
|
||||||
|
<Text fz={{ base: '1rem', md: '1.125rem' }} fw={600} lh={1.4}>
|
||||||
|
Pengumuman Penerima
|
||||||
|
</Text>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Text c="dimmed" fz={{ base: '0.8125rem', md: '0.875rem' }} lh={1.5}>
|
||||||
Daftar penerima beasiswa diumumkan melalui website resmi Desa Darmasaba.
|
Daftar penerima beasiswa diumumkan melalui website resmi Desa Darmasaba.
|
||||||
</Text>
|
</Text>
|
||||||
<Text size="sm" fw={500} mt={4}>
|
<Text fz={{ base: '0.8125rem', md: '0.875rem' }} fw={600} mt={4} lh={1.4}>
|
||||||
Estimasi waktu: 5 hari kerja setelah tahap wawancara selesai
|
Estimasi waktu: 5 hari kerja setelah tahap wawancara selesai
|
||||||
</Text>
|
</Text>
|
||||||
</Timeline.Item>
|
</Timeline.Item>
|
||||||
</Timeline>
|
</Timeline>
|
||||||
|
|
||||||
<Text c="dimmed" size="sm" mt="lg" ta="center">
|
<Text c="dimmed" fz={{ base: '0.8125rem', md: '0.875rem' }} lh={1.5} mt="lg" ta="center">
|
||||||
Total estimasi keseluruhan proses: sekitar 3–4 minggu setelah penutupan pendaftaran
|
Total estimasi keseluruhan proses: sekitar 3–4 minggu setelah penutupan pendaftaran
|
||||||
</Text>
|
</Text>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
|
||||||
{/* Testimoni */}
|
{/* Testimoni */}
|
||||||
<Container size="lg" py="xl">
|
<Container size="lg" py="xl">
|
||||||
<Group mb="sm">
|
<Group mb="sm">
|
||||||
<IconQuote size={24} color={colors["blue-button"]} />
|
<IconQuote size={24} color={colors["blue-button"]} />
|
||||||
<Title order={3} c={colors["blue-button"]}>Cerita Sukses Penerima Beasiswa</Title>
|
<Title order={3} fz={{ base: '1.125rem', md: '1.375rem' }} lh={1.15} c={colors["blue-button"]}>
|
||||||
|
Cerita Sukses Penerima Beasiswa
|
||||||
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="lg">
|
<SimpleGrid cols={{ base: 1, sm: 2 }} spacing="lg">
|
||||||
<Paper shadow="md" p="lg" radius="lg">
|
<Paper shadow="md" p="lg" radius="lg">
|
||||||
<Text fs={'italic'}>
|
<Text fs="italic" fz={{ base: '0.9375rem', md: '1rem' }} lh={1.5}>
|
||||||
“Program ini sangat membantu saya melanjutkan kuliah di Universitas Udayana. Terima kasih Desa Darmasaba!”
|
“Program ini sangat membantu saya melanjutkan kuliah di Universitas Udayana. Terima kasih Desa Darmasaba!”
|
||||||
</Text>
|
</Text>
|
||||||
<Text mt="sm" fw={600}>
|
<Text mt="sm" fw={600} fz={{ base: '0.9375rem', md: '1rem' }} lh={1.4}>
|
||||||
– Ni Kadek Ayu S., Penerima Beasiswa 2024
|
– Ni Kadek Ayu S., Penerima Beasiswa 2024
|
||||||
</Text>
|
</Text>
|
||||||
</Paper>
|
</Paper>
|
||||||
|
|
||||||
<Paper shadow="md" p="lg" radius="lg">
|
<Paper shadow="md" p="lg" radius="lg">
|
||||||
<Text fs={'italic'}>
|
<Text fs="italic" fz={{ base: '0.9375rem', md: '1rem' }} lh={1.5}>
|
||||||
“Selain bantuan dana, kami juga mendapatkan pelatihan komputer dan bahasa Inggris.”
|
“Selain bantuan dana, kami juga mendapatkan pelatihan komputer dan bahasa Inggris.”
|
||||||
</Text>
|
</Text>
|
||||||
<Text mt="sm" fw={600}>
|
<Text mt="sm" fw={600} fz={{ base: '0.9375rem', md: '1rem' }} lh={1.4}>
|
||||||
– I Made Gede A., Penerima Beasiswa 2023
|
– I Made Gede A., Penerima Beasiswa 2023
|
||||||
</Text>
|
</Text>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -218,16 +264,25 @@ export default function BeasiswaPage() {
|
|||||||
<Container size="lg" py="xl" ta="center">
|
<Container size="lg" py="xl" ta="center">
|
||||||
<Group justify="center" mb="sm">
|
<Group justify="center" mb="sm">
|
||||||
<IconUserPlus size={28} color={colors["blue-button"]} />
|
<IconUserPlus size={28} color={colors["blue-button"]} />
|
||||||
<Title order={3} c={colors["blue-button"]}>Siap Bergabung dengan Program Ini?</Title>
|
<Title order={3} fz={{ base: '1.375rem', md: '1.5rem' }} lh={1.15} c={colors["blue-button"]}>
|
||||||
|
Siap Bergabung dengan Program Ini?
|
||||||
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
<Text c="dimmed" mb="md">
|
<Text c="dimmed" fz={{ base: '0.875rem', md: '1rem' }} lh={1.5} mb="md">
|
||||||
Segera daftar dan wujudkan mimpimu bersama Desa Darmasaba.
|
Segera daftar dan wujudkan mimpimu bersama Desa Darmasaba.
|
||||||
</Text>
|
</Text>
|
||||||
<Button onClick={open} size="lg" radius="xl" bg={colors["blue-button"]}>
|
<Button
|
||||||
|
onClick={open}
|
||||||
|
size="lg"
|
||||||
|
radius="xl"
|
||||||
|
bg={colors["blue-button"]}
|
||||||
|
style={{ fontSize: '1.125rem', fontWeight: 600, lineHeight: 1.4 }}
|
||||||
|
>
|
||||||
Daftar Sekarang
|
Daftar Sekarang
|
||||||
</Button>
|
</Button>
|
||||||
</Container>
|
</Container>
|
||||||
|
|
||||||
|
{/* Modal Formulir */}
|
||||||
<Modal
|
<Modal
|
||||||
opened={opened}
|
opened={opened}
|
||||||
onClose={close}
|
onClose={close}
|
||||||
@@ -235,7 +290,7 @@ export default function BeasiswaPage() {
|
|||||||
size="lg"
|
size="lg"
|
||||||
transitionProps={{ transition: 'fade', duration: 200 }}
|
transitionProps={{ transition: 'fade', duration: 200 }}
|
||||||
title={
|
title={
|
||||||
<Text fz="xl" fw={800} c={colors['blue-button']}>
|
<Text fz={{ base: '1.375rem', md: '1.5rem' }} fw={800} c={colors['blue-button']} lh={1.2}>
|
||||||
Formulir Beasiswa
|
Formulir Beasiswa
|
||||||
</Text>
|
</Text>
|
||||||
}
|
}
|
||||||
@@ -245,64 +300,105 @@ export default function BeasiswaPage() {
|
|||||||
<TextInput
|
<TextInput
|
||||||
label="Nama Lengkap"
|
label="Nama Lengkap"
|
||||||
placeholder="Masukkan nama lengkap"
|
placeholder="Masukkan nama lengkap"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.namaLengkap = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.namaLengkap = val.target.value }}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
type="number"
|
type="number"
|
||||||
label="NIS"
|
label="NIS"
|
||||||
placeholder="Masukkan NIS"
|
placeholder="Masukkan NIS"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.nis = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.nis = val.target.value }}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Kelas"
|
label="Kelas"
|
||||||
placeholder="Masukkan kelas"
|
placeholder="Masukkan kelas"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.kelas = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.kelas = val.target.value }}
|
||||||
|
/>
|
||||||
<Select
|
<Select
|
||||||
label="Jenis Kelamin"
|
label="Jenis Kelamin"
|
||||||
placeholder="Pilih jenis kelamin"
|
placeholder="Pilih jenis kelamin"
|
||||||
data={[{ value: "LAKI_LAKI", label: "Laki-laki" }, { value: "PEREMPUAN", label: "Perempuan" }]}
|
data={[
|
||||||
onChange={(val) => { if (val) beasiswaDesa.create.form.jenisKelamin = val }} />
|
{ value: "LAKI_LAKI", label: "Laki-laki" },
|
||||||
|
{ value: "PEREMPUAN", label: "Perempuan" }
|
||||||
|
]}
|
||||||
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { if (val) beasiswaDesa.create.form.jenisKelamin = val }}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Alamat Domisili"
|
label="Alamat Domisili"
|
||||||
placeholder="Masukkan alamat domisili"
|
placeholder="Masukkan alamat domisili"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.alamatDomisili = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.alamatDomisili = val.target.value }}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Tempat Lahir"
|
label="Tempat Lahir"
|
||||||
placeholder="Masukkan tempat lahir"
|
placeholder="Masukkan tempat lahir"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.tempatLahir = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.tempatLahir = val.target.value }}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
type="date"
|
type="date"
|
||||||
label="Tanggal Lahir"
|
label="Tanggal Lahir"
|
||||||
placeholder="Pilih tanggal lahir"
|
placeholder="Pilih tanggal lahir"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.tanggalLahir = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.tanggalLahir = val.target.value }}
|
||||||
|
/>
|
||||||
<Box pt={15} pb={10}>
|
<Box pt={15} pb={10}>
|
||||||
<Divider />
|
<Divider />
|
||||||
</Box>
|
</Box>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Nama Orang Tua / Wali"
|
label="Nama Orang Tua / Wali"
|
||||||
placeholder="Masukkan nama orang tua / wali"
|
placeholder="Masukkan nama orang tua / wali"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.namaOrtu = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.namaOrtu = val.target.value }}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="NIK Orang Tua / Wali"
|
label="NIK Orang Tua / Wali"
|
||||||
placeholder="Masukkan NIK orang tua / wali"
|
placeholder="Masukkan NIK orang tua / wali"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.nik = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.nik = val.target.value }}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Pekerjaan Orang Tua / Wali"
|
label="Pekerjaan Orang Tua / Wali"
|
||||||
placeholder="Masukkan pekerjaan orang tua / wali"
|
placeholder="Masukkan pekerjaan orang tua / wali"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.pekerjaanOrtu = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.pekerjaanOrtu = val.target.value }}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="Penghasilan Orang Tua / Wali"
|
label="Penghasilan Orang Tua / Wali"
|
||||||
placeholder="Masukkan penghasilan orang tua / wali"
|
placeholder="Masukkan penghasilan orang tua / wali"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.penghasilan = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.penghasilan = val.target.value }}
|
||||||
|
/>
|
||||||
<TextInput
|
<TextInput
|
||||||
label="No HP"
|
label="No HP"
|
||||||
placeholder="Masukkan no hp"
|
placeholder="Masukkan no hp"
|
||||||
onChange={(val) => { beasiswaDesa.create.form.noHp = val.target.value }} />
|
labelProps={{ style: { fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 } }}
|
||||||
|
onChange={(val) => { beasiswaDesa.create.form.noHp = val.target.value }}
|
||||||
|
/>
|
||||||
<Group justify="flex-end" mt="md">
|
<Group justify="flex-end" mt="md">
|
||||||
<Button variant="default" radius="xl" onClick={close}>Batal</Button>
|
<Button
|
||||||
<Button radius="xl" bg={colors['blue-button']} onClick={handleSubmit}>Kirim</Button>
|
variant="default"
|
||||||
|
radius="xl"
|
||||||
|
onClick={close}
|
||||||
|
style={{ fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 }}
|
||||||
|
>
|
||||||
|
Batal
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
radius="xl"
|
||||||
|
bg={colors['blue-button']}
|
||||||
|
onClick={handleSubmit}
|
||||||
|
style={{ fontSize: '0.9375rem', fontWeight: 600, lineHeight: 1.4 }}
|
||||||
|
>
|
||||||
|
Kirim
|
||||||
|
</Button>
|
||||||
</Group>
|
</Group>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</Modal>
|
</Modal>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -38,11 +38,17 @@ function Page() {
|
|||||||
</Box>
|
</Box>
|
||||||
<Box px={{ base: 'md', md: 120 }} pb={80}>
|
<Box px={{ base: 'md', md: 120 }} pb={80}>
|
||||||
<Box mb="lg">
|
<Box mb="lg">
|
||||||
<Title ta="center" order={1} fw="bold" c={colors['blue-button']} fz={{ base: 28, md: 38 }}>
|
<Title ta="center" order={1} fw="bold" c={colors['blue-button']} fz={{ base: 'xl', md: '2em' }} lh={1.15}>
|
||||||
Program Bimbingan Belajar Desa
|
Program Bimbingan Belajar Desa
|
||||||
</Title>
|
</Title>
|
||||||
<Divider size="sm" my="md" mx="auto" w="60%" color={colors['blue-button']} />
|
<Divider size="sm" my="md" mx="auto" w="60%" color={colors['blue-button']} />
|
||||||
<Text ta="center" fz="lg" c="black" px={{ base: 'sm', md: 120 }}>
|
<Text
|
||||||
|
ta="center"
|
||||||
|
fz={{ base: 'sm', md: 'md' }}
|
||||||
|
c="black"
|
||||||
|
lh={{ base: 1.6, md: 1.5 }}
|
||||||
|
px={{ base: 'sm', md: 120 }}
|
||||||
|
>
|
||||||
Program unggulan untuk mendukung siswa Desa Darmasaba memahami pelajaran sekolah, meningkatkan prestasi akademik, dan menumbuhkan semangat belajar sejak dini.
|
Program unggulan untuk mendukung siswa Desa Darmasaba memahami pelajaran sekolah, meningkatkan prestasi akademik, dan menumbuhkan semangat belajar sejak dini.
|
||||||
</Text>
|
</Text>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -55,11 +61,16 @@ function Page() {
|
|||||||
<IconBook2 size={36} stroke={1.5} color={colors['blue-button']} />
|
<IconBook2 size={36} stroke={1.5} color={colors['blue-button']} />
|
||||||
</Box>
|
</Box>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Title order={3} fw={700} c={colors['blue-button']} mb="xs">
|
<Title order={3} fw={700} c={colors['blue-button']} lh={1.2} fz={{ base: 'sm', md: 'md' }}>
|
||||||
{stateTujuanProgram.findById.data?.judul}
|
{stateTujuanProgram.findById.data?.judul}
|
||||||
</Title>
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
<Text fz="md" style={{wordBreak: "break-word", whiteSpace: "normal"}} lh={1.6} dangerouslySetInnerHTML={{ __html: stateTujuanProgram.findById.data?.deskripsi }} />
|
<Text
|
||||||
|
fz={{ base: 'xs', md: 'md' }}
|
||||||
|
lh={{ base: 1.6, md: 1.5 }}
|
||||||
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: stateTujuanProgram.findById.data?.deskripsi }}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
<Paper p="xl" radius="lg" shadow="md" withBorder bg={colors['white-trans-1']}>
|
<Paper p="xl" radius="lg" shadow="md" withBorder bg={colors['white-trans-1']}>
|
||||||
@@ -70,11 +81,16 @@ function Page() {
|
|||||||
<IconMapPin size={36} stroke={1.5} color={colors['blue-button']} />
|
<IconMapPin size={36} stroke={1.5} color={colors['blue-button']} />
|
||||||
</Box>
|
</Box>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Title order={3} fw={700} c={colors['blue-button']} mb="xs">
|
<Title order={3} fw={700} c={colors['blue-button']} lh={1.2} fz={{ base: 'sm', md: 'md' }}>
|
||||||
{stateLokasiDanJadwal.findById.data?.judul}
|
{stateLokasiDanJadwal.findById.data?.judul}
|
||||||
</Title>
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
<Text fz="md" lh={1.6} style={{wordBreak: "break-word", whiteSpace: "normal"}} dangerouslySetInnerHTML={{ __html: stateLokasiDanJadwal.findById.data?.deskripsi }} />
|
<Text
|
||||||
|
fz={{ base: 'xs', md: 'md' }}
|
||||||
|
lh={{ base: 1.6, md: 1.5 }}
|
||||||
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: stateLokasiDanJadwal.findById.data?.deskripsi }}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
<Paper p="xl" radius="lg" shadow="md" withBorder bg={colors['white-trans-1']}>
|
<Paper p="xl" radius="lg" shadow="md" withBorder bg={colors['white-trans-1']}>
|
||||||
@@ -85,11 +101,16 @@ function Page() {
|
|||||||
<IconCalendarTime size={36} stroke={1.5} color={colors['blue-button']} />
|
<IconCalendarTime size={36} stroke={1.5} color={colors['blue-button']} />
|
||||||
</Box>
|
</Box>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
<Title order={3} fw={700} c={colors['blue-button']} mb="xs">
|
<Title order={3} fw={700} c={colors['blue-button']} lh={1.2} fz={{ base: 'sm', md: 'md' }}>
|
||||||
{stateFasilitas.findById.data?.judul}
|
{stateFasilitas.findById.data?.judul}
|
||||||
</Title>
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
<Text fz="md" lh={1.6} style={{wordBreak: "break-word", whiteSpace: "normal"}} dangerouslySetInnerHTML={{ __html: stateFasilitas.findById.data?.deskripsi }} />
|
<Text
|
||||||
|
fz={{ base: 'xs', md: 'md' }}
|
||||||
|
lh={{ base: 1.6, md: 1.5 }}
|
||||||
|
style={{ wordBreak: 'break-word', whiteSpace: 'normal' }}
|
||||||
|
dangerouslySetInnerHTML={{ __html: stateFasilitas.findById.data?.deskripsi }}
|
||||||
|
/>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Paper>
|
</Paper>
|
||||||
</SimpleGrid>
|
</SimpleGrid>
|
||||||
@@ -98,4 +119,4 @@ function Page() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Page;
|
export default Page;
|
||||||
Reference in New Issue
Block a user