Skip to content

Commit 56ffc8a

Browse files
committed
[refactor] replace Scroll List with Search List for NGO index page
[fix] many GitHub copilot bugs [optimize] update Upstream packages
1 parent 23feba1 commit 56ffc8a

15 files changed

Lines changed: 351 additions & 529 deletions

File tree

.gitignore

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,7 @@ yarn-debug.log*
2626
yarn-error.log*
2727

2828
# local env files
29-
.env.local
30-
.env.development.local
31-
.env.test.local
32-
.env.production.local
29+
.env*local
3330

3431
# vercel
3532
.vercel

components/Map/CityStatisticMap.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import systemStore from '../../models/System';
1010
const ChinaMap = dynamic(() => import('./ChinaMap'), { ssr: false });
1111

1212
export interface CityStatisticMapProps {
13-
data: OrganizationStatistic['city'];
13+
data: OrganizationStatistic['coverageArea'];
1414
onChange?: (city: string) => any;
1515
}
1616

@@ -60,4 +60,4 @@ export class CityStatisticMap extends ObservedComponent<CityStatisticMapProps> {
6060
/>
6161
);
6262
}
63-
}
63+
}

components/Navigator/MainNavigator.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ const topNavBarMenu = ({ t }: typeof i18n): MenuItem[] => [
5555
{
5656
title: t('ngo'),
5757
subs: [
58-
{ href: '/ngo', title: t('china_public_interest_map') },
58+
{ href: '/ngo', title: t('China_NGO_Map') },
5959
{ href: '/ngo/landscape', title: t('china_public_interest_landscape') },
6060
{
6161
href: 'https://open-source-bazaar.feishu.cn/wiki/VGrMwiweVivWrHkTcvpcJTjjnoY',

components/Organization/ChinaPublicInterestMap.tsx

Lines changed: 0 additions & 129 deletions
This file was deleted.

models/Base.ts

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@ import { TableCellAttachment, TableCellMedia, TableCellValue } from 'mobx-lark';
66
import { DataObject } from 'mobx-restful';
77
import { isEmpty } from 'web-utility';
88

9-
import {
10-
API_Host,
11-
GithubToken,
12-
isServer,
13-
ProxyBaseURL,
14-
LARK_API_HOST,
15-
} from './configuration';
9+
import { API_Host, GithubToken, isServer, ProxyBaseURL, LARK_API_HOST } from './configuration';
1610

1711
export const ownClient = new HTTPClient({
1812
baseURI: `${API_Host}/api/`,
@@ -66,8 +60,13 @@ export function fileURLOf(field: TableCellValue, cache = false) {
6660
return URI;
6761
}
6862

69-
// Strapi client for China NGO Database
7063
export const strapiClient = new HTTPClient({
7164
baseURI: 'https://china-ngo-db.onrender.com/api/',
7265
responseType: 'json',
66+
}).use(({ request }, next) => {
67+
request.headers = {
68+
...request.headers,
69+
'Strapi-Response-Format': 'v4',
70+
};
71+
return next();
7372
});

models/Organization.ts

Lines changed: 36 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,54 @@
11
import { observable } from 'mobx';
2-
import { StrapiListModel, Base } from 'mobx-strapi';
3-
import { groupBy } from 'web-utility';
2+
import { Base, Searchable, SearchableFilter, StrapiListModel } from 'mobx-strapi';
3+
import { changeMonth, formatDate, groupBy } from 'web-utility';
44

5+
import { Organization } from '@open-source-bazaar/china-ngo-database';
56
import { strapiClient } from './Base';
67

7-
// Define the organization data structure similar to China NGO database
8-
export interface Organization extends Base {
9-
name: string;
10-
description?: string;
11-
type?: string;
12-
city?: string;
13-
province?: string;
14-
tags?: string[];
15-
website?: string;
16-
logo?: {
17-
data?: {
18-
attributes: {
19-
url: string;
20-
};
21-
};
22-
};
23-
year?: number;
24-
}
25-
268
export type OrganizationStatistic = Record<
27-
'type' | 'tag' | 'year' | 'city',
9+
'coverageArea' | 'locale' | 'entityType',
2810
Record<string, number>
2911
>;
3012

31-
export class OrganizationModel extends StrapiListModel<Organization> {
13+
export class OrganizationModel extends Searchable<Organization & Base>(StrapiListModel) {
3214
baseURI = 'organizations';
3315
client = strapiClient;
3416

17+
searchKeys = ['name', 'description', 'coverageArea'] as const;
18+
3519
@observable
3620
accessor categoryMap: Record<string, Organization[]> = {};
3721

22+
makeFilter(
23+
pageIndex: number,
24+
pageSize: number,
25+
{ keywords, ...filter }: SearchableFilter<Organization & Base>,
26+
) {
27+
if (keywords) return super.makeFilter(pageIndex, pageSize, { keywords, ...filter });
28+
29+
const meta = super.makeFilter(pageIndex, pageSize, filter);
30+
31+
const { establishedDate } = filter;
32+
33+
const timeRangeFilter =
34+
establishedDate?.length === 4
35+
? { $gte: `${establishedDate}-01-01`, $lt: `${+establishedDate + 1}-01-01` }
36+
: establishedDate?.length === 7
37+
? {
38+
$gte: `${establishedDate}-01`,
39+
$lte: `${formatDate(changeMonth(establishedDate, 1), 'YYYY-MM')}-01`,
40+
}
41+
: {};
42+
return { ...meta, filters: { ...meta.filters, establishedDate: timeRangeFilter } };
43+
}
44+
3845
async groupAllByTags() {
3946
const allData = await this.getAll();
4047

41-
return (this.categoryMap = groupBy(allData, ({ tags }) => tags?.[0] || 'Other'));
48+
return (this.categoryMap = groupBy(
49+
allData,
50+
({ services }) => services?.flatMap(({ serviceCategory }) => serviceCategory!) || [],
51+
));
4252
}
43-
}
53+
}
54+
export default new OrganizationModel();

models/System.ts

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
import { observable } from 'mobx';
22
import { BiSearchModelClass } from 'mobx-lark';
3-
import { BaseModel } from 'mobx-restful';
3+
import { BaseModel, DataObject, ListModel, toggle } from 'mobx-restful';
4+
import { Base, SearchableFilter } from 'mobx-strapi';
5+
import { Constructor } from 'web-utility';
6+
7+
import { ownClient } from './Base';
8+
import { OrganizationModel } from './Organization';
9+
10+
export type SearchModel<T extends DataObject = any> = ListModel<T, SearchableFilter<T>>;
411

512
export type SearchPageMeta = Pick<
613
InstanceType<BiSearchModelClass>,
@@ -10,7 +17,9 @@ export type SearchPageMeta = Pick<
1017
export type CityCoordinateMap = Record<string, [number, number]>;
1118

1219
export class SystemModel extends BaseModel {
13-
searchMap: Record<string, BiSearchModelClass> = {};
20+
searchMap = {
21+
NGO: OrganizationModel,
22+
} as Record<string, Constructor<SearchModel<Base>>>;
1423

1524
@observable
1625
accessor screenNarrow = false;
@@ -27,22 +36,14 @@ export class SystemModel extends BaseModel {
2736

2837
updateScreen = () =>
2938
(this.screenNarrow =
30-
globalThis.innerWidth < globalThis.innerHeight ||
31-
globalThis.innerWidth < 992);
39+
globalThis.innerWidth < globalThis.innerHeight || globalThis.innerWidth < 992);
3240

41+
@toggle('downloading')
3342
async getCityCoordinate() {
34-
// Placeholder for city coordinate data
35-
// In production, this would load from an API or static data
36-
this.cityCoordinate = {
37-
'北京': [116.4074, 39.9042],
38-
'上海': [121.4737, 31.2304],
39-
'广州': [113.2644, 23.1291],
40-
'深圳': [114.0579, 22.5431],
41-
'杭州': [120.1551, 30.2741],
42-
'成都': [104.0668, 30.5728],
43-
'武汉': [114.3054, 30.5931],
44-
'西安': [108.9402, 34.3416],
45-
};
43+
const { body } = await ownClient.get<CityCoordinateMap>(
44+
'https://idea2app.github.io/public-meta-data/china-city-coordinate.json',
45+
);
46+
return (this.cityCoordinate = body!);
4647
}
4748
}
4849

0 commit comments

Comments
 (0)