You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

370 lines
11 KiB

import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
import Highcharts from 'highcharts'
import HighchartsReact from 'highcharts-react-official'
6 months ago
import { Col, Label, Row } from 'reactstrap'
import { format_angka } from '../util'
import collect from 'collect.js'
6 months ago
import jquery from 'jquery'
import { Sidebar } from 'primereact/sidebar'
import '/node_modules/primeflex/primeflex.css'
import { MantineReactTable, useMantineReactTable } from 'mantine-react-table'
import { Text } from '@mantine/core'
import { QueryClient, QueryClientProvider, useInfiniteQuery } from '@tanstack/react-query'
import dayjs from 'dayjs'
var relativeTime = require('dayjs/plugin/relativeTime')
const fetchSize = 101
7 months ago
const Identifikasi = ({ dataSend }) => {
6 months ago
const base_url = '/engineN/'
7 months ago
const refChart = useRef(null)
const [dataGraph, setDataGraph] = useState(null)
const [dataDetail, setDataDetail] = useState({ meta: { data: [], total: 0 } })
const [visibleSidebar, setVisibleSidebar] = useState(false)
const [query, setQuery] = useState(null)
7 months ago
useEffect(() => {
6 months ago
jquery.get({
url: base_url + 'kewilayahan/kytp/sebaranIdentifikasi',
dataType: 'json',
type: 'POST',
7 months ago
data: {
...dataSend
},
success: (data) => {
setDataGraph(data.data)
7 months ago
}
})
}, [dataSend])
const optionsChart = (data, title) => {
const total_wp = collect(data).sum('y')
7 months ago
return {
chart: {
plotBackgroundColor: null,
plotBorderWidth: null,
plotShadow: false,
type: 'pie',
zoomType: 'xy',
height: '300'
7 months ago
},
title: {
text: title,
style: { fontSize: '10px' }
7 months ago
},
tooltip: {
pointFormat: '<b>{point.percentage:.1f}%</b><br>: {point.y} dari ' + format_angka(total_wp) + ' total lokasi Matoa'
7 months ago
},
accessibility: {
point: {
valueSuffix: '%'
7 months ago
}
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
7 months ago
dataLabels: {
enabled: true,
style: { fontSize: '10px' },
// format: "{point.name}: {point.y} <br> {point.percentage:.1f} %"
formatter: function () {
return `${this.key} : ${Number(this.y).toLocaleString('id-ID', {
minimumFractionDigits: 0,
maximumFractionDigits: 0
6 months ago
})} Lokasi <br> ${Number(this.percentage).toLocaleString('id-ID')}%`
}
}
},
series: {
cursor: 'pointer',
point: {
events: {
click: function (a) {
setQuery(this.key)
setVisibleSidebar(true)
}
}
7 months ago
}
}
},
series: [
{
name: '',
7 months ago
data
}
]
}
}
const TableDetailGraph = ({ dataSend, query }) => {
const tableContainerRef = useRef(null)
const rowVirtualizerInstanceRef = useRef(null)
const [columnFilters, setColumnFilters] = useState([])
const [globalFilter, setGlobalFilter] = useState()
const [sorting, setSorting] = useState([])
6 months ago
// const base_url = '/engineN/'
// console.log({ dataSend, query })
const { data, fetchNextPage, isError, isFetching, isLoading } = useInfiniteQuery({
queryKey: ['table-data', columnFilters, globalFilter, sorting],
queryFn: async ({ pageParam = 0 }) => {
6 months ago
const url = new URL(location.protocol + '//' + location.hostname + base_url + 'kewilayahan/sebaran/identifikasi/detail')
url.searchParams.set('start', `${pageParam * fetchSize}`)
url.searchParams.set('size', `${fetchSize}`)
url.searchParams.set('filters', JSON.stringify(columnFilters ?? []))
url.searchParams.set('globalFilter', globalFilter ?? '')
url.searchParams.set('sorting', JSON.stringify(sorting ?? []))
const response = await fetch(url.href, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify({
query,
...dataSend
})
})
const json = await response.json()
return json
},
getNextPageParam: (_lastGroup, groups) => groups.length,
keepPreviousData: true,
refetchOnWindowFocus: false
})
6 months ago
console.log(location.hostname)
const flatData = useMemo(() => data?.pages.flatMap((page) => page.data) ?? [], [data])
const totalDBRowCount = data?.pages?.[0]?.meta?.totalRowCount ?? 0
const totalFetched = flatData.length
const fetchMoreOnBottomReached = useCallback(
(containerRefElement) => {
if (containerRefElement) {
const { scrollHeight, scrollTop, clientHeight } = containerRefElement
//once the user has scrolled within 400px of the bottom of the table, fetch more data if we can
if (scrollHeight - scrollTop - clientHeight < 400 && !isFetching && totalFetched < totalDBRowCount) {
fetchNextPage()
}
}
},
[fetchNextPage, isFetching, totalFetched, totalDBRowCount]
)
const columns = [
{
accessorKey: 'NAMA',
header: 'Nama'
},
{
accessorKey: 'MERK_USAHA',
header: 'Merk Usaha'
},
{
accessorKey: 'NO_IDENTITAS',
header: 'No Identitas'
},
{
accessorKey: 'NPWP',
header: 'NPWP',
enableClickToCopy: true,
size: 150
},
{
accessorKey: 'ALAMAT',
header: 'Alamat'
},
{
accessorKey: 'KELURAHAN',
header: 'Wil. Adm.',
Cell: (data) => {
const dataRow = data.row.original
return `${dataRow.KELURAHAN} ${dataRow.KECAMATAN} ${dataRow.KABUPATEN} ${dataRow.PROVINSI}`
}
},
{
accessorKey: 'STATUS_WP_MFWP',
header: 'Status WP'
},
{
accessorKey: 'JNS_WP_MFWP',
header: 'Jenis WP'
},
{
accessorKey: 'NM_KANTOR_PENGAMPU',
header: 'KPP Terdaftar'
},
{
accessorKey: 'NM_AR_PENGAMPU',
header: 'AR Pengampu'
},
{
accessorKey: 'JUMLAH_PEMBAYARAN_THN_TERAKHIR',
header: 'Rp',
Cell: ({ cell }) => parseFloat(cell.getValue()).toLocaleString('id-ID'),
mantineTableHeadCellProps: {
align: 'right'
},
mantineTableBodyCellProps: {
align: 'right'
},
size: 100
},
{
accessorKey: 'KETERANGAN',
header: 'SPT'
},
{
accessorKey: 'SUM_NILAI',
header: 'NILAI DATA',
Cell: ({ cell }) => parseFloat(cell.getValue()).toLocaleString('id-ID'),
mantineTableHeadCellProps: {
align: 'right'
},
mantineTableBodyCellProps: {
align: 'right'
}
},
{
accessorKey: 'NM_KPP_ZONA',
header: 'KPP Lokasi'
},
{
accessorKey: 'NM_AR_ZONA',
header: 'AR Wilayah',
filter: false
},
{
accessorKey: 'NM_PEREKAM',
header: 'Perekam'
},
{
accessorKey: 'CREATION_DATE',
header: 'Tgl Rekam',
Cell: ({ cell }) => {
return dayjs(cell.getValue()).format('YYYY-MM-DD HH:mm:ss')
}
}
]
useEffect(() => {
if (rowVirtualizerInstanceRef.current) {
try {
rowVirtualizerInstanceRef.current.scrollToIndex(0)
} catch (e) {
console.error(e)
}
}
}, [sorting, columnFilters, globalFilter])
//a check on mount to see if the table is already scrolled to the bottom and immediately needs to fetch more data
useEffect(() => {
fetchMoreOnBottomReached(tableContainerRef.current)
}, [fetchMoreOnBottomReached])
const table1 = useMantineReactTable({
columns,
data: flatData,
enablePagination: false,
enableRowNumbers: true,
enableRowVirtualization: true, //optional, but recommended if it is likely going to be more than 100 rows
manualFiltering: true,
manualSorting: true,
mantineTableContainerProps: {
ref: tableContainerRef, //get access to the table container element
sx: { maxHeight: '600px' }, //give the table a max height
onScroll: (
event //add an event listener to the table container element
) => fetchMoreOnBottomReached(event.target)
},
mantineToolbarAlertBannerProps: {
color: 'red',
children: 'Error loading data'
},
onColumnFiltersChange: setColumnFilters,
onGlobalFilterChange: setGlobalFilter,
onSortingChange: setSorting,
renderBottomToolbarCustomActions: () => (
<Text className="text-sm">
Fetched {totalFetched} of {totalDBRowCount} total rows.
</Text>
),
state: {
columnFilters,
globalFilter,
isLoading,
showAlertBanner: isError,
showProgressBars: isFetching,
sorting
},
rowVirtualizerInstanceRef, //get access to the virtualizer instance
rowVirtualizerProps: { overscan: 10 },
mantineTableBodyCellProps: { className: 'p-1 text-xs' }
})
return <MantineReactTable table={table1} />
}
const queryClient = new QueryClient()
7 months ago
return (
<>
<Row>
<Col>
<HighchartsReact ref={refChart} highcharts={Highcharts} options={optionsChart(dataGraph, 'Identifikasi Lokasi Matoa')} />
</Col>
</Row>
6 months ago
<Row>
<Col>
{/* <div className="text-xs">
6 months ago
<div>Berdasarkan : </div>
<ul>
<li>Zona Pengawasan : Zona Pengawasan yang diampu unit</li>
<li>Perekam : yang dilakukan oleh pegawai unit</li>
<li>Pengampu : wp yang diampu oleh unit </li>
</ul>
</div> */}
<div className="f-14">
<span className="f-14">
Berdasarkan kompilasi data KPD Mobile dan pengolahan data-data perpajakan lainnya (KPD Lainnya), daftar Wajib Pajak yang belum diaktivasi (belum
ber-NPWP) agar segera dilakukan kegiatan ekstensifikasi Wajib Pajak (diaktivasi NPWP-nya) oleh AR yang mengampu wilayah tempat kegiatan usaha
tersebut. Apabila kegiatan usaha yang diawasi terdaftar di unit kerja lain, maka AR pengampu wilayah mengirimkan data registrasi WP ke unit kerja
yang mengadministrasikan kegiatan usaha yang diawasi.
</span>
6 months ago
</div>
<Sidebar
header={
<>
<h4>Detail Data</h4>
</>
}
visible={visibleSidebar}
position="bottom"
onHide={() => setVisibleSidebar(false)}
style={{ height: 'calc(100vh - 100px)' }}
blockScroll
pt={{ header: { className: 'p-1' }, closeButton: { style: { width: '2rem', height: '1rem' } } }}
>
<Row>
<Col>
<QueryClientProvider client={queryClient}>
<TableDetailGraph dataSend={dataSend} query={query} />
</QueryClientProvider>
</Col>
</Row>
</Sidebar>
7 months ago
</Col>
</Row>
</>
)
}
export default Identifikasi