pak-geodata 0.2.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -392
- package/dist/areas/abbottabad.cjs +290 -0
- package/dist/areas/abbottabad.d.ts +3 -0
- package/dist/areas/abbottabad.d.ts.map +1 -0
- package/dist/areas/abbottabad.js +2 -0
- package/dist/areas/abbottabad.js.map +1 -0
- package/dist/areas/aliabad-hunza.cjs +205 -0
- package/dist/areas/aliabad-hunza.d.ts +3 -0
- package/dist/areas/aliabad-hunza.d.ts.map +1 -0
- package/dist/areas/aliabad-hunza.js +2 -0
- package/dist/areas/aliabad-hunza.js.map +1 -0
- package/dist/areas/bahawalpur.cjs +287 -0
- package/dist/areas/bahawalpur.d.ts +3 -0
- package/dist/areas/bahawalpur.d.ts.map +1 -0
- package/dist/areas/bahawalpur.js +2 -0
- package/dist/areas/bahawalpur.js.map +1 -0
- package/dist/areas/dera-ghazi-khan.cjs +246 -0
- package/dist/areas/dera-ghazi-khan.d.ts +3 -0
- package/dist/areas/dera-ghazi-khan.d.ts.map +1 -0
- package/dist/areas/dera-ghazi-khan.js +2 -0
- package/dist/areas/dera-ghazi-khan.js.map +1 -0
- package/dist/areas/dera-ismail-khan.cjs +204 -0
- package/dist/areas/dera-ismail-khan.d.ts +3 -0
- package/dist/areas/dera-ismail-khan.d.ts.map +1 -0
- package/dist/areas/dera-ismail-khan.js +2 -0
- package/dist/areas/dera-ismail-khan.js.map +1 -0
- package/dist/areas/faisalabad.cjs +353 -0
- package/dist/areas/gilgit.cjs +250 -0
- package/dist/areas/gilgit.d.ts +3 -0
- package/dist/areas/gilgit.d.ts.map +1 -0
- package/dist/areas/gilgit.js +2 -0
- package/dist/areas/gilgit.js.map +1 -0
- package/dist/areas/gujranwala.cjs +509 -0
- package/dist/areas/gujranwala.d.ts +3 -0
- package/dist/areas/gujranwala.d.ts.map +1 -0
- package/dist/areas/gujranwala.js +2 -0
- package/dist/areas/gujranwala.js.map +1 -0
- package/dist/areas/gujrat.cjs +247 -0
- package/dist/areas/gujrat.d.ts +3 -0
- package/dist/areas/gujrat.d.ts.map +1 -0
- package/dist/areas/gujrat.js +2 -0
- package/dist/areas/gujrat.js.map +1 -0
- package/dist/areas/gwadar.cjs +249 -0
- package/dist/areas/gwadar.d.ts +3 -0
- package/dist/areas/gwadar.d.ts.map +1 -0
- package/dist/areas/gwadar.js +2 -0
- package/dist/areas/gwadar.js.map +1 -0
- package/dist/areas/hub.cjs +205 -0
- package/dist/areas/hub.d.ts +3 -0
- package/dist/areas/hub.d.ts.map +1 -0
- package/dist/areas/hub.js +2 -0
- package/dist/areas/hub.js.map +1 -0
- package/dist/areas/hyderabad.cjs +603 -0
- package/dist/areas/hyderabad.d.ts +3 -0
- package/dist/areas/hyderabad.d.ts.map +1 -0
- package/dist/areas/hyderabad.js +2 -0
- package/dist/areas/hyderabad.js.map +1 -0
- package/dist/areas/islamabad.cjs +977 -0
- package/dist/areas/jacobabad.cjs +204 -0
- package/dist/areas/jacobabad.d.ts +3 -0
- package/dist/areas/jacobabad.d.ts.map +1 -0
- package/dist/areas/jacobabad.js +2 -0
- package/dist/areas/jacobabad.js.map +1 -0
- package/dist/areas/jhelum.cjs +247 -0
- package/dist/areas/jhelum.d.ts +3 -0
- package/dist/areas/jhelum.d.ts.map +1 -0
- package/dist/areas/jhelum.js +2 -0
- package/dist/areas/jhelum.js.map +1 -0
- package/dist/areas/karachi.cjs +1186 -0
- package/dist/areas/kasur.cjs +206 -0
- package/dist/areas/kasur.d.ts +3 -0
- package/dist/areas/kasur.d.ts.map +1 -0
- package/dist/areas/kasur.js +2 -0
- package/dist/areas/kasur.js.map +1 -0
- package/dist/areas/khuzdar.cjs +205 -0
- package/dist/areas/khuzdar.d.ts +3 -0
- package/dist/areas/khuzdar.d.ts.map +1 -0
- package/dist/areas/khuzdar.js +2 -0
- package/dist/areas/khuzdar.js.map +1 -0
- package/dist/areas/kohat.cjs +204 -0
- package/dist/areas/kohat.d.ts +3 -0
- package/dist/areas/kohat.d.ts.map +1 -0
- package/dist/areas/kohat.js +2 -0
- package/dist/areas/kohat.js.map +1 -0
- package/dist/areas/lahore.cjs +1220 -0
- package/dist/areas/larkana.cjs +245 -0
- package/dist/areas/larkana.d.ts +3 -0
- package/dist/areas/larkana.d.ts.map +1 -0
- package/dist/areas/larkana.js +2 -0
- package/dist/areas/larkana.js.map +1 -0
- package/dist/areas/mardan.cjs +246 -0
- package/dist/areas/mardan.d.ts +3 -0
- package/dist/areas/mardan.d.ts.map +1 -0
- package/dist/areas/mardan.js +2 -0
- package/dist/areas/mardan.js.map +1 -0
- package/dist/areas/mingora.cjs +248 -0
- package/dist/areas/mingora.d.ts +3 -0
- package/dist/areas/mingora.d.ts.map +1 -0
- package/dist/areas/mingora.js +2 -0
- package/dist/areas/mingora.js.map +1 -0
- package/dist/areas/mirpur-khas.cjs +203 -0
- package/dist/areas/mirpur-khas.d.ts +3 -0
- package/dist/areas/mirpur-khas.d.ts.map +1 -0
- package/dist/areas/mirpur-khas.js +2 -0
- package/dist/areas/mirpur-khas.js.map +1 -0
- package/dist/areas/mirpur.cjs +252 -0
- package/dist/areas/mirpur.d.ts +3 -0
- package/dist/areas/mirpur.d.ts.map +1 -0
- package/dist/areas/mirpur.js +2 -0
- package/dist/areas/mirpur.js.map +1 -0
- package/dist/areas/multan.cjs +642 -0
- package/dist/areas/multan.d.ts +3 -0
- package/dist/areas/multan.d.ts.map +1 -0
- package/dist/areas/multan.js +2 -0
- package/dist/areas/multan.js.map +1 -0
- package/dist/areas/muzaffarabad.cjs +247 -0
- package/dist/areas/muzaffarabad.d.ts +3 -0
- package/dist/areas/muzaffarabad.d.ts.map +1 -0
- package/dist/areas/muzaffarabad.js +2 -0
- package/dist/areas/muzaffarabad.js.map +1 -0
- package/dist/areas/nawabshah.cjs +246 -0
- package/dist/areas/nawabshah.d.ts +3 -0
- package/dist/areas/nawabshah.d.ts.map +1 -0
- package/dist/areas/nawabshah.js +2 -0
- package/dist/areas/nawabshah.js.map +1 -0
- package/dist/areas/okara.cjs +204 -0
- package/dist/areas/okara.d.ts +3 -0
- package/dist/areas/okara.d.ts.map +1 -0
- package/dist/areas/okara.js +2 -0
- package/dist/areas/okara.js.map +1 -0
- package/dist/areas/peshawar.cjs +648 -0
- package/dist/areas/peshawar.d.ts +3 -0
- package/dist/areas/peshawar.d.ts.map +1 -0
- package/dist/areas/peshawar.js +2 -0
- package/dist/areas/peshawar.js.map +1 -0
- package/dist/areas/quetta.cjs +464 -0
- package/dist/areas/quetta.d.ts +3 -0
- package/dist/areas/quetta.d.ts.map +1 -0
- package/dist/areas/quetta.js +2 -0
- package/dist/areas/quetta.js.map +1 -0
- package/dist/areas/rahim-yar-khan.cjs +245 -0
- package/dist/areas/rahim-yar-khan.d.ts +3 -0
- package/dist/areas/rahim-yar-khan.d.ts.map +1 -0
- package/dist/areas/rahim-yar-khan.js +2 -0
- package/dist/areas/rahim-yar-khan.js.map +1 -0
- package/dist/areas/rawalakot.cjs +202 -0
- package/dist/areas/rawalakot.d.ts +3 -0
- package/dist/areas/rawalakot.d.ts.map +1 -0
- package/dist/areas/rawalakot.js +2 -0
- package/dist/areas/rawalakot.js.map +1 -0
- package/dist/areas/rawalpindi.cjs +484 -0
- package/dist/areas/sahiwal.cjs +246 -0
- package/dist/areas/sahiwal.d.ts +3 -0
- package/dist/areas/sahiwal.d.ts.map +1 -0
- package/dist/areas/sahiwal.js +2 -0
- package/dist/areas/sahiwal.js.map +1 -0
- package/dist/areas/sargodha.cjs +290 -0
- package/dist/areas/sargodha.d.ts +3 -0
- package/dist/areas/sargodha.d.ts.map +1 -0
- package/dist/areas/sargodha.js +2 -0
- package/dist/areas/sargodha.js.map +1 -0
- package/dist/areas/sheikhupura.cjs +245 -0
- package/dist/areas/sheikhupura.d.ts +3 -0
- package/dist/areas/sheikhupura.d.ts.map +1 -0
- package/dist/areas/sheikhupura.js +2 -0
- package/dist/areas/sheikhupura.js.map +1 -0
- package/dist/areas/sialkot.cjs +335 -0
- package/dist/areas/sialkot.d.ts +3 -0
- package/dist/areas/sialkot.d.ts.map +1 -0
- package/dist/areas/sialkot.js +2 -0
- package/dist/areas/sialkot.js.map +1 -0
- package/dist/areas/skardu.cjs +249 -0
- package/dist/areas/skardu.d.ts +3 -0
- package/dist/areas/skardu.d.ts.map +1 -0
- package/dist/areas/skardu.js +2 -0
- package/dist/areas/skardu.js.map +1 -0
- package/dist/areas/sukkur.cjs +289 -0
- package/dist/areas/sukkur.d.ts +3 -0
- package/dist/areas/sukkur.d.ts.map +1 -0
- package/dist/areas/sukkur.js +2 -0
- package/dist/areas/sukkur.js.map +1 -0
- package/dist/areas/turbat.cjs +203 -0
- package/dist/areas/turbat.d.ts +3 -0
- package/dist/areas/turbat.d.ts.map +1 -0
- package/dist/areas/turbat.js +2 -0
- package/dist/areas/turbat.js.map +1 -0
- package/dist/areas/wah-cantt.cjs +205 -0
- package/dist/areas/wah-cantt.d.ts +3 -0
- package/dist/areas/wah-cantt.d.ts.map +1 -0
- package/dist/areas/wah-cantt.js +2 -0
- package/dist/areas/wah-cantt.js.map +1 -0
- package/dist/data/areas/abbottabad.d.ts +3 -0
- package/dist/data/areas/abbottabad.d.ts.map +1 -0
- package/dist/data/areas/abbottabad.js +260 -0
- package/dist/data/areas/abbottabad.js.map +1 -0
- package/dist/data/areas/aliabad-hunza.d.ts +3 -0
- package/dist/data/areas/aliabad-hunza.d.ts.map +1 -0
- package/dist/data/areas/aliabad-hunza.js +175 -0
- package/dist/data/areas/aliabad-hunza.js.map +1 -0
- package/dist/data/areas/bahawalpur.d.ts +3 -0
- package/dist/data/areas/bahawalpur.d.ts.map +1 -0
- package/dist/data/areas/bahawalpur.js +257 -0
- package/dist/data/areas/bahawalpur.js.map +1 -0
- package/dist/data/areas/dera-ghazi-khan.d.ts +3 -0
- package/dist/data/areas/dera-ghazi-khan.d.ts.map +1 -0
- package/dist/data/areas/dera-ghazi-khan.js +216 -0
- package/dist/data/areas/dera-ghazi-khan.js.map +1 -0
- package/dist/data/areas/dera-ismail-khan.d.ts +3 -0
- package/dist/data/areas/dera-ismail-khan.d.ts.map +1 -0
- package/dist/data/areas/dera-ismail-khan.js +174 -0
- package/dist/data/areas/dera-ismail-khan.js.map +1 -0
- package/dist/data/areas/faisalabad.d.ts.map +1 -1
- package/dist/data/areas/faisalabad.js +353 -0
- package/dist/data/areas/faisalabad.js.map +1 -1
- package/dist/data/areas/gilgit.d.ts +3 -0
- package/dist/data/areas/gilgit.d.ts.map +1 -0
- package/dist/data/areas/gilgit.js +220 -0
- package/dist/data/areas/gilgit.js.map +1 -0
- package/dist/data/areas/gujranwala.d.ts +3 -0
- package/dist/data/areas/gujranwala.d.ts.map +1 -0
- package/dist/data/areas/gujranwala.js +479 -0
- package/dist/data/areas/gujranwala.js.map +1 -0
- package/dist/data/areas/gujrat.d.ts +3 -0
- package/dist/data/areas/gujrat.d.ts.map +1 -0
- package/dist/data/areas/gujrat.js +217 -0
- package/dist/data/areas/gujrat.js.map +1 -0
- package/dist/data/areas/gwadar.d.ts +3 -0
- package/dist/data/areas/gwadar.d.ts.map +1 -0
- package/dist/data/areas/gwadar.js +219 -0
- package/dist/data/areas/gwadar.js.map +1 -0
- package/dist/data/areas/hub.d.ts +3 -0
- package/dist/data/areas/hub.d.ts.map +1 -0
- package/dist/data/areas/hub.js +175 -0
- package/dist/data/areas/hub.js.map +1 -0
- package/dist/data/areas/hyderabad.d.ts +3 -0
- package/dist/data/areas/hyderabad.d.ts.map +1 -0
- package/dist/data/areas/hyderabad.js +573 -0
- package/dist/data/areas/hyderabad.js.map +1 -0
- package/dist/data/areas/index.d.ts +38 -1
- package/dist/data/areas/index.d.ts.map +1 -1
- package/dist/data/areas/index.js +76 -2
- package/dist/data/areas/index.js.map +1 -1
- package/dist/data/areas/islamabad.d.ts.map +1 -1
- package/dist/data/areas/islamabad.js +977 -0
- package/dist/data/areas/islamabad.js.map +1 -1
- package/dist/data/areas/jacobabad.d.ts +3 -0
- package/dist/data/areas/jacobabad.d.ts.map +1 -0
- package/dist/data/areas/jacobabad.js +174 -0
- package/dist/data/areas/jacobabad.js.map +1 -0
- package/dist/data/areas/jhelum.d.ts +3 -0
- package/dist/data/areas/jhelum.d.ts.map +1 -0
- package/dist/data/areas/jhelum.js +217 -0
- package/dist/data/areas/jhelum.js.map +1 -0
- package/dist/data/areas/karachi.d.ts.map +1 -1
- package/dist/data/areas/karachi.js +1186 -0
- package/dist/data/areas/karachi.js.map +1 -1
- package/dist/data/areas/kasur.d.ts +3 -0
- package/dist/data/areas/kasur.d.ts.map +1 -0
- package/dist/data/areas/kasur.js +176 -0
- package/dist/data/areas/kasur.js.map +1 -0
- package/dist/data/areas/khuzdar.d.ts +3 -0
- package/dist/data/areas/khuzdar.d.ts.map +1 -0
- package/dist/data/areas/khuzdar.js +175 -0
- package/dist/data/areas/khuzdar.js.map +1 -0
- package/dist/data/areas/kohat.d.ts +3 -0
- package/dist/data/areas/kohat.d.ts.map +1 -0
- package/dist/data/areas/kohat.js +174 -0
- package/dist/data/areas/kohat.js.map +1 -0
- package/dist/data/areas/lahore.d.ts.map +1 -1
- package/dist/data/areas/lahore.js +1220 -0
- package/dist/data/areas/lahore.js.map +1 -1
- package/dist/data/areas/larkana.d.ts +3 -0
- package/dist/data/areas/larkana.d.ts.map +1 -0
- package/dist/data/areas/larkana.js +215 -0
- package/dist/data/areas/larkana.js.map +1 -0
- package/dist/data/areas/mardan.d.ts +3 -0
- package/dist/data/areas/mardan.d.ts.map +1 -0
- package/dist/data/areas/mardan.js +216 -0
- package/dist/data/areas/mardan.js.map +1 -0
- package/dist/data/areas/mingora.d.ts +3 -0
- package/dist/data/areas/mingora.d.ts.map +1 -0
- package/dist/data/areas/mingora.js +218 -0
- package/dist/data/areas/mingora.js.map +1 -0
- package/dist/data/areas/mirpur-khas.d.ts +3 -0
- package/dist/data/areas/mirpur-khas.d.ts.map +1 -0
- package/dist/data/areas/mirpur-khas.js +173 -0
- package/dist/data/areas/mirpur-khas.js.map +1 -0
- package/dist/data/areas/mirpur.d.ts +3 -0
- package/dist/data/areas/mirpur.d.ts.map +1 -0
- package/dist/data/areas/mirpur.js +222 -0
- package/dist/data/areas/mirpur.js.map +1 -0
- package/dist/data/areas/multan.d.ts +3 -0
- package/dist/data/areas/multan.d.ts.map +1 -0
- package/dist/data/areas/multan.js +612 -0
- package/dist/data/areas/multan.js.map +1 -0
- package/dist/data/areas/muzaffarabad.d.ts +3 -0
- package/dist/data/areas/muzaffarabad.d.ts.map +1 -0
- package/dist/data/areas/muzaffarabad.js +217 -0
- package/dist/data/areas/muzaffarabad.js.map +1 -0
- package/dist/data/areas/nawabshah.d.ts +3 -0
- package/dist/data/areas/nawabshah.d.ts.map +1 -0
- package/dist/data/areas/nawabshah.js +216 -0
- package/dist/data/areas/nawabshah.js.map +1 -0
- package/dist/data/areas/okara.d.ts +3 -0
- package/dist/data/areas/okara.d.ts.map +1 -0
- package/dist/data/areas/okara.js +174 -0
- package/dist/data/areas/okara.js.map +1 -0
- package/dist/data/areas/peshawar.d.ts +3 -0
- package/dist/data/areas/peshawar.d.ts.map +1 -0
- package/dist/data/areas/peshawar.js +618 -0
- package/dist/data/areas/peshawar.js.map +1 -0
- package/dist/data/areas/quetta.d.ts +3 -0
- package/dist/data/areas/quetta.d.ts.map +1 -0
- package/dist/data/areas/quetta.js +434 -0
- package/dist/data/areas/quetta.js.map +1 -0
- package/dist/data/areas/rahim-yar-khan.d.ts +3 -0
- package/dist/data/areas/rahim-yar-khan.d.ts.map +1 -0
- package/dist/data/areas/rahim-yar-khan.js +215 -0
- package/dist/data/areas/rahim-yar-khan.js.map +1 -0
- package/dist/data/areas/rawalakot.d.ts +3 -0
- package/dist/data/areas/rawalakot.d.ts.map +1 -0
- package/dist/data/areas/rawalakot.js +172 -0
- package/dist/data/areas/rawalakot.js.map +1 -0
- package/dist/data/areas/rawalpindi.d.ts.map +1 -1
- package/dist/data/areas/rawalpindi.js +484 -0
- package/dist/data/areas/rawalpindi.js.map +1 -1
- package/dist/data/areas/sahiwal.d.ts +3 -0
- package/dist/data/areas/sahiwal.d.ts.map +1 -0
- package/dist/data/areas/sahiwal.js +216 -0
- package/dist/data/areas/sahiwal.js.map +1 -0
- package/dist/data/areas/sargodha.d.ts +3 -0
- package/dist/data/areas/sargodha.d.ts.map +1 -0
- package/dist/data/areas/sargodha.js +260 -0
- package/dist/data/areas/sargodha.js.map +1 -0
- package/dist/data/areas/sheikhupura.d.ts +3 -0
- package/dist/data/areas/sheikhupura.d.ts.map +1 -0
- package/dist/data/areas/sheikhupura.js +215 -0
- package/dist/data/areas/sheikhupura.js.map +1 -0
- package/dist/data/areas/sialkot.d.ts +3 -0
- package/dist/data/areas/sialkot.d.ts.map +1 -0
- package/dist/data/areas/sialkot.js +305 -0
- package/dist/data/areas/sialkot.js.map +1 -0
- package/dist/data/areas/skardu.d.ts +3 -0
- package/dist/data/areas/skardu.d.ts.map +1 -0
- package/dist/data/areas/skardu.js +219 -0
- package/dist/data/areas/skardu.js.map +1 -0
- package/dist/data/areas/sukkur.d.ts +3 -0
- package/dist/data/areas/sukkur.d.ts.map +1 -0
- package/dist/data/areas/sukkur.js +259 -0
- package/dist/data/areas/sukkur.js.map +1 -0
- package/dist/data/areas/turbat.d.ts +3 -0
- package/dist/data/areas/turbat.d.ts.map +1 -0
- package/dist/data/areas/turbat.js +173 -0
- package/dist/data/areas/turbat.js.map +1 -0
- package/dist/data/areas/wah-cantt.d.ts +3 -0
- package/dist/data/areas/wah-cantt.d.ts.map +1 -0
- package/dist/data/areas/wah-cantt.js +175 -0
- package/dist/data/areas/wah-cantt.js.map +1 -0
- package/dist/data/cities.js +42 -42
- package/dist/data/cities.js.map +1 -1
- package/dist/hierarchy.cjs +15862 -2163
- package/dist/index.cjs +15862 -2163
- package/dist/search.d.ts +3 -3
- package/dist/search.js +3 -3
- package/dist/search.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
`pak-geodata` is an open-source, production-grade TypeScript and JavaScript client library providing offline access to verified geographic data for Pakistan.
|
|
6
6
|
|
|
7
|
-
It covers all administrative provinces, 79 major and secondary cities, and
|
|
7
|
+
It covers all administrative provinces, 79 major and secondary cities, and 812 foundational metropolitan and regional areas across 42 cities.
|
|
8
8
|
|
|
9
9
|
Designed with **zero runtime dependencies**, strict geofencing, sub-millisecond lookups, and modular tree-shakeable subpath exports.
|
|
10
10
|
|
|
@@ -16,7 +16,7 @@ Designed with **zero runtime dependencies**, strict geofencing, sub-millisecond
|
|
|
16
16
|
- **Dual Module Support**: Full ESM (`import`) and CommonJS (`require`) support.
|
|
17
17
|
- **Bilingual Administrative Hierarchy (`PakLocationItem`)**: Unified administrative data structure connecting provinces, cities/districts, and areas with synchronized English and Urdu names.
|
|
18
18
|
- **Resilient O(1) Key Lookups**: Pre-indexed instant resolution via `getCityName(key, lang)` and `getAreaName(cityKey, areaKey, lang)` supporting case-insensitive slugs, title names, and colloquial aliases.
|
|
19
|
-
- **Lightweight PWA Subpath (`pak-geodata/hierarchy`)**: Code-split micro-bundle (< 5 KB gzipped) designed specifically for offline-first
|
|
19
|
+
- **Lightweight PWA Subpath (`pak-geodata/hierarchy`)**: Code-split micro-bundle (< 5 KB gzipped) designed specifically for offline-first Progressive Web Apps and reporting workflows.
|
|
20
20
|
- **Urdu Script & Numeral Normalization**: Robust bidirectional matching across Eastern Arabic numerals (`۳` vs `3`), Urdu letter variants (`ي` vs `ی`, `ك` vs `ک`), and diacritic stripping.
|
|
21
21
|
- **Subpath Tree-Shaking**: Import only the areas you need (e.g. `pak-geodata/areas/lahore`) to keep your bundle footprint under a few kilobytes.
|
|
22
22
|
- **Offline & Self-Contained**: All verified golden datasets are bundled with the library: no remote API calls or latency.
|
|
@@ -91,7 +91,7 @@ for (const area of lahoreAreas.slice(0, 5)) {
|
|
|
91
91
|
|
|
92
92
|
// Total verified areas in Pakistan
|
|
93
93
|
const allAreas = getAllAreas();
|
|
94
|
-
console.log(`Total verified areas: ${allAreas.length}`); //
|
|
94
|
+
console.log(`Total verified areas: ${allAreas.length}`); // 812
|
|
95
95
|
```
|
|
96
96
|
|
|
97
97
|
### 3. Modular Subpath Imports (Tree-Shaking)
|
|
@@ -106,11 +106,16 @@ import { lahoreAreas } from 'pak-geodata/areas/lahore';
|
|
|
106
106
|
import { karachiAreas } from 'pak-geodata/areas/karachi';
|
|
107
107
|
|
|
108
108
|
// Available subpaths:
|
|
109
|
-
// pak-geodata/areas/lahore
|
|
110
109
|
// pak-geodata/areas/karachi
|
|
110
|
+
// pak-geodata/areas/lahore
|
|
111
111
|
// pak-geodata/areas/islamabad
|
|
112
112
|
// pak-geodata/areas/rawalpindi
|
|
113
113
|
// pak-geodata/areas/faisalabad
|
|
114
|
+
// pak-geodata/areas/gujranwala
|
|
115
|
+
// pak-geodata/areas/multan
|
|
116
|
+
// pak-geodata/areas/hyderabad
|
|
117
|
+
// pak-geodata/areas/peshawar
|
|
118
|
+
// pak-geodata/areas/quetta
|
|
114
119
|
```
|
|
115
120
|
|
|
116
121
|
### 4. Intelligent Search
|
|
@@ -202,7 +207,7 @@ console.log(provinces[0]); // { id: 'punjab', nameEn: 'Punjab', nameUr: 'پنج
|
|
|
202
207
|
const punjabCities = getCitiesAsLocationItems('punjab');
|
|
203
208
|
console.log(`Punjab has ${punjabCities.length} verified cities/districts`);
|
|
204
209
|
|
|
205
|
-
// 3. City-scoped bilingual search (
|
|
210
|
+
// 3. City-scoped bilingual search (returns PakLocationItem[])
|
|
206
211
|
const results = searchAreas('Lahore', 'DHA 5', 'ur');
|
|
207
212
|
console.log(results[0]);
|
|
208
213
|
// { id: 'lahore-dha-phase-5', nameEn: 'DHA Phase 5', nameUr: 'ڈی ایچ اے فیز ۵', type: 'area', parentId: 'lahore', ... }
|
|
@@ -210,408 +215,34 @@ console.log(results[0]);
|
|
|
210
215
|
|
|
211
216
|
---
|
|
212
217
|
|
|
213
|
-
##
|
|
214
|
-
|
|
215
|
-
This guide documents the design patterns, data contracts, and implementation specifications built into `pak-geodata` for **Sanctuary**—an offline-first emergency rescue reporting and tracking Progressive Web App (PWA) operating across Pakistan.
|
|
216
|
-
|
|
217
|
-
### 1. Bilingual Administrative Hierarchy (`PakLocationItem`)
|
|
218
|
-
|
|
219
|
-
Emergency dispatching, disaster triage, and community reporting span multiple administrative tiers. Rather than handling disconnected data shapes for provinces, cities, and neighborhoods, `pak-geodata` provides a unified data contract: `PakLocationItem`.
|
|
220
|
-
|
|
221
|
-
```typescript
|
|
222
|
-
export type PakLocationType = 'province' | 'division' | 'district' | 'tehsil' | 'area';
|
|
223
|
-
|
|
224
|
-
export interface PakLocationItem {
|
|
225
|
-
id: string; // Canonical identifier (e.g. "punjab", "lahore", "lahore-gulberg-iii")
|
|
226
|
-
nameEn: string; // Standardized English name (e.g. "Punjab", "Lahore", "Gulberg III")
|
|
227
|
-
nameUr: string; // Native Urdu script (e.g. "پنجاب", "لاہور", "گلبرگ ۳")
|
|
228
|
-
type: PakLocationType; // Administrative level
|
|
229
|
-
parentId?: string; // Hierarchy linkage: area -> cityId -> provinceId
|
|
230
|
-
coordinates?: {
|
|
231
|
-
lat: number;
|
|
232
|
-
lng: number;
|
|
233
|
-
};
|
|
234
|
-
}
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
#### Hierarchy Traversal Functions
|
|
218
|
+
## Bilingual Hierarchy & Lightweight PWA Subpath
|
|
238
219
|
|
|
239
|
-
|
|
240
|
-
Returns all 7 provinces and federal territories (`type: 'province'`, `parentId: undefined`).
|
|
241
|
-
- **`getCitiesAsLocationItems(provinceId?: string): PakLocationItem[]`**
|
|
242
|
-
Returns all 79 verified municipal cities/districts (`type: 'district'`, `parentId: provinceId`). If `provinceId` is provided, filters cities belonging to that province.
|
|
243
|
-
- **`getAreasAsLocationItems(cityKey: string): PakLocationItem[]`**
|
|
244
|
-
Returns all verified areas in a given city (`type: 'area'`, `parentId: cityId`).
|
|
245
|
-
- **`toLocationItem(entity)`**
|
|
246
|
-
Universal converter accepting any `PakistanProvince`, `PakistanCity`, or `PakistanArea` object and mapping it to a standard `PakLocationItem`.
|
|
220
|
+
For applications requiring hierarchical administrative selection (Province → City/District → Area), `pak-geodata` provides a unified bilingual interface `PakLocationItem` and an ultra-lightweight `< 5 KB` gzipped subpath export:
|
|
247
221
|
|
|
248
222
|
```typescript
|
|
249
223
|
import {
|
|
250
224
|
getProvincesAsLocationItems,
|
|
251
225
|
getCitiesAsLocationItems,
|
|
252
|
-
getAreasAsLocationItems
|
|
253
|
-
|
|
226
|
+
getAreasAsLocationItems,
|
|
227
|
+
getCityName,
|
|
228
|
+
getAreaName,
|
|
229
|
+
searchAreas
|
|
230
|
+
} from 'pak-geodata/hierarchy'; // Ultra-lightweight subpath (< 5 KB gzipped)
|
|
254
231
|
|
|
255
|
-
//
|
|
232
|
+
// 1. Traverse administrative hierarchy
|
|
256
233
|
const provinces = getProvincesAsLocationItems();
|
|
257
|
-
|
|
258
|
-
// Load cities in Sindh
|
|
259
234
|
const sindhCities = getCitiesAsLocationItems('sindh');
|
|
260
|
-
|
|
261
|
-
// Load areas in Karachi
|
|
262
235
|
const karachiAreas = getAreasAsLocationItems('karachi');
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
---
|
|
266
|
-
|
|
267
|
-
### 2. Standardized English Storage & Real-Time Localized Display
|
|
268
236
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
**The Golden Pattern:**
|
|
273
|
-
1. **Database / Persistence Layer**: Always persist canonical, standardized English keys (`city: "Lahore"`, `location_area: "Gulberg"` or `"Gulberg III"`).
|
|
274
|
-
2. **Presentation / UI Layer**: Resolve these keys dynamically at render time into English or native Urdu Nastaliq using resilient O(1) lookup helpers.
|
|
275
|
-
|
|
276
|
-
#### Resilient O(1) Lookup Helpers
|
|
277
|
-
|
|
278
|
-
- **`getCityName(key: string, lang?: 'en' | 'ur'): string`**
|
|
279
|
-
Resolves a city slug (`"lahore"`), title-cased name (`"Lahore"`), or Urdu representation (`"لاہور"`) to the requested language.
|
|
280
|
-
- `getCityName("lahore", "ur")` $\rightarrow$ `"لاہور"`
|
|
281
|
-
- `getCityName("Lahore", "en")` $\rightarrow$ `"Lahore"`
|
|
282
|
-
- Resilient fallback: returns the raw `key` if the city is custom or unverified.
|
|
283
|
-
|
|
284
|
-
- **`getAreaName(cityKey: string, areaKey: string, lang?: 'en' | 'ur'): string`**
|
|
285
|
-
Resolves an area within a city using compound O(1) indexing (`${cityKey}:${areaKey}`). Supports:
|
|
286
|
-
- Canonical slugs: `"lahore-gulberg-iii"`
|
|
287
|
-
- Local slugs without city prefix: `"gulberg-iii"`
|
|
288
|
-
- Title names: `"Gulberg III"`
|
|
289
|
-
- Colloquial aliases: `"Gulberg"`, `"dha 5"`
|
|
290
|
-
- Urdu script queries: `"گلبرگ ۳"`
|
|
291
|
-
- Returns: `"Gulberg III"` (for `'en'`) or `"گلبرگ ۳"` (for `'ur'`).
|
|
292
|
-
- Resilient fallback: returns `areaKey` unchanged if unverified or custom-entered.
|
|
293
|
-
|
|
294
|
-
```typescript
|
|
295
|
-
import { getCityName, getAreaName } from 'pak-geodata';
|
|
296
|
-
|
|
297
|
-
// Standardized DB Record:
|
|
298
|
-
const record = { city: 'Lahore', location_area: 'Gulberg' };
|
|
299
|
-
|
|
300
|
-
// English display:
|
|
301
|
-
console.log(`${getAreaName(record.city, record.location_area, 'en')}, ${getCityName(record.city, 'en')}`);
|
|
302
|
-
// "Gulberg III, Lahore"
|
|
303
|
-
|
|
304
|
-
// Urdu display:
|
|
305
|
-
console.log(`${getCityName(record.city, 'ur')}، ${getAreaName(record.city, record.location_area, 'ur')}`);
|
|
306
|
-
// "لاہور، گلبرگ ۳"
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
---
|
|
310
|
-
|
|
311
|
-
### 3. Autocomplete Search with Overloaded `searchAreas` & Urdu Normalization
|
|
312
|
-
|
|
313
|
-
Sanctuary requires responsive autocomplete search scoped to a chosen city, returning typed `PakLocationItem[]` results.
|
|
314
|
-
|
|
315
|
-
#### Function Overload Signatures
|
|
316
|
-
|
|
317
|
-
`pak-geodata` supports two search calling styles:
|
|
318
|
-
|
|
319
|
-
```typescript
|
|
320
|
-
// 1. Sanctuary Overload (city-scoped, returns PakLocationItem[])
|
|
321
|
-
function searchAreas(cityKey: string, query: string, lang?: 'en' | 'ur'): PakLocationItem[];
|
|
322
|
-
|
|
323
|
-
// 2. Direct Named Function (same as Sanctuary overload)
|
|
324
|
-
function searchLocationItems(cityKey: string, query: string, lang?: 'en' | 'ur'): PakLocationItem[];
|
|
325
|
-
|
|
326
|
-
// 3. Classic GIS Overload (global or options-based, returns raw PakistanArea[])
|
|
327
|
-
function searchAreas(query: string, options?: SearchOptions, candidateAreas?: readonly PakistanArea[]): PakistanArea[];
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
#### Urdu Script & Numeral Normalization Engine
|
|
331
|
-
|
|
332
|
-
Mobile users and rescue field operators in Pakistan frequently switch between English, Urdu Nastaliq keyboards, and Arabic numeral settings. `pak-geodata` transparently pre-normalizes search terms with zero runtime performance cost:
|
|
333
|
-
- **Numeral Unification**: Eastern Arabic-Indic numerals (`۰-۹`), standard Arabic-Indic digits (`٠-٩`), and Western digits (`0-9`) match bidirectionally (`"گلبرگ ۳"` or `"گلبرگ ٣"` matches `"Gulberg 3"`).
|
|
334
|
-
- **Letter Variant Normalization**:
|
|
335
|
-
- Arabic Yeh (`ي`, U+064A) and Alef Maksura (`ى`, U+0649) map to Urdu Yeh (`ی`, U+06CC).
|
|
336
|
-
- Arabic Kaf (`ك`, U+0643) maps to Urdu Keheh (`ک`, U+06A9).
|
|
337
|
-
- Arabic Heh (`ه`, U+0647) maps to Urdu Goal Heh (`ہ`, U+06C1).
|
|
338
|
-
- **Diacritic / Tashkeel & Tatweel Stripping**: Removes Zabar, Zer, Pesh, Tanween, Tashdeed, Sukun, and Tatweel/Kashida (`[\u0640\u064B-\u065F\u0670]`).
|
|
339
|
-
|
|
340
|
-
```typescript
|
|
341
|
-
import { searchAreas } from 'pak-geodata';
|
|
237
|
+
// 2. Resilient O(1) lookups (English & native Urdu Nastaliq)
|
|
238
|
+
console.log(getCityName('lahore', 'ur')); // "لاہور"
|
|
239
|
+
console.log(getAreaName('lahore', 'Gulberg', 'ur')); // "گلبرگ ۳"
|
|
342
240
|
|
|
343
|
-
//
|
|
241
|
+
// 3. City-scoped autocomplete search
|
|
344
242
|
const results = searchAreas('Lahore', 'گلبرگ ۳', 'ur');
|
|
345
|
-
console.log(results[0].nameEn); // "Gulberg III"
|
|
346
|
-
console.log(results[0].nameUr); // "گلبرگ ۳"
|
|
347
243
|
```
|
|
348
244
|
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
### 4. Lightweight PWA Subpath (`pak-geodata/hierarchy`)
|
|
352
|
-
|
|
353
|
-
PWAs operating in low-connectivity 2G/3G environments must minimize JavaScript bundle sizes. The `./hierarchy` subpath contains administrative boundaries and O(1) lookup engines with **zero neighborhood geospatial overhead**:
|
|
354
|
-
|
|
355
|
-
```typescript
|
|
356
|
-
// ESM or CommonJS import
|
|
357
|
-
import {
|
|
358
|
-
getCityName,
|
|
359
|
-
getAreaName,
|
|
360
|
-
getProvincesAsLocationItems,
|
|
361
|
-
getCitiesAsLocationItems,
|
|
362
|
-
getAreasAsLocationItems,
|
|
363
|
-
searchLocationItems,
|
|
364
|
-
toLocationItem
|
|
365
|
-
} from 'pak-geodata/hierarchy';
|
|
366
|
-
```
|
|
367
|
-
|
|
368
|
-
- **Bundle footprint**: `< 15 KB` unminified, **`< 5 KB` gzipped**.
|
|
369
|
-
- Perfect for initial service worker caching, instant app shell startup, and background tracking views.
|
|
370
|
-
- City-specific areas can be dynamically loaded on demand when the user selects a city via `pak-geodata/areas/<city>`.
|
|
371
|
-
|
|
372
|
-
---
|
|
373
|
-
|
|
374
|
-
### 5. Production Implementation Examples
|
|
375
|
-
|
|
376
|
-
#### Example 1: Emergency Incident Reporting Form (`/report`)
|
|
377
|
-
|
|
378
|
-
This component demonstrates how a reporting intake form allows a user to select a city, search areas with real-time bilingual feedback, and submit standardized English keys into the database:
|
|
379
|
-
|
|
380
|
-
```typescript
|
|
381
|
-
import React, { useState, useMemo } from 'react';
|
|
382
|
-
import {
|
|
383
|
-
getCitiesAsLocationItems,
|
|
384
|
-
searchAreas,
|
|
385
|
-
type PakLocationItem
|
|
386
|
-
} from 'pak-geodata';
|
|
387
|
-
|
|
388
|
-
interface IncidentReportPayload {
|
|
389
|
-
reportNumber: string;
|
|
390
|
-
city: string; // Standardized English: e.g. "Lahore"
|
|
391
|
-
location_area: string; // Standardized English: e.g. "Gulberg III"
|
|
392
|
-
coordinates?: {
|
|
393
|
-
lat: number;
|
|
394
|
-
lng: number;
|
|
395
|
-
};
|
|
396
|
-
notes: string;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
interface IncidentReportFormProps {
|
|
400
|
-
lang: 'en' | 'ur';
|
|
401
|
-
onSubmitReport: (payload: IncidentReportPayload) => Promise<void>;
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
export function IncidentReportForm({ lang, onSubmitReport }: IncidentReportFormProps) {
|
|
405
|
-
const [selectedCityId, setSelectedCityId] = useState<string>('lahore');
|
|
406
|
-
const [areaQuery, setAreaQuery] = useState<string>('');
|
|
407
|
-
const [selectedArea, setSelectedArea] = useState<PakLocationItem | null>(null);
|
|
408
|
-
const [notes, setNotes] = useState<string>('');
|
|
409
|
-
const [isSubmitting, setIsSubmitting] = useState<boolean>(false);
|
|
410
|
-
|
|
411
|
-
// 1. Load city options formatted for current language
|
|
412
|
-
const cities = useMemo(() => getCitiesAsLocationItems(), []);
|
|
413
|
-
|
|
414
|
-
// 2. City-scoped bilingual search: handles Urdu script, Eastern numerals ('۳'), and aliases
|
|
415
|
-
const areaSuggestions = useMemo(() => {
|
|
416
|
-
if (!areaQuery.trim() || !selectedCityId) return [];
|
|
417
|
-
// Invokes overloaded Sanctuary signature: searchAreas(cityKey, query, lang)
|
|
418
|
-
return searchAreas(selectedCityId, areaQuery, lang);
|
|
419
|
-
}, [selectedCityId, areaQuery, lang]);
|
|
420
|
-
|
|
421
|
-
const handleSubmit = async (e: React.FormEvent) => {
|
|
422
|
-
e.preventDefault();
|
|
423
|
-
if (!selectedArea) return;
|
|
424
|
-
|
|
425
|
-
setIsSubmitting(true);
|
|
426
|
-
try {
|
|
427
|
-
const selectedCityObj = cities.find((c) => c.id === selectedCityId);
|
|
428
|
-
|
|
429
|
-
// 3. Persist standardized English keys to database / backend
|
|
430
|
-
const payload: IncidentReportPayload = {
|
|
431
|
-
reportNumber: `SANCTUARY-${Date.now().toString().slice(-6)}`,
|
|
432
|
-
city: selectedCityObj?.nameEn || selectedCityId, // Persist English: "Lahore"
|
|
433
|
-
location_area: selectedArea.nameEn, // Persist English: "Gulberg III"
|
|
434
|
-
coordinates: selectedArea.coordinates,
|
|
435
|
-
notes
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
await onSubmitReport(payload);
|
|
439
|
-
setAreaQuery('');
|
|
440
|
-
setSelectedArea(null);
|
|
441
|
-
setNotes('');
|
|
442
|
-
} finally {
|
|
443
|
-
setIsSubmitting(false);
|
|
444
|
-
}
|
|
445
|
-
};
|
|
446
|
-
|
|
447
|
-
return (
|
|
448
|
-
<form className="incident-form" onSubmit={handleSubmit} dir={lang === 'ur' ? 'rtl' : 'ltr'}>
|
|
449
|
-
<h2>{lang === 'ur' ? 'ایمرجنسی رپورٹ درج کریں' : 'Submit Emergency Report'}</h2>
|
|
450
|
-
|
|
451
|
-
{/* City Dropdown */}
|
|
452
|
-
<div className="form-group">
|
|
453
|
-
<label htmlFor="city-select">
|
|
454
|
-
{lang === 'ur' ? 'شہر منتخب کریں' : 'Select City'}
|
|
455
|
-
</label>
|
|
456
|
-
<select
|
|
457
|
-
id="city-select"
|
|
458
|
-
value={selectedCityId}
|
|
459
|
-
onChange={(e) => {
|
|
460
|
-
setSelectedCityId(e.target.value);
|
|
461
|
-
setSelectedArea(null);
|
|
462
|
-
setAreaQuery('');
|
|
463
|
-
}}
|
|
464
|
-
>
|
|
465
|
-
{cities.map((city) => (
|
|
466
|
-
<option key={city.id} value={city.id}>
|
|
467
|
-
{lang === 'ur' ? city.nameUr : city.nameEn}
|
|
468
|
-
</option>
|
|
469
|
-
))}
|
|
470
|
-
</select>
|
|
471
|
-
</div>
|
|
472
|
-
|
|
473
|
-
{/* Area Search / Combobox */}
|
|
474
|
-
<div className="form-group autocomplete-container">
|
|
475
|
-
<label htmlFor="area-search">
|
|
476
|
-
{lang === 'ur' ? 'علاقہ / سیکٹر / محلہ' : 'Area / Neighborhood'}
|
|
477
|
-
</label>
|
|
478
|
-
<input
|
|
479
|
-
id="area-search"
|
|
480
|
-
type="text"
|
|
481
|
-
value={areaQuery}
|
|
482
|
-
onChange={(e) => {
|
|
483
|
-
setAreaQuery(e.target.value);
|
|
484
|
-
setSelectedArea(null);
|
|
485
|
-
}}
|
|
486
|
-
placeholder={lang === 'ur' ? 'تلاش کریں (مثلاً: گلبرگ، ڈی ایچ اے، ۳)' : 'Search (e.g. Gulberg, DHA, Phase 5)'}
|
|
487
|
-
autoComplete="off"
|
|
488
|
-
/>
|
|
489
|
-
|
|
490
|
-
{/* Suggestion Dropdown */}
|
|
491
|
-
{areaSuggestions.length > 0 && !selectedArea && (
|
|
492
|
-
<ul className="suggestions-list">
|
|
493
|
-
{areaSuggestions.map((item) => (
|
|
494
|
-
<li
|
|
495
|
-
key={item.id}
|
|
496
|
-
onClick={() => {
|
|
497
|
-
setSelectedArea(item);
|
|
498
|
-
setAreaQuery(lang === 'ur' ? item.nameUr : item.nameEn);
|
|
499
|
-
}}
|
|
500
|
-
>
|
|
501
|
-
<span className="suggestion-primary">
|
|
502
|
-
{lang === 'ur' ? item.nameUr : item.nameEn}
|
|
503
|
-
</span>
|
|
504
|
-
<span className="suggestion-secondary">
|
|
505
|
-
{lang === 'ur' ? item.nameEn : item.nameUr}
|
|
506
|
-
</span>
|
|
507
|
-
</li>
|
|
508
|
-
))}
|
|
509
|
-
</ul>
|
|
510
|
-
)}
|
|
511
|
-
</div>
|
|
512
|
-
|
|
513
|
-
{/* Additional Notes */}
|
|
514
|
-
<div className="form-group">
|
|
515
|
-
<label htmlFor="notes">
|
|
516
|
-
{lang === 'ur' ? 'واقعے کی تفصیلات' : 'Incident Details'}
|
|
517
|
-
</label>
|
|
518
|
-
<textarea
|
|
519
|
-
id="notes"
|
|
520
|
-
value={notes}
|
|
521
|
-
onChange={(e) => setNotes(e.target.value)}
|
|
522
|
-
rows={3}
|
|
523
|
-
/>
|
|
524
|
-
</div>
|
|
525
|
-
|
|
526
|
-
<button type="submit" disabled={!selectedArea || isSubmitting}>
|
|
527
|
-
{isSubmitting
|
|
528
|
-
? (lang === 'ur' ? 'رپورٹ بھیجی جا رہی ہے...' : 'Submitting...')
|
|
529
|
-
: (lang === 'ur' ? 'ایمرجنسی ٹیم طلب کریں' : 'Request Emergency Rescue')}
|
|
530
|
-
</button>
|
|
531
|
-
</form>
|
|
532
|
-
);
|
|
533
|
-
}
|
|
534
|
-
```
|
|
535
|
-
|
|
536
|
-
---
|
|
537
|
-
|
|
538
|
-
#### Example 2: Emergency Incident Tracking View (`/report/track/:reportNumber`)
|
|
539
|
-
|
|
540
|
-
This component demonstrates how an incident tracking view loads a database record with standardized English fields and dynamically resolves the city and area names using the lightweight `< 5 KB` `pak-geodata/hierarchy` subpath:
|
|
541
|
-
|
|
542
|
-
```typescript
|
|
543
|
-
import React from 'react';
|
|
544
|
-
import {
|
|
545
|
-
getCityName,
|
|
546
|
-
getAreaName
|
|
547
|
-
} from 'pak-geodata/hierarchy'; // Ultra-lightweight subpath (< 5 KB gzipped)
|
|
548
|
-
|
|
549
|
-
export interface RescueIncidentRecord {
|
|
550
|
-
reportNumber: string;
|
|
551
|
-
city: string; // Stored English key: e.g. "Lahore"
|
|
552
|
-
location_area: string; // Stored English key or alias: e.g. "Gulberg"
|
|
553
|
-
status: 'RECEIVED' | 'DISPATCHED' | 'EN_ROUTE' | 'ON_SCENE' | 'RESOLVED';
|
|
554
|
-
reportedAt: string;
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
interface IncidentTrackingViewProps {
|
|
558
|
-
incident: RescueIncidentRecord;
|
|
559
|
-
lang: 'en' | 'ur';
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
export function IncidentTrackingView({ incident, lang }: IncidentTrackingViewProps) {
|
|
563
|
-
// O(1) Resilient Lookups: resolves slugs, English names, and aliases in O(1) time
|
|
564
|
-
// e.g. "Lahore" -> "لاہور", "Gulberg" -> "گلبرگ ۳"
|
|
565
|
-
const localizedCity = getCityName(incident.city, lang);
|
|
566
|
-
const localizedArea = getAreaName(incident.city, incident.location_area, lang);
|
|
567
|
-
|
|
568
|
-
const statusMap = {
|
|
569
|
-
RECEIVED: { en: 'Report Received', ur: 'رپورٹ موصول ہو چکی ہے', color: '#f59e0b' },
|
|
570
|
-
DISPATCHED: { en: 'Rescue Team Dispatched', ur: 'ریسکیو ٹیم روانہ ہو چکی ہے', color: '#3b82f6' },
|
|
571
|
-
EN_ROUTE: { en: 'En Route to Location', ur: 'ٹیم جائے وقوعہ کی طرف گامزن ہے', color: '#6366f1' },
|
|
572
|
-
ON_SCENE: { en: 'Team on Scene', ur: 'ٹیم جائے وقوعہ پر پہنچ چکی ہے', color: '#10b981' },
|
|
573
|
-
RESOLVED: { en: 'Incident Resolved', ur: 'ریسکیو مشن مکمل', color: '#059669' }
|
|
574
|
-
};
|
|
575
|
-
|
|
576
|
-
const currentStatus = statusMap[incident.status] || statusMap.RECEIVED;
|
|
577
|
-
|
|
578
|
-
return (
|
|
579
|
-
<div className="tracking-card" dir={lang === 'ur' ? 'rtl' : 'ltr'}>
|
|
580
|
-
<header className="tracking-header">
|
|
581
|
-
<span className="badge">
|
|
582
|
-
{lang === 'ur' ? 'رپورٹ نمبر:' : 'Report #:'} {incident.reportNumber}
|
|
583
|
-
</span>
|
|
584
|
-
<span className="timestamp">
|
|
585
|
-
{new Date(incident.reportedAt).toLocaleTimeString()}
|
|
586
|
-
</span>
|
|
587
|
-
</header>
|
|
588
|
-
|
|
589
|
-
{/* Localized Location Display */}
|
|
590
|
-
<div className="tracking-location-section">
|
|
591
|
-
<div className="location-pin">📍</div>
|
|
592
|
-
<div className="location-details">
|
|
593
|
-
<h3>
|
|
594
|
-
{lang === 'ur'
|
|
595
|
-
? `${localizedCity}، ${localizedArea}`
|
|
596
|
-
: `${localizedArea}, ${localizedCity}`}
|
|
597
|
-
</h3>
|
|
598
|
-
<p className="canonical-subtext">
|
|
599
|
-
{incident.location_area}, {incident.city}
|
|
600
|
-
</p>
|
|
601
|
-
</div>
|
|
602
|
-
</div>
|
|
603
|
-
|
|
604
|
-
{/* Real-time Status */}
|
|
605
|
-
<div className="tracking-status" style={{ borderColor: currentStatus.color }}>
|
|
606
|
-
<div className="status-indicator" style={{ backgroundColor: currentStatus.color }} />
|
|
607
|
-
<span className="status-label">
|
|
608
|
-
{currentStatus[lang]}
|
|
609
|
-
</span>
|
|
610
|
-
</div>
|
|
611
|
-
</div>
|
|
612
|
-
);
|
|
613
|
-
}
|
|
614
|
-
```
|
|
245
|
+
> 📖 **Full Implementation Recipe**: For complete React form components, real-time localized display patterns, and offline database persistence, see the [Bilingual Reporting & Tracking PWA Recipe](https://github.com/sohaibbinmohsin/pak-geodata/blob/main/docs/recipes/bilingual-reporting-pwa.md).
|
|
615
246
|
|
|
616
247
|
---
|
|
617
248
|
|