@axboot-mcp/mcp-server 1.0.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.
Files changed (78) hide show
  1. package/CLAUDE.md +119 -0
  2. package/MCP_TOOL_PLAN.md +710 -0
  3. package/MCP_USAGE.md +914 -0
  4. package/README.md +168 -0
  5. package/REPOSITORY_CONVENTIONS.md +250 -0
  6. package/SEARCH_PARAMS_MCP_TOOL_COMPLETE_PLAN.md +646 -0
  7. package/SEARCH_PARAMS_PLAN.md +2570 -0
  8. package/STORE_PATTERNS.md +1178 -0
  9. package/debug-dto.js +72 -0
  10. package/generate-banner-store.js +62 -0
  11. package/generation-plan.json +2176 -0
  12. package/generation-results.json +1817 -0
  13. package/package.json +45 -0
  14. package/scripts/batch-generate-all.js +159 -0
  15. package/scripts/batch-generate-mcp.js +329 -0
  16. package/scripts/batch-generate-stores-v2.js +272 -0
  17. package/scripts/batch-generate-stores.js +179 -0
  18. package/scripts/batch-plan.json +3810 -0
  19. package/scripts/batch-process.py +90 -0
  20. package/scripts/batch-regenerate.js +356 -0
  21. package/scripts/direct-generate.js +227 -0
  22. package/scripts/execute-batches.js +1911 -0
  23. package/scripts/generate-all-stores.js +144 -0
  24. package/scripts/generate-stores-mcp.js +161 -0
  25. package/scripts/generate-stores-v2.js +450 -0
  26. package/scripts/generate-stores-v3.js +412 -0
  27. package/scripts/generate-stores-v4.js +521 -0
  28. package/scripts/generate-stores.js +382 -0
  29. package/scripts/repos-to-process.json +1899 -0
  30. package/src/config/nh-layout-patterns.ts +166 -0
  31. package/src/docs/HOOK_GENERATION_PLAN.md +2226 -0
  32. package/src/docs/NH_STORE_PATTERNS.md +297 -0
  33. package/src/docs/README.md +216 -0
  34. package/src/docs/index.ts +28 -0
  35. package/src/docs/loader.ts +568 -0
  36. package/src/docs/patterns.json +419 -0
  37. package/src/docs/practical-examples.md +732 -0
  38. package/src/docs/quick-start.md +257 -0
  39. package/src/docs/requirements-analysis-guide.md +364 -0
  40. package/src/docs/rules.json +321 -0
  41. package/src/docs/store-pattern-analysis.md +664 -0
  42. package/src/docs/store-patterns-rules.md +1168 -0
  43. package/src/docs/store-patterns-usage-guide.md +1835 -0
  44. package/src/docs/troubleshooting.md +544 -0
  45. package/src/docs/type-selection-guide.md +572 -0
  46. package/src/docs//354/202/254/354/232/251/353/262/225/AntD-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +1515 -0
  47. package/src/docs//354/202/254/354/232/251/353/262/225/DataGrid-/354/202/254/354/232/251/353/262/225.md +866 -0
  48. package/src/docs//354/202/254/354/232/251/353/262/225/FormItem-/354/202/254/354/232/251/353/262/225.md +903 -0
  49. package/src/docs//354/202/254/354/232/251/353/262/225/FormModal-/354/202/254/354/232/251/353/262/225.md +1155 -0
  50. package/src/docs//354/202/254/354/232/251/353/262/225/MCP-/353/260/224/354/235/264/353/270/214/354/275/224/353/224/251-/352/260/200/354/235/264/353/223/234.md +1133 -0
  51. package/src/docs//354/202/254/354/232/251/353/262/225/MSW-Mock-/353/215/260/354/235/264/355/204/260-/354/202/254/354/232/251/353/262/225.md +579 -0
  52. package/src/docs//354/202/254/354/232/251/353/262/225/Search-/354/273/264/355/217/254/353/204/214/355/212/270-/354/202/254/354/232/251/353/262/225.md +738 -0
  53. package/src/docs//354/202/254/354/232/251/353/262/225/Store-/355/214/250/355/204/264-/354/202/254/354/232/251/353/262/225.md +1135 -0
  54. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/352/265/254/354/204/261-/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234/354/210/234/354/204/234.md +1805 -0
  55. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/352/260/234/353/260/234-/355/224/204/353/241/254/355/224/204/355/212/270-/352/260/200/354/235/264/353/223/234.md +946 -0
  56. package/src/docs//354/202/254/354/232/251/353/262/225//355/231/225/354/236/245/355/231/224/353/251/264/355/203/200/354/236/205/353/263/204-/354/203/201/354/204/270-/355/224/204/353/241/254/355/224/204/355/212/270/352/260/200/354/235/264/353/223/234.md +2422 -0
  57. package/src/features/store-features.ts +232 -0
  58. package/src/handlers/analyze-requirements.ts +403 -0
  59. package/src/handlers/analyze.ts +1373 -0
  60. package/src/handlers/generate-from-requirements.ts +250 -0
  61. package/src/handlers/generate-hook.ts +950 -0
  62. package/src/handlers/generate-interactive.ts +840 -0
  63. package/src/handlers/generate-listdatagrid.ts +521 -0
  64. package/src/handlers/generate-multi-stores.ts +577 -0
  65. package/src/handlers/generate-requirements-from-layout.ts +160 -0
  66. package/src/handlers/generate-search-params.ts +717 -0
  67. package/src/handlers/generate.ts +911 -0
  68. package/src/handlers/list-templates.ts +104 -0
  69. package/src/handlers/scan-metadata.ts +485 -0
  70. package/src/handlers/suggest-layout.ts +326 -0
  71. package/src/index.ts +959 -0
  72. package/src/prompts/search-params.md +793 -0
  73. package/src/templates/index.ts +107 -0
  74. package/src/templates/unified.ts +462 -0
  75. package/store-generation-error-patterns.md +225 -0
  76. package/test/useAgentStore.ts +136 -0
  77. package/test-server.js +78 -0
  78. package/tsconfig.json +20 -0
@@ -0,0 +1,521 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+
4
+ /**
5
+ * ListDataGrid 컴포넌트 생성 도구
6
+ * NH-FE-B 패턴 기반 ListDataGrid.tsx 파일을 생성합니다.
7
+ */
8
+ export interface GenerateListDataGridParams {
9
+ /** 생성할 ListDataGrid 파일 경로 (절대 경로) */
10
+ outputPath: string;
11
+ /** ListDataGrid 설정 */
12
+ config: ListDataGridConfig;
13
+ }
14
+
15
+ export interface ListDataGridConfig {
16
+ /** Store 이름 (예: useProductListStore) */
17
+ storeName: string;
18
+ /** DTO 타입 (예: ProductRes) */
19
+ dtoType: string;
20
+ /** 행 키 (예: id, prdCd) */
21
+ rowKey: string;
22
+ /** 선택 모드 */
23
+ selectionMode?: 'single' | 'multi' | 'none';
24
+ /** FormHeader 포함 여부 */
25
+ withFormHeader?: boolean;
26
+ /** 엑셀 다운로드 포함 여부 */
27
+ withExcel?: boolean;
28
+ /** 컬럼 정의 */
29
+ columns: ColumnConfig[];
30
+ /** onClickItem 동작 타입 */
31
+ onClickType?: 'modal' | 'link' | 'select' | 'none';
32
+ /** 추가적인 import */
33
+ extraImports?: string[];
34
+ }
35
+
36
+ export interface ColumnConfig {
37
+ /** 컬럼 키 (DTO 필드명) */
38
+ key: string;
39
+ /** 라벨 */
40
+ label: string;
41
+ /** 컬럼 타입 */
42
+ type?: 'rowNo' | 'title' | 'money' | 'date' | 'dateTime' | 'user' | 'selectable' | 'custom';
43
+ /** 정렬 */
44
+ align?: 'left' | 'center' | 'right';
45
+ /** 너비 */
46
+ width?: number;
47
+ /** itemRender 코드 (사용자 정의 렌더링) */
48
+ itemRender?: string;
49
+ /** 코드 변수명 (코드 변환시 사용) */
50
+ codeVar?: string;
51
+ }
52
+
53
+ /**
54
+ * ListDataGrid 컴포넌트 생성
55
+ */
56
+ export async function generateListDataGrid(params: GenerateListDataGridParams): Promise<{
57
+ content: Array<{ type: string; text: string }>;
58
+ }> {
59
+ const { outputPath, config } = params;
60
+
61
+ // 코드 생성
62
+ const code = generateListDataGridCode(config);
63
+
64
+ // 파일에 쓰기
65
+ const dir = path.dirname(outputPath);
66
+ if (!fs.existsSync(dir)) {
67
+ fs.mkdirSync(dir, { recursive: true });
68
+ }
69
+ fs.writeFileSync(outputPath, code, 'utf-8');
70
+
71
+ return {
72
+ content: [
73
+ {
74
+ type: 'text',
75
+ text: JSON.stringify({
76
+ success: true,
77
+ outputPath,
78
+ message: `ListDataGrid 파일이 생성되었습니다: ${outputPath}`,
79
+ nextSteps: `
80
+ ## 다음 단계
81
+
82
+ ### 1. App.tsx에 ListDataGrid import 추가
83
+ \`\`\`typescript
84
+ import { ListDataGrid } from "./ListDataGrid";
85
+ \`\`\`
86
+
87
+ ### 2. Store에 필요한 상태/액션 확인
88
+ 다음 상태가 Store에 있는지 확인하세요:
89
+
90
+ **필수:**
91
+ - listColWidths, listSortParams, listData, listPage, listSpinning
92
+ - setListColWidths, setListSortParams, changeListPage
93
+
94
+ **단일 선택 모드 시:**
95
+ - selectedItem, setSelectedItem
96
+
97
+ **다중 선택 모드 시:**
98
+ - checkedRowKeys, setCheckedRowKeys
99
+
100
+ **엑셀 다운로드 시:**
101
+ - excelSpinning, callExcelDownloadApi
102
+
103
+ ### 3. 컬럼 정의 완료
104
+ 생성된 코드에서 컬럼 배열을 완성하세요:
105
+ \`\`\`typescript
106
+ const { columns } = useDataGridColumns<DtoItem>(
107
+ [
108
+ { key: "${config.rowKey}", label: t("번호"), type: "rowNo" },
109
+ // TODO: 여기에 컬럼 추가
110
+ ${config.columns.map(c => `{ key: "${c.key}", label: t("${c.label}")${c.type ? `, type: "${c.type}"` : ''}${c.width ? `, width: ${c.width}` : ''}${c.align ? `, align: "${c.align}"` : ''} }`).join('\n ')}
111
+ ],
112
+ {
113
+ colWidths: listColWidths,
114
+ ${config.columns.some(c => c.codeVar) ? `deps: [${config.columns.filter(c => c.codeVar).map(c => c.codeVar).join(', ')}],` : ''}
115
+ }
116
+ );
117
+ \`\`\`
118
+
119
+ ### 4. onClickItem 핸들러 구현
120
+ onClickType이 "${config.onClickType || 'select'}"이므로 필요한 동작을 구현하세요.
121
+ `.trim(),
122
+ }),
123
+ },
124
+ ],
125
+ };
126
+ }
127
+
128
+ /**
129
+ * ListDataGrid 코드 생성
130
+ */
131
+ function generateListDataGridCode(config: ListDataGridConfig): string {
132
+ const {
133
+ storeName,
134
+ dtoType,
135
+ rowKey,
136
+ selectionMode = 'none',
137
+ withFormHeader = false,
138
+ withExcel = false,
139
+ columns,
140
+ onClickType = 'select',
141
+ extraImports = [],
142
+ } = config;
143
+
144
+ // Import 생성
145
+ const imports = generateImports(config, extraImports);
146
+
147
+ // Interface 생성
148
+ const interfaces = generateInterfaces(config);
149
+
150
+ // Store 연결
151
+ const storeConnections = generateStoreConnections(config);
152
+
153
+ // 컬럼 정의
154
+ const columnsDefinition = generateColumnsDefinition(config);
155
+
156
+ // 이벤트 핸들러
157
+ const eventHandlers = generateEventHandlers(config);
158
+
159
+ // FormHeader
160
+ const formHeader = generateFormHeader(config);
161
+
162
+ // DataGrid props
163
+ const dataGridProps = generateDataGridProps(config);
164
+
165
+ // Styled Components
166
+ const styledComponents = generateStyledComponents(config);
167
+
168
+ return `${imports}
169
+
170
+ ${interfaces}
171
+
172
+ export function ListDataGrid({}: Props) {
173
+ const { t } = useI18n();${withFormHeader || withExcel ? `
174
+ const { messageApi } = useAntApp();` : ''}
175
+
176
+ ${storeConnections}
177
+
178
+ ${eventHandlers}
179
+
180
+ ${columnsDefinition}
181
+
182
+ const sortedListData = useDataGridSortedList<DtoItem>(listData, listSortParams);
183
+
184
+ return (
185
+ ${formHeader}
186
+ <Container ref={containerRef}>
187
+ <DataGrid<DtoItem>
188
+ frozenColumnIndex={0}
189
+ width={containerWidth}
190
+ height={containerHeight}
191
+ columns={columns}
192
+ data={sortedListData}
193
+ spinning={listSpinning}
194
+ ${dataGridProps}
195
+ />
196
+ </Container>${withFormHeader ? '\n </>' : ''}
197
+ );
198
+ }
199
+
200
+ ${styledComponents}
201
+ `;
202
+ }
203
+
204
+ /**
205
+ * Import 생성
206
+ */
207
+ function generateImports(config: ListDataGridConfig, extraImports: string[] = []): string {
208
+ const imports: string[] = [
209
+ `import { AXDGChangeColumnsInfo, AXDGClickParams } from "@axboot/datagrid";`,
210
+ `import { DataGrid } from "@core/components/DataGrid";`,
211
+ `import ${config.withFormHeader || config.withExcel ? `{ useAntApp } from "@core/hooks";` : `""// { useAntApp } from "@core/hooks";`}${config.withFormHeader || config.withExcel ? '' : ' // 필요시 추가'}`,
212
+ `import { useDataGridColumns } from "@core/hooks/useDataGridColumns";`,
213
+ `import { useDataGridSortedList } from "@core/hooks/useDataGridSortedList";`,
214
+ `import { useContainerSize } from "@core/hooks/useContainerSize";`,
215
+ ];
216
+
217
+ if (config.withFormHeader) {
218
+ imports.push(`import { Button, Flex } from "antd";`);
219
+ imports.push(`import { IconDownload } from "components/icon";`);
220
+ }
221
+
222
+ imports.push(`import styled from "@emotion/styled";`);
223
+ imports.push(`import { useI18n } from "hooks";`);
224
+ imports.push(`import React from "react";`);
225
+ imports.push(`import { PageLayout } from "styles/pageStyled";`);
226
+ imports.push(`import { errorHandling } from "utils";`);
227
+ imports.push(`import { ${config.dtoType} } from "services";`);
228
+
229
+ // Store import
230
+ const storeFileName = config.storeName.replace(/^use/, '');
231
+ imports.push(`import { ${config.storeName} } from "./${storeFileName}";`);
232
+
233
+ // 컬럼 타입별 필요한 import
234
+ if (config.columns.some(c => c.type === 'money')) {
235
+ imports.push(`// import { formatterNumber } from "@core/utils"; // 금액 포맷 필요시`);
236
+ }
237
+ if (config.columns.some(c => c.type === 'date' || c.type === 'dateTime')) {
238
+ imports.push(`// import { formatterDate } from "@core/utils"; // 날짜 포맷 필요시`);
239
+ imports.push(`// import { DT_FORMAT } from "@types"; // 날짜 포맷 필요시`);
240
+ }
241
+
242
+ // 추가 imports
243
+ if (extraImports.length > 0) {
244
+ imports.push(...extraImports);
245
+ }
246
+
247
+ return imports.join('\n');
248
+ }
249
+
250
+ /**
251
+ * Interface 생성
252
+ */
253
+ function generateInterfaces(config: ListDataGridConfig): string {
254
+ return `interface DtoItem extends ${config.dtoType} {}
255
+
256
+ interface Props {}`;
257
+ }
258
+
259
+ /**
260
+ * Store 연결 생성
261
+ */
262
+ function generateStoreConnections(config: ListDataGridConfig): string {
263
+ const { storeName, selectionMode, withExcel } = config;
264
+
265
+ const connections: string[] = [
266
+ ` const listColWidths = ${storeName}((s) => s.listColWidths);`,
267
+ ` const listSortParams = ${storeName}((s) => s.listSortParams);`,
268
+ ` const listData = ${storeName}((s) => s.listData);`,
269
+ ` const listPage = ${storeName}((s) => s.listPage);`,
270
+ ` const listSpinning = ${storeName}((s) => s.listSpinning);`,
271
+ ` const setListColWidths = ${storeName}((s) => s.setListColWidths);`,
272
+ ` const setListSortParams = ${storeName}((s) => s.setListSortParams);`,
273
+ ` const changeListPage = ${storeName}((s) => s.changeListPage);`,
274
+ ];
275
+
276
+ // programFn
277
+ connections.push(` const programFn = ${storeName}((s) => s.programFn);`);
278
+
279
+ // 선택 모드별 추가 연결
280
+ if (selectionMode === 'single') {
281
+ connections.push(
282
+ ``,
283
+ ` // 단일 선택`,
284
+ ` const selectedItem = ${storeName}((s) => s.selectedItem);`,
285
+ ` const setSelectedItem = ${storeName}((s) => s.setSelectedItem);`,
286
+ );
287
+ } else if (selectionMode === 'multi') {
288
+ connections.push(
289
+ ``,
290
+ ` // 다중 선택`,
291
+ ` const checkedRowKeys = ${storeName}((s) => s.checkedRowKeys);`,
292
+ ` const setCheckedRowKeys = ${storeName}((s) => s.setCheckedRowKeys);`,
293
+ );
294
+ }
295
+
296
+ // 엑셀 다운로드
297
+ if (withExcel) {
298
+ connections.push(
299
+ ``,
300
+ ` // 엑셀 다운로드`,
301
+ ` const excelSpinning = ${storeName}((s) => s.excelSpinning);`,
302
+ ` const callExcelDownloadApi = ${storeName}((s) => s.callExcelDownloadApi);`,
303
+ );
304
+ }
305
+
306
+ // Container
307
+ connections.push(` const { containerRef, width: containerWidth, height: containerHeight } = useContainerSize();`);
308
+
309
+ return connections.join('\n');
310
+ }
311
+
312
+ /**
313
+ * 컬럼 정의 생성
314
+ */
315
+ function generateColumnsDefinition(config: ListDataGridConfig): string {
316
+ const { storeName, columns, rowKey } = config;
317
+
318
+ // 컬럼 배열 생성
319
+ const columnItems = columns.map(col => {
320
+ const { key, label, type, align, width, itemRender, codeVar } = col;
321
+
322
+ // itemRender가 있는 경우
323
+ if (itemRender) {
324
+ return ` { key: "${key}", label: t("${label}")${width ? `, width: ${width}` : ''}${align ? `, align: "${align}"` : ''}, itemRender: ${itemRender} }`;
325
+ }
326
+
327
+ // 코드 변환이 필요한 경우
328
+ if (codeVar) {
329
+ return ` { key: "${key}", label: t("${label}")${width ? `, width: ${width}` : ''}${align ? `, align: "${align}"` : ''}, itemRender: ({ value }) => ${codeVar}?.find(value)?.label ?? value }`;
330
+ }
331
+
332
+ // 타입이 있는 경우
333
+ if (type) {
334
+ return ` { key: "${key}", label: t("${label}"), type: "${type}"${width ? `, width: ${width}` : ''}${align ? `, align: "${align}"` : ''} }`;
335
+ }
336
+
337
+ // 기본
338
+ return ` { key: "${key}", label: t("${label}")${width ? `, width: ${width}` : ''}${align ? `, align: "${align}"` : ''} }`;
339
+ });
340
+
341
+ const hasCodeVar = columns.some(c => c.codeVar);
342
+
343
+ return ` const handleColumnsChange = React.useCallback(
344
+ (columnIndex: number | null, { columns }: AXDGChangeColumnsInfo<DtoItem>) => {
345
+ setListColWidths(columns.map((column) => column.width));
346
+ },
347
+ [setListColWidths],
348
+ );
349
+
350
+ const { columns } = useDataGridColumns<DtoItem>(
351
+ [
352
+ { key: "${rowKey}", label: t("번호"), type: "rowNo" },
353
+ ${columnItems.join(',\n')}
354
+ ],
355
+ {
356
+ colWidths: listColWidths,${hasCodeVar ? '\n deps: [' + columns.filter(c => c.codeVar).map(c => c.codeVar!).join(', ') + '],' : ''}
357
+ }
358
+ );`;
359
+ }
360
+
361
+ /**
362
+ * 이벤트 핸들러 생성
363
+ */
364
+ function generateEventHandlers(config: ListDataGridConfig): string {
365
+ const { storeName, onClickType, withExcel } = config;
366
+ const handlers: string[] = [];
367
+
368
+ // 엑셀 다운로드 핸들러
369
+ if (withExcel) {
370
+ handlers.push(
371
+ ` const handleExcelDownload = React.useCallback(async () => {
372
+ try {
373
+ await callExcelDownloadApi();
374
+ messageApi.success("엑셀 다운로드가 완료되었습니다.");
375
+ } catch (err) {
376
+ await errorHandling(err);
377
+ }
378
+ }, [callExcelDownloadApi, messageApi]);`,
379
+ );
380
+ }
381
+
382
+ // onClickItem 핸들러
383
+ if (onClickType === 'modal') {
384
+ handlers.push(
385
+ ``,
386
+ ` const onClickItem = React.useCallback(
387
+ async (params: AXDGClickParams<DtoItem>) => {
388
+ try {
389
+ // TODO: 모달 열기
390
+ // const data = await openFormModal({ query: params.item });
391
+ // if (data.save) {
392
+ // messageApi.info("저장되었습니다.");
393
+ // await callListApi();
394
+ // }
395
+ } catch (err) {
396
+ await errorHandling(err);
397
+ }
398
+ },
399
+ [callListApi, messageApi],
400
+ );`,
401
+ );
402
+ } else if (onClickType === 'link') {
403
+ handlers.push(
404
+ ``,
405
+ ` const onClickItem = React.useCallback(
406
+ async (params: AXDGClickParams<DtoItem>) => {
407
+ try {
408
+ // TODO: 링크 이동
409
+ // const menu = MENUS_LIST.find((m) => m.progId === "TARGET_PAGE");
410
+ // if (menu) linkByMenu(menu, { id: params.item.${config.rowKey} });
411
+ } catch (err) {
412
+ await errorHandling(err);
413
+ }
414
+ },
415
+ [],
416
+ );`,
417
+ );
418
+ } else if (onClickType === 'select') {
419
+ const { selectionMode } = config;
420
+ if (selectionMode === 'single') {
421
+ handlers.push(
422
+ ``,
423
+ ` const onClickItem = React.useCallback(
424
+ async (params: AXDGClickParams<DtoItem>) => {
425
+ try {
426
+ await setSelectedItem(params.item);
427
+ } catch (err) {
428
+ await errorHandling(err);
429
+ }
430
+ },
431
+ [setSelectedItem],
432
+ );`,
433
+ );
434
+ }
435
+ }
436
+
437
+ return handlers.join('\n');
438
+ }
439
+
440
+ /**
441
+ * FormHeader 생성
442
+ */
443
+ function generateFormHeader(config: ListDataGridConfig): string {
444
+ if (!config.withFormHeader) {
445
+ return ' <>';
446
+ }
447
+
448
+ const { withExcel } = config;
449
+
450
+ let buttons = '';
451
+ if (withExcel) {
452
+ buttons = `
453
+ {programFn?.fn04 && (
454
+ <Button size={"small"} icon={<IconDownload />} onClick={handleExcelDownload} loading={excelSpinning}>
455
+ {t("엑셀다운로드")}
456
+ </Button>
457
+ )}`;
458
+ }
459
+
460
+ return ` <>
461
+ <FormHeader>
462
+ 목록
463
+ <Flex gap={6} align={"center"}>${buttons}
464
+ </Flex>
465
+ </FormHeader>`;
466
+ }
467
+
468
+ /**
469
+ * DataGrid Props 생성
470
+ */
471
+ function generateDataGridProps(config: ListDataGridConfig): string {
472
+ const { selectionMode, rowKey } = config;
473
+ const props: string[] = [
474
+ ` onClick={onClickItem}`,
475
+ ` page={{`,
476
+ ` ...listPage,`,
477
+ ` loading: false,`,
478
+ ` onChange: async (currentPage, pageSize) => {`,
479
+ ` await changeListPage(currentPage, pageSize);`,
480
+ ` },`,
481
+ ` }}`,
482
+ ` sort={{`,
483
+ ` sortParams: listSortParams,`,
484
+ ` onChange: setListSortParams,`,
485
+ ` }}`,
486
+ ` onChangeColumns={handleColumnsChange}`,
487
+ ` rowKey={"${rowKey}"}`,
488
+ ];
489
+
490
+ // 선택 모드별 props
491
+ if (selectionMode === 'single') {
492
+ props.push(` selectedRowKey={selectedItem?.${rowKey} ?? ""}`);
493
+ } else if (selectionMode === 'multi') {
494
+ props.push(
495
+ ` rowChecked={{`,
496
+ ` checkedRowKeys,`,
497
+ ` onChange: (checkedIndexes, checkedRowKeys, checkedAll) => {`,
498
+ ` setCheckedRowKeys(checkedRowKeys);`,
499
+ ` },`,
500
+ ` }}`,
501
+ );
502
+ }
503
+
504
+ return props.join('\n');
505
+ }
506
+
507
+ /**
508
+ * Styled Components 생성
509
+ */
510
+ function generateStyledComponents(config: ListDataGridConfig): string {
511
+ let styled = `const Container = styled.div\`
512
+ flex: 1;
513
+ \`;`;
514
+
515
+ if (config.withFormHeader) {
516
+ styled += `
517
+ const FormHeader = styled(PageLayout.FrameHeader)\`\`;`;
518
+ }
519
+
520
+ return styled;
521
+ }