Skip to content

Commit 563f9ad

Browse files
committed
chore: sitemap builder 리펙토링
1 parent c4acb6c commit 563f9ad

File tree

5 files changed

+62
-46
lines changed

5 files changed

+62
-46
lines changed

apps/pyconkr/src/App.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ export const App: React.FC = () => {
2525
const currentSiteMapDepth: (BackendAPISchemas.NestedSiteMapSchema | undefined)[] = [siteMapNode];
2626

2727
for (const routeCode of currentRouteCodes.splice(1)) {
28-
currentSiteMapDepth.push(currentSiteMapDepth.at(-1)?.children[routeCode]);
28+
const childrenMap = currentSiteMapDepth
29+
.at(-1)
30+
?.children?.reduce((acc, child) => ({ ...acc, [child.route_code]: child }), {} as Record<string, BackendAPISchemas.NestedSiteMapSchema>);
31+
currentSiteMapDepth.push(childrenMap?.[routeCode]);
2932
if (R.isNullish(currentSiteMapDepth.at(-1))) {
3033
console.warn(`Route not found in site map: ${routeCode}`);
3134
break;

packages/common/src/schemas/backendAPI.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace BackendAPISchemas {
3131
order: number;
3232
page: string;
3333
hide: boolean;
34-
children: { [key: string]: NestedSiteMapSchema };
34+
children: NestedSiteMapSchema[];
3535
};
3636

3737
export type SectionSchema = {

packages/common/src/schemas/backendAdminAPI.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,29 @@ namespace BackendAdminAPISchemas {
5656
body_en: string | null;
5757
};
5858

59+
export type FlattenedSiteMapSchema = {
60+
id: string;
61+
route_code: string;
62+
name_ko: string;
63+
name_en: string;
64+
order: number;
65+
parent_sitemap: string | null;
66+
page: string;
67+
hide: boolean;
68+
};
69+
70+
export type NestedSiteMapSchema = {
71+
id: string;
72+
route_code: string;
73+
name_ko: string;
74+
name_en: string;
75+
order: number;
76+
parent_sitemap: string | null;
77+
page: string;
78+
hide: boolean;
79+
children: NestedSiteMapSchema[];
80+
};
81+
5982
export type PageSectionBulkUpdateSchema = PageSectionSchema | Omit<PageSectionSchema, "id">;
6083
}
6184

packages/common/src/utils/api.ts

Lines changed: 32 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,50 @@
11
import * as R from "remeda";
22

3-
import BackendAPISchemas from "../schemas/backendAPI";
4-
5-
export const buildNestedSiteMap: (flattened: BackendAPISchemas.FlattenedSiteMapSchema[]) => {
6-
[key: string]: BackendAPISchemas.NestedSiteMapSchema;
7-
} = (flattened) => {
8-
const map: Record<string, BackendAPISchemas.NestedSiteMapSchema> = {};
9-
const roots: BackendAPISchemas.NestedSiteMapSchema[] = [];
3+
type GFlatSiteMap = {
4+
id: string;
5+
route_code: string;
6+
order: number;
7+
parent_sitemap: string | null;
8+
page: string;
9+
hide: boolean;
10+
};
11+
type GNestedSiteMap<T = GFlatSiteMap> = T & { children: GNestedSiteMap<T>[] };
12+
type MultiRootGNestedSiteMap<T = GFlatSiteMap> = { [key: string]: GNestedSiteMap<T> };
1013

11-
const siteMapIdRouteCodeMap = flattened.reduce(
12-
(acc, item) => {
13-
acc[item.id] = item.route_code;
14-
return acc;
15-
},
16-
{} as Record<string, string>
17-
);
14+
const _sortChildren = <T extends GFlatSiteMap>(children: GNestedSiteMap<T>[]) => {
15+
return children
16+
.sort((a, b) => a.order - b.order)
17+
.map(<Z extends GNestedSiteMap<T>>(child: Z): Z => ({ ...child, children: _sortChildren(child.children) }));
18+
};
1819

19-
flattened.forEach((item) => {
20-
map[item.id] = {
21-
...item,
22-
children: {},
23-
};
24-
});
20+
export const buildNestedSiteMap = <T extends GFlatSiteMap>(flat: T[]) => {
21+
const roots: GNestedSiteMap<T>[] = [];
22+
const flatWithChildren = flat.map((item) => ({ ...item, children: [] as GNestedSiteMap<T>[] }));
23+
const map = flatWithChildren.reduce((a, i) => ({ ...a, [i.id]: i }), {} as MultiRootGNestedSiteMap<T>);
2524

26-
flattened.forEach((item) => {
25+
flat.forEach((item) => {
2726
if (item.parent_sitemap) {
28-
map[item.parent_sitemap].children[siteMapIdRouteCodeMap[item.id]] = map[item.id];
27+
map[item.parent_sitemap].children.push(map[item.id]);
2928
} else {
3029
roots.push(map[item.id]);
3130
}
3231
});
3332

34-
return roots.reduce(
35-
(acc, item) => {
36-
acc[item.route_code] = item;
37-
return acc;
38-
},
39-
{} as Record<string, BackendAPISchemas.NestedSiteMapSchema>
40-
);
33+
return roots
34+
.map((root) => ({ ...root, children: _sortChildren(root.children) }))
35+
.reduce((a, i) => ({ ...a, [i.route_code]: i }), {} as MultiRootGNestedSiteMap<T>);
4136
};
4237

43-
export const findSiteMapUsingRoute = (
44-
route: string,
45-
siteMapData: BackendAPISchemas.NestedSiteMapSchema
46-
): BackendAPISchemas.NestedSiteMapSchema | null => {
47-
const currentRouteCodes = ["", ...route.split("/").filter((code) => !R.isEmpty(code))];
38+
export const buildFlatSiteMap = <T extends GNestedSiteMap>(nested: GNestedSiteMap<T>) => {
39+
const flat: T[] = [];
4840

49-
let currentSitemap: BackendAPISchemas.NestedSiteMapSchema | null | undefined = siteMapData.children[currentRouteCodes[0]];
50-
if (currentSitemap === undefined) return null;
41+
const traverse = (node: GNestedSiteMap<T>) => {
42+
flat.push(node);
43+
node.children.forEach(traverse);
44+
};
5145

52-
for (const routeCode of currentRouteCodes.slice(1)) {
53-
if ((currentSitemap = currentSitemap.children[routeCode] || null) === null) {
54-
break;
55-
}
56-
}
57-
return currentSitemap;
46+
traverse(nested);
47+
return flat;
5848
};
5949

6050
export const parseCss = (t: unknown): React.CSSProperties => {

packages/common/src/utils/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { buildNestedSiteMap as _buildNestedSiteMap, findSiteMapUsingRoute as _findSiteMapUsingRoute, parseCss as _parseCss } from "./api";
1+
import { buildFlatSiteMap as _buildFlatSiteMap, buildNestedSiteMap as _buildNestedSiteMap, parseCss as _parseCss } from "./api";
22
import { getCookie as _getCookie } from "./cookie";
33
import { getFormValue as _getFormValue, isFormValid as _isFormValid } from "./form";
44
import {
@@ -9,8 +9,8 @@ import {
99
import { isFilledString as _isFilledString, isValidHttpUrl as _isValidHttpUrl, rtrim as _rtrim } from "./string";
1010

1111
namespace Utils {
12+
export const buildFlatSiteMap = _buildFlatSiteMap;
1213
export const buildNestedSiteMap = _buildNestedSiteMap;
13-
export const findSiteMapUsingRoute = _findSiteMapUsingRoute;
1414
export const parseCss = _parseCss;
1515
export const getCookie = _getCookie;
1616
export const isFormValid = _isFormValid;

0 commit comments

Comments
 (0)