Tambahan filter data sesuai tahun, di landing page apbdes
This commit is contained in:
@@ -361,6 +361,7 @@ function CreateAPBDes() {
|
||||
data={[
|
||||
{ value: 'pendapatan', label: 'Pendapatan' },
|
||||
{ value: 'belanja', label: 'Belanja' },
|
||||
{ value: 'pembiayaan', label: 'Pembiayaan' },
|
||||
]}
|
||||
value={newItem.level === 1 ? null : newItem.tipe}
|
||||
onChange={(val) => setNewItem({ ...newItem, tipe: val as any })}
|
||||
|
||||
@@ -151,7 +151,7 @@ function Page() {
|
||||
variant="light"
|
||||
color="blue"
|
||||
leftSection={<IconDeviceImacCog size={16} />}
|
||||
onClick={() => router.push(`/darmasaba/ppid/daftar-informasi-publik-desa-darmasaba/${item.id}`)}
|
||||
onClick={() => router.push(`/darmasaba/ppid/daftar-informasi-publik/${item.id}`)}
|
||||
>
|
||||
Detail
|
||||
</Button>
|
||||
|
||||
@@ -1,13 +1,8 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
// src/app/admin/(dashboard)/landing-page/APBDes/APBDesProgress.tsx
|
||||
'use client';
|
||||
|
||||
import { Box, Paper, Progress, Stack, Text, Title } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import apbdes from '@/app/admin/(dashboard)/_state/landing-page/apbdes';
|
||||
import colors from '@/con/colors';
|
||||
|
||||
|
||||
import { Box, Paper, Progress, Stack, Text, Title } from '@mantine/core';
|
||||
import { APBDesData } from './types';
|
||||
|
||||
function formatRupiah(value: number) {
|
||||
return new Intl.NumberFormat('id-ID', {
|
||||
@@ -17,31 +12,33 @@ function formatRupiah(value: number) {
|
||||
}).format(value);
|
||||
}
|
||||
|
||||
function APBDesProgress() {
|
||||
const state = useProxy(apbdes);
|
||||
const data = state.findMany.data || [];
|
||||
interface APBDesProgressProps {
|
||||
apbdesData: APBDesData;
|
||||
}
|
||||
|
||||
// Ambil APBDes pertama (misalnya, jika hanya satu tahun ditampilkan)
|
||||
const apbdesItem = data[0]; // 👈 sesuaikan logika jika ada banyak APBDes
|
||||
|
||||
if (!apbdesItem) {
|
||||
return (
|
||||
<Box py="md" px={{ base: 'md', md: 100 }}>
|
||||
<Text c="dimmed">Belum ada data APBDes untuk ditampilkan.</Text>
|
||||
</Box>
|
||||
);
|
||||
function APBDesProgress({ apbdesData }: APBDesProgressProps) {
|
||||
// Return null if apbdesData is not available yet
|
||||
if (!apbdesData) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const items = apbdesItem.items || [];
|
||||
const items = apbdesData.items || [];
|
||||
const sortedItems = [...items].sort((a, b) => a.kode.localeCompare(b.kode));
|
||||
|
||||
// Kelompokkan berdasarkan tipe
|
||||
const pendapatanItems = sortedItems.filter(item => item.tipe === 'pendapatan');
|
||||
const belanjaItems = sortedItems.filter(item => item.tipe === 'belanja');
|
||||
const pembiayaanItems = sortedItems.filter(item => item.tipe === 'pembiayaan'); // jika ada
|
||||
const pembiayaanItems = sortedItems.filter(item => item.tipe === 'pembiayaan');
|
||||
|
||||
// Items without a type (should be filtered out from calculations)
|
||||
const untypedItems = sortedItems.filter(item => !item.tipe);
|
||||
|
||||
if (untypedItems.length > 0) {
|
||||
console.warn(`Found ${untypedItems.length} items without a type. These will be excluded from calculations.`);
|
||||
}
|
||||
|
||||
// Hitung total per kategori
|
||||
const calcTotal = (items: any[]) => {
|
||||
const calcTotal = (items: { anggaran: number; realisasi: number }[]) => {
|
||||
const anggaran = items.reduce((sum, item) => sum + item.anggaran, 0);
|
||||
const realisasi = items.reduce((sum, item) => sum + item.realisasi, 0);
|
||||
const persen = anggaran > 0 ? (realisasi / anggaran) * 100 : 0;
|
||||
@@ -50,10 +47,10 @@ function APBDesProgress() {
|
||||
|
||||
const pendapatan = calcTotal(pendapatanItems);
|
||||
const belanja = calcTotal(belanjaItems);
|
||||
const pembiayaan = calcTotal(pembiayaanItems); // bisa kosong
|
||||
const pembiayaan = calcTotal(pembiayaanItems);
|
||||
|
||||
// Render satu progress bar
|
||||
const renderProgress = (label: string, dataset: any) => {
|
||||
const renderProgress = (label: string, dataset: { realisasi: number; anggaran: number; persen: number }) => {
|
||||
const isPembiayaan = label.includes('Pembiayaan');
|
||||
|
||||
return (
|
||||
@@ -71,8 +68,8 @@ function APBDesProgress() {
|
||||
root: { backgroundColor: '#d7e3f1' },
|
||||
section: {
|
||||
backgroundColor: isPembiayaan
|
||||
? 'green' // warna hijau untuk pembiayaan
|
||||
: colors['blue-button'], // biru untuk pendapatan/belanja
|
||||
? 'green'
|
||||
: colors['blue-button'],
|
||||
position: 'relative',
|
||||
'&::after': {
|
||||
content: `'${dataset.persen.toFixed(2)}%'`,
|
||||
@@ -102,7 +99,7 @@ function APBDesProgress() {
|
||||
>
|
||||
<Stack gap="lg">
|
||||
<Title order={4} c={colors['blue-button']} ta="center">
|
||||
Grafik Pelaksanaan APBDes Tahun {apbdesItem.tahun}
|
||||
Grafik Pelaksanaan APBDes Tahun {apbdesData.tahun}
|
||||
</Title>
|
||||
|
||||
<Text ta="center" fw="bold" fz="sm" c="dimmed">
|
||||
@@ -112,97 +109,9 @@ function APBDesProgress() {
|
||||
{renderProgress('Pendapatan Desa', pendapatan)}
|
||||
{renderProgress('Belanja Desa', belanja)}
|
||||
{renderProgress('Pembiayaan Desa', pembiayaan)}
|
||||
{pembiayaanItems.length > 0 && renderProgress('Pembiayaan Desa', pembiayaan)}
|
||||
</Stack>
|
||||
</Paper>
|
||||
);
|
||||
}
|
||||
|
||||
export default APBDesProgress;
|
||||
|
||||
// /* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
// 'use client';
|
||||
|
||||
// import { Box, Paper, Stack, Text, Title } from '@mantine/core';
|
||||
// import { BarChart } from '@mantine/charts';
|
||||
// import { useProxy } from 'valtio/utils';
|
||||
// import apbdes from '@/app/admin/(dashboard)/_state/landing-page/apbdes';
|
||||
// import colors from '@/con/colors';
|
||||
|
||||
// function APBDesProgress() {
|
||||
// const state = useProxy(apbdes);
|
||||
// const data = state.findMany.data || [];
|
||||
|
||||
// const apbdesItem = data[0];
|
||||
// if (!apbdesItem) {
|
||||
// return (
|
||||
// <Box py="md" px={{ base: 'md', md: 100 }}>
|
||||
// <Text c="dimmed">Belum ada data APBDes untuk ditampilkan.</Text>
|
||||
// </Box>
|
||||
// );
|
||||
// }
|
||||
|
||||
// const items = apbdesItem.items || [];
|
||||
// const sortedItems = [...items].sort((a, b) => a.kode.localeCompare(b.kode));
|
||||
|
||||
// const pendapatanItems = sortedItems.filter(i => i.tipe === 'pendapatan');
|
||||
// const belanjaItems = sortedItems.filter(i => i.tipe === 'belanja');
|
||||
// const pembiayaanItems = sortedItems.filter(i => i.tipe === 'pembiayaan');
|
||||
|
||||
// const total = (rows: any[]) => {
|
||||
// const anggaran = rows.reduce((s, i) => s + i.anggaran, 0);
|
||||
// const realisasi = rows.reduce((s, i) => s + i.realisasi, 0);
|
||||
// return anggaran === 0 ? 0 : (realisasi / anggaran) * 100;
|
||||
// };
|
||||
|
||||
// const chartData = [
|
||||
// { name: 'Pendapatan', persen: total(pendapatanItems) },
|
||||
// { name: 'Belanja', persen: total(belanjaItems) },
|
||||
// ];
|
||||
|
||||
// if (pembiayaanItems.length > 0) {
|
||||
// chartData.push({ name: 'Pembiayaan', persen: total(pembiayaanItems) });
|
||||
// }
|
||||
|
||||
// return (
|
||||
// <Paper
|
||||
// mx={{ base: 'md', md: 100 }}
|
||||
// p="xl"
|
||||
// radius="md"
|
||||
// shadow="sm"
|
||||
// withBorder
|
||||
// bg={colors['white-1']}
|
||||
// >
|
||||
// <Stack gap="lg">
|
||||
// <Title order={4} c={colors['blue-button']} ta="center">
|
||||
// Grafik Pelaksanaan APBDes Tahun {apbdesItem.tahun}
|
||||
// </Title>
|
||||
|
||||
// <Text ta="center" fw="bold" fz="sm" c="dimmed">
|
||||
// Persentase Realisasi (%) dari Anggaran
|
||||
// </Text>
|
||||
|
||||
// <BarChart
|
||||
// h={200}
|
||||
// data={chartData}
|
||||
// orientation="vertical"
|
||||
// dataKey="name"
|
||||
// barProps={{ radius: 6 }}
|
||||
// series={[
|
||||
// {
|
||||
// name: 'persen',
|
||||
// label: 'Persentase',
|
||||
// color: colors['blue-button'],
|
||||
// },
|
||||
// ]}
|
||||
// yAxisProps={{
|
||||
// domain: [0, 100],
|
||||
// }}
|
||||
// valueFormatter={(v) => `${v.toFixed(1)}%`}
|
||||
// />
|
||||
// </Stack>
|
||||
// </Paper>
|
||||
// );
|
||||
// }
|
||||
|
||||
// export default APBDesProgress;
|
||||
export default APBDesProgress;
|
||||
@@ -1,30 +1,8 @@
|
||||
// src/app/admin/(dashboard)/landing-page/APBDes/APBDesTable.tsx
|
||||
'use client';
|
||||
|
||||
import { Box, Paper, Table, Text, Title, Badge, Group } from '@mantine/core';
|
||||
import { useProxy } from 'valtio/utils';
|
||||
import apbdes from '@/app/admin/(dashboard)/_state/landing-page/apbdes';
|
||||
import colors from '@/con/colors';
|
||||
|
||||
interface APBDesItem {
|
||||
id: string;
|
||||
kode: string;
|
||||
uraian: string;
|
||||
anggaran: number;
|
||||
realisasi: number;
|
||||
selisih: number;
|
||||
persentase: number;
|
||||
level: number;
|
||||
tipe: 'pendapatan' | 'belanja' | 'pembiayaan';
|
||||
}
|
||||
|
||||
interface APBDesData {
|
||||
id: string;
|
||||
tahun: number;
|
||||
items: APBDesItem[];
|
||||
image?: { id: string; url: string } | null;
|
||||
file?: { id: string; url: string } | null;
|
||||
}
|
||||
import { APBDesData } from './types';
|
||||
|
||||
// Helper: Format Rupiah, tapi jika 0 → tampilkan '-'
|
||||
function formatRupiahOrEmpty(value: number): string {
|
||||
@@ -51,22 +29,12 @@ function getIndent(level: number) {
|
||||
};
|
||||
}
|
||||
|
||||
function APBDesTable() {
|
||||
const state = useProxy(apbdes);
|
||||
const data = state.findMany.data || [];
|
||||
interface APBDesTableProps {
|
||||
apbdesData: APBDesData;
|
||||
}
|
||||
|
||||
// Get the first APBDes item
|
||||
const apbdesItem = data[0] as unknown as APBDesData | undefined;
|
||||
|
||||
if (!apbdesItem) {
|
||||
return (
|
||||
<Box py="md" px={{ base: 'md', md: 100 }}>
|
||||
<Text c="dimmed">Belum ada data APBDes untuk ditampilkan.</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
const items = Array.isArray(apbdesItem.items) ? apbdesItem.items : [];
|
||||
function APBDesTable({ apbdesData }: APBDesTableProps) {
|
||||
const items = Array.isArray(apbdesData.items) ? apbdesData.items : [];
|
||||
const sortedItems = [...items].sort((a, b) => a.kode.localeCompare(b.kode));
|
||||
|
||||
// Calculate totals
|
||||
@@ -76,13 +44,13 @@ function APBDesTable() {
|
||||
const totalPersentase = totalAnggaran > 0 ? (totalRealisasi / totalAnggaran) * 100 : 0;
|
||||
|
||||
return (
|
||||
<Box py="md" px={{ base: 'md', md: 100 }}>
|
||||
<Box pt={"xs"} pb="md" px={{ base: 'md', md: 100 }}>
|
||||
<Title order={4} c={colors['blue-button']} mb="sm">
|
||||
Rincian APBDes Tahun {apbdesItem.tahun}
|
||||
Rincian APBDes Tahun {apbdesData.tahun}
|
||||
</Title>
|
||||
|
||||
<Paper withBorder radius="md" shadow="xs" p="md">
|
||||
<Box style={{overflowY: 'auto' }}>
|
||||
<Box style={{ overflowY: 'auto' }}>
|
||||
<Table withColumnBorders highlightOnHover>
|
||||
<Table.Thead bg="#2c5f78">
|
||||
<Table.Tr>
|
||||
@@ -109,9 +77,7 @@ function APBDesTable() {
|
||||
<Table.Td style={getIndent(item.level)}>
|
||||
<Group gap="xs" align="flex-start">
|
||||
<Text fw={item.level === 1 ? 'bold' : 'normal'}>{item.kode}</Text>
|
||||
<Text fz="sm" >
|
||||
{item.uraian}
|
||||
</Text>
|
||||
<Text fz="sm">{item.uraian}</Text>
|
||||
</Group>
|
||||
</Table.Td>
|
||||
<Table.Td ta="right">{formatRupiahOrEmpty(item.anggaran)}</Table.Td>
|
||||
|
||||
42
src/app/darmasaba/(tambahan)/apbdes/lib/types.ts
Normal file
42
src/app/darmasaba/(tambahan)/apbdes/lib/types.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
export type APBDesTipe = 'pendapatan' | 'belanja' | 'pembiayaan';
|
||||
|
||||
export function isAPBDesTipe(tipe: string | null | undefined): tipe is APBDesTipe {
|
||||
return tipe === 'pendapatan' || tipe === 'belanja' || tipe === 'pembiayaan';
|
||||
}
|
||||
|
||||
export interface APBDesItem {
|
||||
id: string;
|
||||
kode: string;
|
||||
uraian: string;
|
||||
anggaran: number;
|
||||
realisasi: number;
|
||||
selisih: number;
|
||||
persentase: number;
|
||||
level: number;
|
||||
tipe?: APBDesTipe | null;
|
||||
// Additional fields from API
|
||||
createdAt?: Date;
|
||||
updatedAt?: Date;
|
||||
deletedAt?: Date | null;
|
||||
isActive?: boolean;
|
||||
apbdesId?: string;
|
||||
}
|
||||
|
||||
export interface APBDesData {
|
||||
id: string;
|
||||
tahun: number | null;
|
||||
items: APBDesItem[];
|
||||
image?: { id: string; url: string } | null;
|
||||
file?: { id: string; url: string } | null;
|
||||
}
|
||||
|
||||
export function transformAPBDesData(data: any): APBDesData {
|
||||
return {
|
||||
...data,
|
||||
items: data.items.map((item: any) => ({
|
||||
...item,
|
||||
tipe: isAPBDesTipe(item.tipe) ? item.tipe : null
|
||||
}))
|
||||
};
|
||||
}
|
||||
@@ -4,19 +4,21 @@
|
||||
import PendapatanAsliDesa from '@/app/admin/(dashboard)/_state/ekonomi/PADesa'
|
||||
import apbdes from '@/app/admin/(dashboard)/_state/landing-page/apbdes'
|
||||
import colors from '@/con/colors'
|
||||
import { ActionIcon, BackgroundImage, Box, Center, Container, Group, Loader, SimpleGrid, Stack, Text, Title } from '@mantine/core'
|
||||
import { ActionIcon, BackgroundImage, Box, Center, Container, Group, Loader, Select, SimpleGrid, Stack, Text, Title } from '@mantine/core'
|
||||
import { IconDownload } from '@tabler/icons-react'
|
||||
import { Link } from 'next-view-transitions'
|
||||
import { useEffect, useState } from 'react'
|
||||
import { useProxy } from 'valtio/utils'
|
||||
import BackButton from '../../(pages)/desa/layanan/_com/BackButto'
|
||||
import APBDesProgress from './lib/apbDesaProgress'
|
||||
import APBDesTable from './lib/apbDesaTable'
|
||||
import APBDesProgress from './lib/apbDesaProgress'
|
||||
import { transformAPBDesData } from './lib/types'
|
||||
|
||||
function Page() {
|
||||
const state = useProxy(apbdes)
|
||||
const paDesaState = useProxy(PendapatanAsliDesa.ApbDesa)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [selectedYear, setSelectedYear] = useState<string | null>(null)
|
||||
useEffect(() => {
|
||||
const loadData = async () => {
|
||||
try {
|
||||
@@ -34,6 +36,23 @@ function Page() {
|
||||
|
||||
const dataAPBDes = state.findMany.data || []
|
||||
|
||||
// Buat daftar tahun unik dari data
|
||||
const years = Array.from(new Set(dataAPBDes.map((item: any) => item.tahun)))
|
||||
.sort((a, b) => b - a) // urutkan descending
|
||||
.map(year => ({ value: year.toString(), label: `Tahun ${year}` }))
|
||||
|
||||
// Pilih tahun pertama sebagai default jika belum ada yang dipilih
|
||||
useEffect(() => {
|
||||
if (years.length > 0 && !selectedYear) {
|
||||
setSelectedYear(years[0].value)
|
||||
}
|
||||
}, [years, selectedYear])
|
||||
|
||||
// Transform and filter data based on selected year
|
||||
const currentApbdes = dataAPBDes.length > 0
|
||||
? transformAPBDesData(dataAPBDes.find(item => item?.tahun?.toString() === selectedYear) || dataAPBDes[0])
|
||||
: null
|
||||
|
||||
return (
|
||||
<Stack pos="relative" bg={colors.Bg} py="xl" gap={32}>
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
@@ -94,8 +113,31 @@ function Page() {
|
||||
))}
|
||||
</SimpleGrid>
|
||||
)}
|
||||
<APBDesTable />
|
||||
<APBDesProgress />
|
||||
{/* 🔥 COMBOBOX UNTUK PILIH TAHUN */}
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Select
|
||||
label="Pilih Tahun APBDes"
|
||||
placeholder="Pilih tahun"
|
||||
value={selectedYear}
|
||||
onChange={setSelectedYear}
|
||||
data={years}
|
||||
w={{ base: '100%', sm: 200 }}
|
||||
searchable
|
||||
clearable
|
||||
nothingFoundMessage="Tidak ada tahun tersedia"
|
||||
/>
|
||||
</Box>
|
||||
{/* ❗ Pass currentApbdes ke komponen anak */}
|
||||
{currentApbdes ? (
|
||||
<>
|
||||
<APBDesTable apbdesData={currentApbdes} />
|
||||
<APBDesProgress apbdesData={currentApbdes} />
|
||||
</>
|
||||
) : (
|
||||
<Box px={{ base: 'md', md: 100 }} py="md">
|
||||
<Text c="dimmed">Tidak ada data APBDes untuk tahun yang dipilih.</Text>
|
||||
</Box>
|
||||
)}
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
'use client'
|
||||
import apbdes from '@/app/admin/(dashboard)/_state/landing-page/apbdes'
|
||||
import APBDesProgress from '@/app/darmasaba/(tambahan)/apbdes/lib/apbDesaProgress'
|
||||
import { transformAPBDesData } from '@/app/darmasaba/(tambahan)/apbdes/lib/types'
|
||||
import colors from '@/con/colors'
|
||||
import { ActionIcon, BackgroundImage, Box, Button, Center, Flex, Group, Loader, SimpleGrid, Stack, Text } from '@mantine/core'
|
||||
import { ActionIcon, BackgroundImage, Box, Button, Center, Flex, Group, Loader, Select, SimpleGrid, Stack, Text } from '@mantine/core'
|
||||
import { IconDownload } from '@tabler/icons-react'
|
||||
import Link from 'next/link'
|
||||
import { useEffect, useState } from 'react'
|
||||
@@ -12,6 +14,7 @@ import { useProxy } from 'valtio/utils'
|
||||
function Apbdes() {
|
||||
const state = useProxy(apbdes)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [selectedYear, setSelectedYear] = useState<string | null>(null)
|
||||
|
||||
const textHeading = {
|
||||
title: 'APBDes',
|
||||
@@ -32,6 +35,24 @@ function Apbdes() {
|
||||
loadData()
|
||||
}, [])
|
||||
|
||||
const dataAPBDes = state.findMany.data || []
|
||||
|
||||
const years = Array.from(new Set(dataAPBDes.map((item: any) => item.tahun)))
|
||||
.sort((a, b) => b - a) // urutkan descending
|
||||
.map(year => ({ value: year.toString(), label: `Tahun ${year}` }))
|
||||
|
||||
// Pilih tahun pertama sebagai default jika belum ada yang dipilih
|
||||
useEffect(() => {
|
||||
if (years.length > 0 && !selectedYear) {
|
||||
setSelectedYear(years[0].value)
|
||||
}
|
||||
}, [years, selectedYear])
|
||||
|
||||
// Transform and filter data based on selected year
|
||||
const currentApbdes = dataAPBDes.length > 0
|
||||
? transformAPBDesData(dataAPBDes.find(item => item?.tahun?.toString() === selectedYear) || dataAPBDes[0])
|
||||
: null
|
||||
|
||||
const data = (state.findMany.data || []).slice(0, 3)
|
||||
|
||||
return (
|
||||
@@ -60,8 +81,30 @@ function Apbdes() {
|
||||
</Button>
|
||||
</Group>
|
||||
|
||||
{/* Chart */}
|
||||
<APBDesProgress />
|
||||
{/* 🔥 COMBOBOX UNTUK PILIH TAHUN */}
|
||||
<Box px={{ base: 'md', md: 100 }}>
|
||||
<Select
|
||||
label="Pilih Tahun APBDes"
|
||||
placeholder="Pilih tahun"
|
||||
value={selectedYear}
|
||||
onChange={setSelectedYear}
|
||||
data={years}
|
||||
w={{ base: '100%', sm: 200 }}
|
||||
searchable
|
||||
clearable
|
||||
nothingFoundMessage="Tidak ada tahun tersedia"
|
||||
/>
|
||||
</Box>
|
||||
|
||||
{currentApbdes ? (
|
||||
<>
|
||||
<APBDesProgress apbdesData={currentApbdes} />
|
||||
</>
|
||||
) : (
|
||||
<Box px={{ base: 'md', md: 100 }} py="md">
|
||||
<Text c="dimmed">Tidak ada data APBDes untuk tahun yang dipilih.</Text>
|
||||
</Box>
|
||||
)}
|
||||
|
||||
<SimpleGrid mx={{ base: 'md', md: 100 }} cols={{ base: 1, sm: 3 }} spacing="lg" pb={"xl"}>
|
||||
{loading ? (
|
||||
@@ -129,7 +172,7 @@ function Apbdes() {
|
||||
)}
|
||||
</SimpleGrid>
|
||||
|
||||
|
||||
|
||||
</Stack>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user