1- import { FC , useEffect , useRef } from 'react' ;
2- import { Card , Col , Container , Row , Spinner } from 'react-bootstrap' ;
1+ import { computed } from 'mobx' ;
2+ import { observer } from 'mobx-react' ;
3+ import { ObservedComponent } from 'mobx-react-helper' ;
4+ import dynamic from 'next/dynamic' ;
35
4- export interface MapProps {
5- data ?: { name : string ; city ?: string ; province ?: string ; latitude ?: number ; longitude ?: number } [ ] ;
6- loading ?: boolean ;
6+ import { OrganizationStatistic } from '../../models/Organization' ;
7+
8+ const ChinaMap = dynamic ( ( ) => import ( './ChinaMap' ) , { ssr : false } ) ;
9+
10+ export interface CityStatisticMapProps {
11+ data : OrganizationStatistic [ 'city' ] ;
12+ onChange ?: ( city : string ) => any ;
713}
814
9- export const Map : FC < MapProps > = ( { data = [ ] , loading = false } ) => {
10- const mapRef = useRef < HTMLDivElement > ( null ) ;
15+ @observer
16+ export class CityStatisticMap extends ObservedComponent < CityStatisticMapProps > {
17+ @computed
18+ get markers ( ) {
19+ const { data } = this . observedProps ;
20+
21+ return data . map ( ( { label : city , count } ) => ( {
22+ tooltip : `${ city } ${ count } ` ,
23+ position : [ 34.32 , 108.55 ] as [ number , number ] , // Default center for now
24+ } ) ) ;
25+ }
26+
27+ handleChange = ( { latlng : { lat, lng } } : any ) => {
28+ const { markers } = this ;
29+ const { tooltip } = markers . find ( ( { position : p } ) =>
30+ p instanceof Array && lat === p [ 0 ] && lng === p [ 1 ]
31+ ) || { } ;
32+ const [ city ] = tooltip ?. split ( / \s + / ) || [ ] ;
33+
34+ this . props . onChange ?.( city ) ;
35+ } ;
1136
12- useEffect ( ( ) => {
13- // Placeholder for actual map implementation
14- // This would integrate with a mapping library like Leaflet, AMap, or MapBox
15- } , [ ] ) ;
37+ render ( ) {
38+ const { markers } = this ;
1639
17- if ( loading ) {
1840 return (
19- < Container className = "d-flex justify-content-center align-items-center" style = { { minHeight : '400px' } } >
20- < Spinner animation = "border" role = "status" >
21- < span className = "visually-hidden" > Loading...</ span >
22- </ Spinner >
23- </ Container >
41+ < ChinaMap
42+ style = { { height : '70vh' } }
43+ center = { [ 34.32 , 108.55 ] }
44+ zoom = { 4 }
45+ markers = { markers }
46+ onMarkerClick = { this . handleChange }
47+ />
2448 ) ;
2549 }
26-
27- return (
28- < Container >
29- < Row >
30- < Col >
31- < Card >
32- < Card . Body >
33- < div
34- ref = { mapRef }
35- style = { {
36- width : '100%' ,
37- height : '500px' ,
38- backgroundColor : '#f8f9fa' ,
39- border : '1px solid #dee2e6' ,
40- borderRadius : '0.375rem' ,
41- position : 'relative' ,
42- display : 'flex' ,
43- alignItems : 'center' ,
44- justifyContent : 'center' ,
45- } }
46- >
47- < div className = "text-center text-muted" >
48- < h5 > Interactive Map Coming Soon</ h5 >
49- < p > Geographic visualization of { data . length } organizations</ p >
50- { data . length > 0 && (
51- < small >
52- Data includes organizations from{ ' ' }
53- { [ ...new Set ( data . map ( item => item . province || item . city ) . filter ( Boolean ) ) ] . length } { ' ' }
54- locations
55- </ small >
56- ) }
57- </ div >
58- </ div >
59- </ Card . Body >
60- </ Card >
61- </ Col >
62- </ Row >
63- </ Container >
64- ) ;
65- } ;
66-
67- export default Map ;
50+ }
0 commit comments