From 2f28a7dfa7b2e256aa29a1fb807d61797fce68e8 Mon Sep 17 00:00:00 2001 From: Anitha_M Date: Sat, 18 Jul 2026 11:39:15 +0530 Subject: [PATCH] Approval pending --- Approval_Pending/config.json | 3 + Approval_Pending/icon.svg | 1 + Approval_Pending/manifest.json | 29 +++++ Approval_Pending/src/config.ts | 7 ++ Approval_Pending/src/index.tsx | 104 ++++++++++++++++++ Approval_Pending/src/runtime/widget.tsx | 8 ++ Approval_Pending/src/styles.css | 24 ++++ Approval_Pending/tests/simple-widget.test.tsx | 14 +++ 8 files changed, 190 insertions(+) create mode 100644 Approval_Pending/config.json create mode 100644 Approval_Pending/icon.svg create mode 100644 Approval_Pending/manifest.json create mode 100644 Approval_Pending/src/config.ts create mode 100644 Approval_Pending/src/index.tsx create mode 100644 Approval_Pending/src/runtime/widget.tsx create mode 100644 Approval_Pending/src/styles.css create mode 100644 Approval_Pending/tests/simple-widget.test.tsx diff --git a/Approval_Pending/config.json b/Approval_Pending/config.json new file mode 100644 index 0000000..783d28f --- /dev/null +++ b/Approval_Pending/config.json @@ -0,0 +1,3 @@ +{ + "exampleConfigProperty": "test" +} diff --git a/Approval_Pending/icon.svg b/Approval_Pending/icon.svg new file mode 100644 index 0000000..39ab732 --- /dev/null +++ b/Approval_Pending/icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/Approval_Pending/manifest.json b/Approval_Pending/manifest.json new file mode 100644 index 0000000..dd056d4 --- /dev/null +++ b/Approval_Pending/manifest.json @@ -0,0 +1,29 @@ +{ + "name": "Approval_Pending", + "label": "Approval_Pending", + "type": "widget", + "version": "1.16.0", + "exbVersion": "1.16.0", + "author": "Tanii GIS Developer", + "description": "This is a barebones, simple widget. It includes an example of how to use the config file, and it includes a placeholder SVG icon. It intentionally does not include the following so you can use this to start from scratch: i18n translations, a Settings panel, unit tests. See the documentation for more information on how to implement these features.", + "copyright": "", + "license": "http://www.apache.org/licenses/LICENSE-2.0", + "properties": { + "hasSettingPage": false + }, + "widgets": [ + { + "uri": "Approval_Pending", + "label": "Approval_Pending", + "thumbnail": "thumbnail.png", + "description": "Summarizes Street Light, Highmast, and Pillar Box counts by zone." + } + ], + "framework": "react", + "translatedLocales": ["en"], + "dataSources": [], + "elements": [] +} + + + diff --git a/Approval_Pending/src/config.ts b/Approval_Pending/src/config.ts new file mode 100644 index 0000000..780aacf --- /dev/null +++ b/Approval_Pending/src/config.ts @@ -0,0 +1,7 @@ +import { type ImmutableObject } from 'seamless-immutable' + +export interface Config { + exampleConfigProperty: string +} + +export type IMConfig = ImmutableObject diff --git a/Approval_Pending/src/index.tsx b/Approval_Pending/src/index.tsx new file mode 100644 index 0000000..07a03c6 --- /dev/null +++ b/Approval_Pending/src/index.tsx @@ -0,0 +1,104 @@ +import React, { useEffect, useState } from 'react'; +import FeatureLayer from '@arcgis/core/layers/FeatureLayer'; +import { Box, Typography } from '@mui/material'; + +interface ZoneData { + zone_no: string; + pendingCount: number; + toBeVerifiedCount: number; +} + +const ZoneIntimationOnly = () => { + const [zoneData, setZoneData] = useState([]); + + useEffect(() => { + fetchData(); + }, []); + + const normalizeZone = (zone: any) => { + if (zone == null) return ''; + const s = String(zone); + const match = s.match(/\d+/); + return match ? match[0].padStart(2, '0') : ''; + }; + + const fetchData = async () => { + const BUILDING_LAYER_URL = + 'https://gisgcc.chennaicorporation.gov.in/server/rest/services/Revenue/Building_Updation/FeatureServer/0'; + + const buildingLayer = new FeatureLayer({ + url: BUILDING_LAYER_URL + }); + + const query = buildingLayer.createQuery(); + query.outFields = ['zone', 'approval']; + query.where = '1=1'; + query.returnGeometry = false; + query.num = 2000; + + let features: any[] = []; + let offset = 0; + + while (true) { + query.start = offset; + const res = await buildingLayer.queryFeatures(query); + features = features.concat(res.features); + if (res.features.length < query.num) break; + offset += query.num; + } + + const zonePendingMap: Record = {}; + const zoneTBVMap: Record = {}; + + features.forEach(f => { + const rawZone = f.attributes?.zone ?? ''; + const approval = (f.attributes?.approval ?? '').trim().toLowerCase(); + + const zone = normalizeZone(rawZone); + if (!zone) return; + + if (approval === 'pending') { + zonePendingMap[zone] = (zonePendingMap[zone] || 0) + 1; + } + + if (approval === 'to be verified') { + zoneTBVMap[zone] = (zoneTBVMap[zone] || 0) + 1; + } + }); + + const allZones = new Set([ + ...Object.keys(zonePendingMap), + ...Object.keys(zoneTBVMap) + ]); + + const result: ZoneData[] = Array.from(allZones).map(zone => ({ + zone_no: zone, + pendingCount: zonePendingMap[zone] || 0, + toBeVerifiedCount: zoneTBVMap[zone] || 0 + })); + + result.sort((a, b) => parseInt(a.zone_no, 10) - parseInt(b.zone_no, 10)); + + setZoneData(result); + }; + + return ( + + {zoneData.length === 0 ? ( + + No Pending or To Be Verified records found. + + ) : ( + zoneData.map(z => ( + + Zone {z.zone_no} — Pending: + {z.pendingCount} | To be Verified: + {z.toBeVerifiedCount} + + )) + )} + + ); +}; + +export default ZoneIntimationOnly; diff --git a/Approval_Pending/src/runtime/widget.tsx b/Approval_Pending/src/runtime/widget.tsx new file mode 100644 index 0000000..d3f9df0 --- /dev/null +++ b/Approval_Pending/src/runtime/widget.tsx @@ -0,0 +1,8 @@ +import { React, AllWidgetProps } from 'jimu-core'; +import ZoneAbstractWidget from '../index'; + +const Widget = (props: AllWidgetProps) => { + return ; +}; + +export default Widget; diff --git a/Approval_Pending/src/styles.css b/Approval_Pending/src/styles.css new file mode 100644 index 0000000..7a2f66a --- /dev/null +++ b/Approval_Pending/src/styles.css @@ -0,0 +1,24 @@ +.widget-container { + padding: 15px; + background: white; + border-radius: 8px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + } + + h3 { + font-size: 18px; + margin-bottom: 10px; + } + + .export-button { + margin-top: 10px; + background-color: #0078d4; + color: white; + } + + .table-container { + max-height: 400px; + overflow-y: auto; + border: 1px solid #ddd; + } + \ No newline at end of file diff --git a/Approval_Pending/tests/simple-widget.test.tsx b/Approval_Pending/tests/simple-widget.test.tsx new file mode 100644 index 0000000..e2573e0 --- /dev/null +++ b/Approval_Pending/tests/simple-widget.test.tsx @@ -0,0 +1,14 @@ +import { React } from 'jimu-core' +import _Widget from '../src/runtime/widget' +import { widgetRender, wrapWidget } from 'jimu-for-test' + +const render = widgetRender() +describe('test simple widget', () => { + it('simple test', () => { + const Widget = wrapWidget(_Widget, { + config: { exampleConfigProperty: 'a' } + }) + const { queryByText } = render() + expect(queryByText('exampleConfigProperty: a').tagName).toBe('P') + }) +})