Skip to content

Commit 81a83e0

Browse files
CopilotTechQuery
andcommitted
Address PR review feedback: Fix .npmrc, restore Base.ts, update navigation, fix imports
Co-authored-by: TechQuery <19969570+TechQuery@users.noreply.github.com>
1 parent 20db4cc commit 81a83e0

16 files changed

Lines changed: 428 additions & 343 deletions

File tree

.npmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
auto-install-peers = false
2+
//npm.pkg.github.com/:_authToken=${GH_PAT}
23
@open-source-bazaar:registry=https://npm.pkg.github.com

components/Map/index.tsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import { FC, useEffect, useRef } from 'react';
2+
import { Card, Col, Container, Row, Spinner } from 'react-bootstrap';
3+
4+
export interface MapProps {
5+
data?: { name: string; city?: string; province?: string; latitude?: number; longitude?: number }[];
6+
loading?: boolean;
7+
}
8+
9+
export const Map: FC<MapProps> = ({ data = [], loading = false }) => {
10+
const mapRef = useRef<HTMLDivElement>(null);
11+
12+
useEffect(() => {
13+
// Placeholder for actual map implementation
14+
// This would integrate with a mapping library like Leaflet, AMap, or MapBox
15+
}, []);
16+
17+
if (loading) {
18+
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>
24+
);
25+
}
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;

components/Navigator/MainNavigator.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,14 @@ const topNavBarMenu = ({ t }: typeof i18n): MenuItem[] => [
5353
],
5454
},
5555
{
56-
title: t('china_public_interest_map'),
56+
title: t('ngo'),
5757
subs: [
58-
{ href: '/organization', title: t('china_public_interest_map') },
59-
{ href: '/organization/landscape', title: t('china_public_interest_landscape') },
58+
{ href: '/ngo', title: t('china_public_interest_map') },
59+
{ href: '/ngo/landscape', title: t('china_public_interest_landscape') },
60+
{
61+
href: 'https://open-source-bazaar.feishu.cn/wiki/VGrMwiweVivWrHkTcvpcJTjjnoY',
62+
title: t('open_source_public_interest_plan')
63+
},
6064
],
6165
},
6266
];
Lines changed: 107 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,117 @@
11
import { observer } from 'mobx-react';
2-
import { FC, useContext } from 'react';
3-
import { Badge,Card, Col, Row } from 'react-bootstrap';
2+
import { FC, useContext, useEffect, useState } from 'react';
3+
import { Badge, Card, Col, Container, Row } from 'react-bootstrap';
44

5-
import { Organization } from '../../models/Organization';
5+
import { Organization, OrganizationModel } from '../../models/Organization';
66
import { I18nContext } from '../../models/Translation';
77

8-
export interface ChinaPublicInterestLandscapeProps {
9-
tagMap: Record<string, Organization[]>;
10-
}
8+
const organizationModel = new OrganizationModel();
119

12-
export const ChinaPublicInterestLandscape: FC<ChinaPublicInterestLandscapeProps> = observer(
13-
({ tagMap }) => {
14-
const { t } = useContext(I18nContext);
10+
export const ChinaPublicInterestLandscape: FC = observer(() => {
11+
const { t } = useContext(I18nContext);
12+
const [tagMap, setTagMap] = useState<Record<string, Organization[]>>({});
13+
const [loading, setLoading] = useState(false);
1514

16-
const tagEntries = Object.entries(tagMap).sort(([, a], [, b]) => b.length - a.length);
15+
useEffect(() => {
16+
const loadData = async () => {
17+
setLoading(true);
18+
try {
19+
const groupedData = await organizationModel.groupAllByTags();
20+
setTagMap(groupedData);
21+
} finally {
22+
setLoading(false);
23+
}
24+
};
1725

18-
return (
19-
<div>
20-
{tagEntries.length === 0 && (
21-
<Card>
22-
<Card.Body className="text-center py-5">
23-
<Card.Title>{t('no_data_available')}</Card.Title>
24-
<Card.Text>{t('landscape_data_loading_message')}</Card.Text>
25-
</Card.Body>
26-
</Card>
27-
)}
26+
loadData();
27+
}, []);
2828

29-
{tagEntries.map(([tag, organizations]) => (
30-
<Card key={tag} className="mb-4">
31-
<Card.Header className="d-flex justify-content-between align-items-center">
32-
<h5 className="mb-0">{tag}</h5>
33-
<Badge bg="primary">{organizations.length} {t('organizations')}</Badge>
34-
</Card.Header>
35-
<Card.Body>
36-
<Row className="g-3">
37-
{organizations.map(org => (
38-
<Col key={org.id} md={6} lg={4}>
39-
<Card className="h-100">
40-
<Card.Body>
41-
<Card.Title className="h6">{org.name}</Card.Title>
42-
{org.description && (
43-
<Card.Text className="small text-muted">
44-
{org.description.length > 100
45-
? `${org.description.substring(0, 100)}...`
46-
: org.description}
47-
</Card.Text>
48-
)}
49-
<div className="mt-2">
50-
{org.city && (
51-
<Badge bg="secondary" className="me-1">
52-
{org.city}
53-
</Badge>
29+
const tagEntries = Object.entries(tagMap).sort(([, a], [, b]) => b.length - a.length);
30+
31+
return (
32+
<Container className="py-4">
33+
<Row className="mb-4">
34+
<Col>
35+
<h1>{t('china_public_interest_landscape')}</h1>
36+
</Col>
37+
</Row>
38+
39+
{loading && (
40+
<Row>
41+
<Col className="text-center">
42+
<div className="spinner-border" role="status">
43+
<span className="visually-hidden">Loading...</span>
44+
</div>
45+
</Col>
46+
</Row>
47+
)}
48+
49+
{!loading && tagEntries.length === 0 && (
50+
<Row>
51+
<Col>
52+
<Card>
53+
<Card.Body className="text-center py-5">
54+
<Card.Title>{t('no_data_available')}</Card.Title>
55+
<Card.Text>{t('landscape_data_loading_message')}</Card.Text>
56+
</Card.Body>
57+
</Card>
58+
</Col>
59+
</Row>
60+
)}
61+
62+
{!loading && tagEntries.map(([tag, organizations]) => (
63+
<Row key={tag} className="mb-4">
64+
<Col>
65+
<Card>
66+
<Card.Header className="d-flex justify-content-between align-items-center">
67+
<h5 className="mb-0">{tag}</h5>
68+
<Badge bg="primary">{organizations.length} {t('organizations')}</Badge>
69+
</Card.Header>
70+
<Card.Body>
71+
<Row className="g-3">
72+
{organizations.map(org => (
73+
<Col key={org.id} md={6} lg={4}>
74+
<Card className="h-100">
75+
<Card.Body>
76+
<Card.Title className="h6">{org.name}</Card.Title>
77+
{org.description && (
78+
<Card.Text className="small text-muted">
79+
{org.description.length > 100
80+
? `${org.description.substring(0, 100)}...`
81+
: org.description}
82+
</Card.Text>
5483
)}
55-
{org.type && (
56-
<Badge bg="info" className="me-1">
57-
{org.type}
58-
</Badge>
84+
<div className="mt-2">
85+
{org.city && (
86+
<Badge bg="secondary" className="me-1">
87+
{org.city}
88+
</Badge>
89+
)}
90+
{org.type && (
91+
<Badge bg="info" className="me-1">
92+
{org.type}
93+
</Badge>
94+
)}
95+
</div>
96+
{org.website && (
97+
<Card.Link
98+
href={org.website}
99+
target="_blank"
100+
className="small"
101+
>
102+
{t('visit_website')}
103+
</Card.Link>
59104
)}
60-
</div>
61-
{org.website && (
62-
<Card.Link
63-
href={org.website}
64-
target="_blank"
65-
className="small"
66-
>
67-
{t('visit_website')}
68-
</Card.Link>
69-
)}
70-
</Card.Body>
71-
</Card>
72-
</Col>
73-
))}
74-
</Row>
75-
</Card.Body>
76-
</Card>
77-
))}
78-
</div>
79-
);
80-
},
81-
);
105+
</Card.Body>
106+
</Card>
107+
</Col>
108+
))}
109+
</Row>
110+
</Card.Body>
111+
</Card>
112+
</Col>
113+
</Row>
114+
))}
115+
</Container>
116+
);
117+
});

0 commit comments

Comments
 (0)