Fix QC Kak Inno Mobile Done

FIx QC Kak Ayu Mobile Admin Done
Fix Tampilan Admin Mobile Device All Menu Done
This commit is contained in:
2026-01-02 16:33:15 +08:00
parent 50bc54ceca
commit f436aa2ef0
117 changed files with 3812 additions and 1361 deletions

View File

@@ -129,7 +129,7 @@ function EditProgramPenghijauan() {
};
return (
<Box px={{ base: 'sm', md: 'lg' }} py="md">
<Box px={{ base: 0, md: 'lg' }} py="xs">
{/* Header */}
<Group mb="md">
<Button

View File

@@ -79,7 +79,7 @@ function DetailProgramPenghijauan() {
const data = stateProgramPenghijauan.findUnique.data
return (
<Box py={10}>
<Box px={{ base: 0, md: 'lg' }} py="xs">
{/* Tombol kembali */}
<Button
variant="subtle"
@@ -93,7 +93,7 @@ function DetailProgramPenghijauan() {
{/* Konten detail */}
<Paper
withBorder
w={{ base: "100%", md: "60%" }}
w={{ base: "100%", md: "70%" }}
bg={colors['white-1']}
p="lg"
radius="md"
@@ -129,7 +129,9 @@ function DetailProgramPenghijauan() {
<Box>
<Text fz="lg" fw="bold">Deskripsi</Text>
<Text fz="md" c="dimmed" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: data?.deskripsi || '-' }} />
<Box pl={5}>
<Text fz="md" c="dimmed" style={{ wordBreak: "break-word", whiteSpace: "normal" }} dangerouslySetInnerHTML={{ __html: data?.deskripsi || '-' }} />
</Box>
</Box>
{/* Tombol aksi */}

View File

@@ -49,7 +49,7 @@ function CreateProgramPenghijauan() {
};
return (
<Box px={{ base: 'sm', md: 'lg' }} py="md">
<Box px={{ base: 0, md: 'lg' }} py="xs">
{/* Tombol back + title */}
<Group mb="md">
<Button

View File

@@ -6,6 +6,7 @@ import {
Box,
Button,
Center,
Group,
Pagination,
Paper,
Skeleton,
@@ -17,22 +18,33 @@ import {
TableThead,
TableTr,
Text,
Title
Title,
} from '@mantine/core';
import {
IconAlertTriangle,
IconAmbulance,
IconBuilding,
IconCash,
IconChartLine,
IconChristmasTreeFilled,
IconClipboardTextFilled,
IconDeviceImac,
IconDroplet,
IconFiretruck,
IconHome,
IconHomeEco,
IconHospital,
IconLeaf,
IconPlus,
IconRecycle,
IconScale,
IconSchool,
IconSearch,
IconShieldFilled,
IconShoppingCart,
IconTent,
IconTrashFilled,
IconTree,
IconTrendingUp,
IconTrophy,
IconTruckFilled,
@@ -42,9 +54,10 @@ import React, { useEffect, useState } from 'react';
import { useProxy } from 'valtio/utils';
import HeaderSearch from '../../_com/header';
import programPenghijauanState from '../../_state/lingkungan/program-penghijauan';
import { useDebouncedValue } from '@mantine/hooks';
function ProgramPenghijauan() {
const [search, setSearch] = useState("");
const [search, setSearch] = useState('');
return (
<Box>
<HeaderSearch
@@ -60,15 +73,16 @@ function ProgramPenghijauan() {
}
function ListProgramPenghijauan({ search }: { search: string }) {
const listState = useProxy(programPenghijauanState)
const { data, loading, page, totalPages, load } = listState.findMany
const listState = useProxy(programPenghijauanState);
const { data, loading, page, totalPages, load } = listState.findMany;
const router = useRouter();
const [debouncedSearch] = useDebouncedValue(search, 1000);
useEffect(() => {
load(page, 10, search)
}, [page, search])
load(page, 10, debouncedSearch);
}, [page, debouncedSearch]);
const filteredData = data || []
const filteredData = data || [];
const iconMap: Record<string, React.FC<any>> = {
ekowisata: IconLeaf,
@@ -84,87 +98,244 @@ function ListProgramPenghijauan({ search }: { search: string }) {
sumberOksigen: IconChristmasTreeFilled,
ekonomiBerkelanjutan: IconTrendingUp,
mencegahBencana: IconShieldFilled,
rumah: IconHome,
pohon: IconTree,
air: IconDroplet,
bantuan: IconCash,
pelatihan: IconSchool,
subsidi: IconShoppingCart,
layananKesehatan: IconHospital,
polisi: IconShieldFilled,
ambulans: IconAmbulance,
pemadam: IconFiretruck,
rumahSakit: IconHospital,
bangunan: IconBuilding,
darurat: IconAlertTriangle,
};
if (loading || !data) {
return (
<Stack py={10}>
<Stack py="md">
<Skeleton height={600} radius="md" />
</Stack>
);
}
return (
<Box py={10}>
<Box py="md">
<Paper withBorder bg={colors['white-1']} p="lg" shadow="md" radius="md">
{/* Header Section */}
<Box mb="md" display="flex" style={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Title order={4}>Daftar Program Penghijauan</Title>
<Box mb="lg" visibleFrom="md">
<Group
justify="space-between"
align="center"
mb="md"
>
<Title order={4} size="md" lh={1.2}>
Daftar Program Penghijauan
</Title>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() =>
router.push('/admin/lingkungan/program-penghijauan/create')
}
>
Tambah Baru
</Button>
</Group>
{/* Desktop Table */}
<Box miw={0}>
<Table
highlightOnHover
miw={0}
style={{ tableLayout: 'fixed', width: '100%' }}
>
<TableThead>
<TableTr>
<TableTh style={{ width: '5%', textAlign: 'center' }}>
<Text fz="xs" fw={600} lh={1.4} ta="center">
No
</Text>
</TableTh>
<TableTh style={{ width: '25%' }}>
<Text fz="xs" fw={600} lh={1.4}>
Nama Program
</Text>
</TableTh>
<TableTh style={{ width: '35%' }}>
<Text fz="xs" fw={600} lh={1.4}>
Judul / Deskripsi
</Text>
</TableTh>
<TableTh style={{ width: '15%', textAlign: 'center' }}>
<Text fz="xs" fw={600} lh={1.4} ta="center">
Ikon
</Text>
</TableTh>
<TableTh style={{ width: '20%', textAlign: 'center' }}>
<Text fz="xs" fw={600} lh={1.4} ta="center">
Aksi
</Text>
</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{filteredData.length > 0 ? (
filteredData.map((item, index) => (
<TableTr key={item.id}>
<TableTd ta="center">
<Text fz="sm" fw={500} lh={1.5}>
{index + 1}
</Text>
</TableTd>
<TableTd>
<Text fz="sm" fw={500} lh={1.5} truncate="end">
{item.name}
</Text>
</TableTd>
<TableTd>
<Text
fz="sm"
fw={500}
lh={1.5}
lineClamp={1}
dangerouslySetInnerHTML={{ __html: item.judul }}
/>
</TableTd>
<TableTd ta="center">
{iconMap[item.icon] && (
<Box mx="auto" title={item.icon}>
{React.createElement(iconMap[item.icon], {
size: 22,
})}
</Box>
)}
</TableTd>
<TableTd ta="center">
<Button
size="xs"
radius="md"
variant="light"
color="blue"
leftSection={<IconDeviceImac size={16} />}
onClick={() =>
router.push(
`/admin/lingkungan/program-penghijauan/${item.id}`
)
}
>
Detail
</Button>
</TableTd>
</TableTr>
))
) : (
<TableTr>
<TableTd colSpan={5}>
<Center py="xl">
<Text c="dimmed" fz="sm" lh={1.4}>
Tidak ada data program penghijauan yang cocok
</Text>
</Center>
</TableTd>
</TableTr>
)}
</TableTbody>
</Table>
</Box>
</Box>
{/* Mobile View Card Layout */}
<Box hiddenFrom="md">
<Box mb="md">
<Title order={4} size="sm" lh={1.2}>
Daftar Program Penghijauan
</Title>
</Box>
<Button
leftSection={<IconPlus size={18} />}
color="blue"
variant="light"
onClick={() => router.push('/admin/lingkungan/program-penghijauan/create')}
mb="lg"
fullWidth
onClick={() =>
router.push('/admin/lingkungan/program-penghijauan/create')
}
>
Tambah Baru
</Button>
</Box>
{/* Table Section */}
<Box style={{ overflowX: 'auto' }}>
<Table highlightOnHover>
<TableThead>
<TableTr>
<TableTh style={{ width: '5%', textAlign: 'center' }}>No</TableTh>
<TableTh style={{ width: '25%' }}>Nama Program</TableTh>
<TableTh style={{ width: '35%' }}>Judul / Deskripsi</TableTh>
<TableTh style={{ width: '15%', textAlign: 'center' }}>Ikon</TableTh>
<TableTh style={{ width: '15%', textAlign: 'center' }}>Aksi</TableTh>
</TableTr>
</TableThead>
<TableTbody>
{filteredData.length > 0 ? (
filteredData.map((item, index) => (
<TableTr key={item.id}>
<TableTd style={{ textAlign: 'center' }}>{index + 1}</TableTd>
<TableTd>
<Text fw={500} truncate="end" lineClamp={1}>{item.name}</Text>
</TableTd>
<TableTd>
<Text lineClamp={1} fz="sm" c="dimmed" dangerouslySetInnerHTML={{ __html: item.judul }} />
</TableTd>
<TableTd style={{ textAlign: 'center' }}>
{filteredData.length > 0 ? (
filteredData.map((item, index) => (
<Paper key={item.id} withBorder p="md" mb="sm" radius="md">
<Stack gap="xs">
<Box>
<Text fz="sm" fw={600} lh={1.4}>
No
</Text>
<Text fz="sm" fw={500} lh={1.4}>
{index + 1}
</Text>
</Box>
<Box>
<Text fz="sm" fw={600} lh={1.4}>
Nama Program
</Text>
<Text fz="sm" fw={500} lh={1.4}>
{item.name}
</Text>
</Box>
<Box>
<Text fz="sm" fw={600} lh={1.4}>
Judul / Deskripsi
</Text>
<Text
fz="sm"
fw={500}
lh={1.5}
dangerouslySetInnerHTML={{ __html: item.judul }}
/>
</Box>
<Box>
<Text fz="sm" fw={600} lh={1.4}>
Ikon
</Text>
<Box mt="xs" ta="center">
{iconMap[item.icon] && (
<Box title={item.icon} mx="auto">
{React.createElement(iconMap[item.icon], { size: 22 })}
</Box>
React.createElement(iconMap[item.icon], { size: 24 })
)}
</TableTd>
<TableTd style={{ textAlign: 'center' }}>
<Button
size="xs"
radius="md"
variant="light"
color="blue"
leftSection={<IconDeviceImac size={16} />}
onClick={() => router.push(`/admin/lingkungan/program-penghijauan/${item.id}`)}
>
Detail
</Button>
</TableTd>
</TableTr>
))
) : (
<TableTr>
<TableTd colSpan={5}>
<Center py={20}>
<Text c="dimmed">Tidak ada data program penghijauan yang cocok</Text>
</Center>
</TableTd>
</TableTr>
)}
</TableTbody>
</Table>
</Box>
</Box>
<Box>
<Button
size="xs"
radius="md"
variant="light"
color="blue"
leftSection={<IconDeviceImac size={16} />}
onClick={() =>
router.push(
`/admin/lingkungan/program-penghijauan/${item.id}`
)
}
>
Detail
</Button>
</Box>
</Stack>
</Paper>
))
) : (
<Center py="xl">
<Text c="dimmed" fz="sm" lh={1.4}>
Tidak ada data program penghijauan yang cocok
</Text>
</Center>
)}
</Box>
</Paper>
@@ -187,4 +358,4 @@ function ListProgramPenghijauan({ search }: { search: string }) {
);
}
export default ProgramPenghijauan;
export default ProgramPenghijauan;