evnict-kit 0.2.1

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 (138) hide show
  1. package/README.md +19 -0
  2. package/bin/cli.js +38 -0
  3. package/package.json +48 -0
  4. package/src/commands/add.js +129 -0
  5. package/src/commands/init-check.js +19 -0
  6. package/src/commands/init-context.js +37 -0
  7. package/src/commands/init-rules.js +42 -0
  8. package/src/commands/init-workflow.js +36 -0
  9. package/src/commands/init.js +722 -0
  10. package/src/utils/config.js +167 -0
  11. package/src/utils/file.js +53 -0
  12. package/templates/GETTING-STARTED.md +196 -0
  13. package/templates/content/context/AGENTS.md.template +462 -0
  14. package/templates/content/rules/01-evnict-kit-general-rules.md +303 -0
  15. package/templates/content/rules/02-evnict-kit-security-rules.md +423 -0
  16. package/templates/content/rules/03-evnict-kit-backend-conventions.md +383 -0
  17. package/templates/content/rules/04-evnict-kit-frontend-conventions.md +402 -0
  18. package/templates/content/rules/05-evnict-kit-project-conventions.md +228 -0
  19. package/templates/content/skills/evnict-kit-brainstorm/SKILL.md +140 -0
  20. package/templates/content/skills/evnict-kit-bug-fix/SKILL.md +108 -0
  21. package/templates/content/skills/evnict-kit-checkpoint/SKILL.md +156 -0
  22. package/templates/content/skills/evnict-kit-code-review/SKILL.md +158 -0
  23. package/templates/content/skills/evnict-kit-coordinate/SKILL.md +274 -0
  24. package/templates/content/skills/evnict-kit-create-api/SKILL.md +281 -0
  25. package/templates/content/skills/evnict-kit-create-component/SKILL.md +263 -0
  26. package/templates/content/skills/evnict-kit-create-page/SKILL.md +247 -0
  27. package/templates/content/skills/evnict-kit-database-migration/SKILL.md +164 -0
  28. package/templates/content/skills/evnict-kit-doc-postmortem/SKILL.md +93 -0
  29. package/templates/content/skills/evnict-kit-finish-branch/SKILL.md +87 -0
  30. package/templates/content/skills/evnict-kit-fix-attt/SKILL.md +129 -0
  31. package/templates/content/skills/evnict-kit-fix-business-logic/SKILL.md +89 -0
  32. package/templates/content/skills/evnict-kit-git-worktrees/SKILL.md +104 -0
  33. package/templates/content/skills/evnict-kit-merge-checklist/SKILL.md +108 -0
  34. package/templates/content/skills/evnict-kit-onboard/SKILL.md +143 -0
  35. package/templates/content/skills/evnict-kit-prompt-standard/SKILL.md +103 -0
  36. package/templates/content/skills/evnict-kit-receiving-review/SKILL.md +89 -0
  37. package/templates/content/skills/evnict-kit-security-audit/SKILL.md +190 -0
  38. package/templates/content/skills/evnict-kit-spec/SKILL.md +237 -0
  39. package/templates/content/skills/evnict-kit-tdd/SKILL.md +413 -0
  40. package/templates/content/skills/evnict-kit-wiki/SKILL.md +412 -0
  41. package/templates/content/workflows/evnict-kit-archive-wiki.md +100 -0
  42. package/templates/content/workflows/evnict-kit-attt.md +100 -0
  43. package/templates/content/workflows/evnict-kit-bug-fix.md +107 -0
  44. package/templates/content/workflows/evnict-kit-feature-large.md +393 -0
  45. package/templates/content/workflows/evnict-kit-feature-small.md +86 -0
  46. package/templates/content/workflows/evnict-kit-handoff.md +243 -0
  47. package/templates/content/workflows/evnict-kit-implement.md +247 -0
  48. package/templates/content/workflows/evnict-kit-init-check.md +76 -0
  49. package/templates/content/workflows/evnict-kit-init-context.md +58 -0
  50. package/templates/content/workflows/evnict-kit-init-rules.md +114 -0
  51. package/templates/content/workflows/evnict-kit-init-wiki.md +80 -0
  52. package/templates/content/workflows/evnict-kit-plan.md +308 -0
  53. package/templates/content/workflows/evnict-kit-review.md +53 -0
  54. package/templates/content/workflows/evnict-kit-spec-archive.md +53 -0
  55. package/templates/content/workflows/evnict-kit-wiki-archive-feature.md +164 -0
  56. package/templates/content/workflows/evnict-kit-wiki-query.md +91 -0
  57. package/templates/content/workflows/evnict-kit-wiki-scan-project.md +272 -0
  58. package/templates/context/AGENT.md.template +9 -0
  59. package/templates/context/AGENTS.md.template +462 -0
  60. package/templates/context/CLAUDE.md.template +301 -0
  61. package/templates/context/copilot-instructions.md.template +60 -0
  62. package/templates/context/cursorrules.template +114 -0
  63. package/templates/instruct/Instruct-Agent-AI.be.md +96 -0
  64. package/templates/instruct/Instruct-Agent-AI.fe.md +79 -0
  65. package/templates/rules/antigravity/01-evnict-kit-general-rules.md +303 -0
  66. package/templates/rules/antigravity/02-evnict-kit-security-rules.md +423 -0
  67. package/templates/rules/antigravity/03-evnict-kit-backend-conventions.md +383 -0
  68. package/templates/rules/antigravity/04-evnict-kit-frontend-conventions.md +402 -0
  69. package/templates/rules/antigravity/05-evnict-kit-project-conventions.md +228 -0
  70. package/templates/rules/claude/README.md +8 -0
  71. package/templates/rules/cursor/01-evnict-kit-general-rules.mdc +46 -0
  72. package/templates/rules/cursor/02-evnict-kit-security-rules.mdc +46 -0
  73. package/templates/rules/cursor/03-evnict-kit-backend-conventions.mdc +50 -0
  74. package/templates/rules/cursor/04-evnict-kit-frontend-conventions.mdc +43 -0
  75. package/templates/rules/cursor/05-evnict-kit-project-conventions.mdc +63 -0
  76. package/templates/rules/cursor/README.md +7 -0
  77. package/templates/skills/evnict-kit-brainstorm/SKILL.md +140 -0
  78. package/templates/skills/evnict-kit-bug-fix/SKILL.md +108 -0
  79. package/templates/skills/evnict-kit-checkpoint/SKILL.md +156 -0
  80. package/templates/skills/evnict-kit-code-review/SKILL.md +158 -0
  81. package/templates/skills/evnict-kit-coordinate/SKILL.md +274 -0
  82. package/templates/skills/evnict-kit-create-api/SKILL.md +281 -0
  83. package/templates/skills/evnict-kit-create-component/SKILL.md +263 -0
  84. package/templates/skills/evnict-kit-create-page/SKILL.md +247 -0
  85. package/templates/skills/evnict-kit-database-migration/SKILL.md +164 -0
  86. package/templates/skills/evnict-kit-doc-postmortem/SKILL.md +93 -0
  87. package/templates/skills/evnict-kit-finish-branch/SKILL.md +87 -0
  88. package/templates/skills/evnict-kit-fix-attt/SKILL.md +129 -0
  89. package/templates/skills/evnict-kit-fix-business-logic/SKILL.md +89 -0
  90. package/templates/skills/evnict-kit-git-worktrees/SKILL.md +104 -0
  91. package/templates/skills/evnict-kit-merge-checklist/SKILL.md +108 -0
  92. package/templates/skills/evnict-kit-onboard/SKILL.md +143 -0
  93. package/templates/skills/evnict-kit-prompt-standard/SKILL.md +103 -0
  94. package/templates/skills/evnict-kit-receiving-review/SKILL.md +89 -0
  95. package/templates/skills/evnict-kit-security-audit/SKILL.md +190 -0
  96. package/templates/skills/evnict-kit-spec/SKILL.md +237 -0
  97. package/templates/skills/evnict-kit-tdd/SKILL.md +413 -0
  98. package/templates/skills/evnict-kit-wiki/SKILL.md +412 -0
  99. package/templates/wiki/README.md +35 -0
  100. package/templates/wiki/config.example.yaml +17 -0
  101. package/templates/wiki/package.json +17 -0
  102. package/templates/wiki/raw/notes/.gitkeep +1 -0
  103. package/templates/wiki/scripts/ingest.js +66 -0
  104. package/templates/workflows/antigravity/evnict-kit-archive-wiki.md +100 -0
  105. package/templates/workflows/antigravity/evnict-kit-attt.md +100 -0
  106. package/templates/workflows/antigravity/evnict-kit-bug-fix.md +107 -0
  107. package/templates/workflows/antigravity/evnict-kit-feature-large.md +393 -0
  108. package/templates/workflows/antigravity/evnict-kit-feature-small.md +86 -0
  109. package/templates/workflows/antigravity/evnict-kit-handoff.md +243 -0
  110. package/templates/workflows/antigravity/evnict-kit-implement.md +247 -0
  111. package/templates/workflows/antigravity/evnict-kit-init-check.md +76 -0
  112. package/templates/workflows/antigravity/evnict-kit-init-context.md +58 -0
  113. package/templates/workflows/antigravity/evnict-kit-init-rules.md +114 -0
  114. package/templates/workflows/antigravity/evnict-kit-init-wiki.md +80 -0
  115. package/templates/workflows/antigravity/evnict-kit-plan.md +308 -0
  116. package/templates/workflows/antigravity/evnict-kit-review.md +53 -0
  117. package/templates/workflows/antigravity/evnict-kit-spec-archive.md +53 -0
  118. package/templates/workflows/antigravity/evnict-kit-wiki-archive-feature.md +164 -0
  119. package/templates/workflows/antigravity/evnict-kit-wiki-query.md +91 -0
  120. package/templates/workflows/antigravity/evnict-kit-wiki-scan-project.md +272 -0
  121. package/templates/workflows/claude/README.md +6 -0
  122. package/templates/workflows/claude/evnict-kit-archive-wiki.md +98 -0
  123. package/templates/workflows/claude/evnict-kit-attt.md +98 -0
  124. package/templates/workflows/claude/evnict-kit-bug-fix.md +105 -0
  125. package/templates/workflows/claude/evnict-kit-feature-large.md +391 -0
  126. package/templates/workflows/claude/evnict-kit-feature-small.md +84 -0
  127. package/templates/workflows/claude/evnict-kit-handoff.md +240 -0
  128. package/templates/workflows/claude/evnict-kit-implement.md +245 -0
  129. package/templates/workflows/claude/evnict-kit-init-check.md +74 -0
  130. package/templates/workflows/claude/evnict-kit-init-context.md +56 -0
  131. package/templates/workflows/claude/evnict-kit-init-rules.md +112 -0
  132. package/templates/workflows/claude/evnict-kit-init-wiki.md +78 -0
  133. package/templates/workflows/claude/evnict-kit-plan.md +305 -0
  134. package/templates/workflows/claude/evnict-kit-review.md +51 -0
  135. package/templates/workflows/claude/evnict-kit-spec-archive.md +51 -0
  136. package/templates/workflows/claude/evnict-kit-wiki-archive-feature.md +162 -0
  137. package/templates/workflows/claude/evnict-kit-wiki-query.md +89 -0
  138. package/templates/workflows/claude/evnict-kit-wiki-scan-project.md +270 -0
@@ -0,0 +1,263 @@
1
+ ---
2
+ name: evnict-kit-create-component
3
+ description: Tạo UI component chuẩn — check reuse → generate → style → test → a11y. Angular + PrimeNG.
4
+ compatibility: Angular 16+, PrimeNG
5
+ ---
6
+
7
+ # evnict-kit-create-component — Tạo UI Component
8
+
9
+ ## Khi nào dùng
10
+ - Tạo component mới cho feature
11
+ - Tạo shared/reusable component
12
+ - Tạo form component complex
13
+
14
+ ## Input Parameters
15
+ - `name` (bắt buộc): Tên component (VD: customer-form, order-table)
16
+ - `type` (optional): page | shared | feature (default: feature)
17
+ - `module` (optional): Module chứa component
18
+
19
+ ---
20
+
21
+ ## Workflow Steps
22
+
23
+ ### Bước 1: Check Reuse — TRƯỚC KHI tạo mới
24
+ 1. Tìm trong `shared/components/` → có component tương tự?
25
+ 2. Tìm trong PrimeNG → đã có component sẵn?
26
+ 3. Tìm trong module hiện tại → có thể extend?
27
+
28
+ ```bash
29
+ # Scan existing components
30
+ find src/app -name "*.component.ts" | grep -i "{keyword}"
31
+ # Check PrimeNG docs nếu cần
32
+ ```
33
+
34
+ Nếu tìm thấy → REUSE hoặc EXTEND, KHÔNG tạo mới.
35
+
36
+ ### Bước 2: Generate Component
37
+
38
+ #### Xác định vị trí
39
+ | Type | Path |
40
+ |------|------|
41
+ | shared | `src/app/shared/components/{name}/` |
42
+ | feature | `src/app/features/{module}/components/{name}/` |
43
+ | page | `src/app/features/{module}/pages/{name}/` |
44
+
45
+ #### Tạo files
46
+ ```
47
+ {name}/
48
+ ├── {name}.component.ts
49
+ ├── {name}.component.html
50
+ ├── {name}.component.scss
51
+ └── {name}.component.spec.ts
52
+ ```
53
+
54
+ ### Bước 3: Component Code
55
+
56
+ ```typescript
57
+ // ✅ Component tiêu chuẩn
58
+ @Component({
59
+ selector: 'app-{name}',
60
+ templateUrl: './{name}.component.html',
61
+ styleUrls: ['./{name}.component.scss']
62
+ })
63
+ export class {Name}Component implements OnInit, OnDestroy {
64
+ // Input/Output
65
+ @Input() data: {Type}[];
66
+ @Output() onAction = new EventEmitter<{Type}>();
67
+
68
+ // State
69
+ loading = false;
70
+ errorMessage = '';
71
+
72
+ // Lifecycle
73
+ private destroy$ = new Subject<void>();
74
+
75
+ constructor(
76
+ private service: {Module}Service,
77
+ private messageService: MessageService
78
+ ) {}
79
+
80
+ ngOnInit(): void {
81
+ this.loadData();
82
+ }
83
+
84
+ ngOnDestroy(): void {
85
+ this.destroy$.next();
86
+ this.destroy$.complete();
87
+ }
88
+
89
+ // Methods
90
+ loadData(): void {
91
+ this.loading = true;
92
+ this.service.getData()
93
+ .pipe(
94
+ takeUntil(this.destroy$),
95
+ finalize(() => this.loading = false)
96
+ )
97
+ .subscribe({
98
+ next: (res) => {
99
+ if (res.status === 0) {
100
+ this.data = res.data;
101
+ } else {
102
+ this.errorMessage = res.message;
103
+ }
104
+ },
105
+ error: (err) => {
106
+ this.messageService.add({
107
+ severity: 'error',
108
+ summary: 'Lỗi',
109
+ detail: 'Không thể tải dữ liệu'
110
+ });
111
+ }
112
+ });
113
+ }
114
+ }
115
+ ```
116
+
117
+ ### Bước 4: Template (HTML)
118
+
119
+ ```html
120
+ <!-- ✅ Template chuẩn với PrimeNG -->
121
+ <div class="component-container">
122
+ <!-- Loading state -->
123
+ <div *ngIf="loading" class="loading-container">
124
+ <p-progressSpinner></p-progressSpinner>
125
+ </div>
126
+
127
+ <!-- Error state -->
128
+ <p-message *ngIf="errorMessage" severity="error" [text]="errorMessage"></p-message>
129
+
130
+ <!-- Content -->
131
+ <ng-container *ngIf="!loading && !errorMessage">
132
+ <!-- Component content here -->
133
+ </ng-container>
134
+ </div>
135
+ ```
136
+
137
+ ### Bước 5: Styles (SCSS)
138
+
139
+ ```scss
140
+ // ✅ Styles chuẩn
141
+ :host {
142
+ display: block;
143
+ }
144
+
145
+ .component-container {
146
+ padding: 1rem;
147
+ }
148
+
149
+ .loading-container {
150
+ display: flex;
151
+ justify-content: center;
152
+ padding: 2rem;
153
+ }
154
+
155
+ // Responsive
156
+ @media (max-width: 768px) {
157
+ .component-container {
158
+ padding: 0.5rem;
159
+ }
160
+ }
161
+ ```
162
+
163
+ ### Bước 6: Form Component Pattern (nếu là form)
164
+
165
+ ```typescript
166
+ // ✅ Reactive Form component
167
+ export class CustomerFormComponent implements OnInit {
168
+ form: FormGroup;
169
+ isEdit = false;
170
+
171
+ constructor(
172
+ private fb: FormBuilder,
173
+ private service: CustomerService,
174
+ private messageService: MessageService
175
+ ) {}
176
+
177
+ ngOnInit(): void {
178
+ this.initForm();
179
+ }
180
+
181
+ private initForm(): void {
182
+ this.form = this.fb.group({
183
+ name: ['', [Validators.required, Validators.maxLength(200)]],
184
+ phone: ['', [Validators.pattern(/^0[0-9]{9}$/)]],
185
+ donViId: [null, Validators.required]
186
+ });
187
+ }
188
+
189
+ onSubmit(): void {
190
+ if (this.form.invalid) {
191
+ this.form.markAllAsTouched();
192
+ return;
193
+ }
194
+ const dto = this.form.value;
195
+ const action$ = this.isEdit
196
+ ? this.service.update(dto.id, dto)
197
+ : this.service.create(dto);
198
+
199
+ action$.subscribe({
200
+ next: (res) => {
201
+ if (res.status === 0) {
202
+ this.messageService.add({
203
+ severity: 'success',
204
+ summary: 'Thành công',
205
+ detail: this.isEdit ? 'Cập nhật thành công' : 'Tạo mới thành công'
206
+ });
207
+ }
208
+ }
209
+ });
210
+ }
211
+ }
212
+ ```
213
+
214
+ ### Bước 7: Test
215
+
216
+ ```typescript
217
+ describe('{Name}Component', () => {
218
+ let component: {Name}Component;
219
+ let fixture: ComponentFixture<{Name}Component>;
220
+
221
+ beforeEach(async () => {
222
+ await TestBed.configureTestingModule({
223
+ declarations: [{Name}Component],
224
+ imports: [/* required modules */],
225
+ providers: [/* mock services */]
226
+ }).compileComponents();
227
+
228
+ fixture = TestBed.createComponent({Name}Component);
229
+ component = fixture.componentInstance;
230
+ fixture.detectChanges();
231
+ });
232
+
233
+ it('should create', () => {
234
+ expect(component).toBeTruthy();
235
+ });
236
+
237
+ it('should load data on init', () => { /* ... */ });
238
+ it('should show loading spinner', () => { /* ... */ });
239
+ it('should handle error', () => { /* ... */ });
240
+ });
241
+ ```
242
+
243
+ ### Bước 8: A11y Check
244
+ - [ ] Tất cả `<img>` có `alt`
245
+ - [ ] Form fields có `<label>` hoặc `aria-label`
246
+ - [ ] Interactive elements có `tabindex`
247
+ - [ ] Color contrast ≥ 4.5:1
248
+
249
+ ### Bước 9: Register Component
250
+ Thêm vào module declarations hoặc shared module exports.
251
+
252
+ ---
253
+
254
+ ## Tiêu chí hoàn thành
255
+ - [ ] Reuse check done — không tạo trùng
256
+ - [ ] Component files tạo đầy đủ (ts, html, scss, spec.ts)
257
+ - [ ] Reactive Forms nếu là form component
258
+ - [ ] Loading/error states handled
259
+ - [ ] RxJS unsubscribe (takeUntil pattern)
260
+ - [ ] Responsive design
261
+ - [ ] A11y check pass
262
+ - [ ] Tests viết và PASS
263
+ - [ ] Registered trong module
@@ -0,0 +1,247 @@
1
+ ---
2
+ name: evnict-kit-create-page
3
+ description: Tạo page mới — module → routing → component → service → loading/error states. Angular lazy-loaded.
4
+ compatibility: Angular 16+, PrimeNG
5
+ ---
6
+
7
+ # evnict-kit-create-page — Tạo Page Mới
8
+
9
+ ## Khi nào dùng
10
+ - Tạo page mới trong feature module
11
+ - Tạo feature module mới với routing
12
+
13
+ ## Input Parameters
14
+ - `name` (bắt buộc): Tên page (VD: customer-list, order-detail)
15
+ - `module` (bắt buộc): Module chứa page
16
+ - `route` (optional): Route path (default: based on name)
17
+
18
+ ---
19
+
20
+ ## Workflow Steps
21
+
22
+ ### Bước 1: Kiểm tra module
23
+
24
+ #### Module đã tồn tại?
25
+ ```bash
26
+ find src/app/features -name "{module}.module.ts"
27
+ ```
28
+
29
+ #### Nếu chưa → Tạo module mới
30
+ ```
31
+ src/app/features/{module}/
32
+ ├── {module}.module.ts
33
+ ├── {module}-routing.module.ts
34
+ ├── pages/
35
+ │ └── {page-name}/
36
+ ├── components/
37
+ ├── services/
38
+ └── models/
39
+ ```
40
+
41
+ ```typescript
42
+ // {module}.module.ts
43
+ @NgModule({
44
+ declarations: [],
45
+ imports: [
46
+ CommonModule,
47
+ {Module}RoutingModule,
48
+ SharedModule,
49
+ // PrimeNG modules
50
+ TableModule,
51
+ ButtonModule,
52
+ InputTextModule,
53
+ DialogModule
54
+ ]
55
+ })
56
+ export class {Module}Module {}
57
+ ```
58
+
59
+ ```typescript
60
+ // {module}-routing.module.ts
61
+ const routes: Routes = [
62
+ { path: '', component: {PageName}Component }
63
+ ];
64
+
65
+ @NgModule({
66
+ imports: [RouterModule.forChild(routes)],
67
+ exports: [RouterModule]
68
+ })
69
+ export class {Module}RoutingModule {}
70
+ ```
71
+
72
+ ### Bước 2: Thêm lazy loading vào app-routing
73
+ ```typescript
74
+ // app-routing.module.ts
75
+ {
76
+ path: '{module}',
77
+ loadChildren: () => import('./features/{module}/{module}.module')
78
+ .then(m => m.{Module}Module),
79
+ canActivate: [AuthGuard]
80
+ }
81
+ ```
82
+
83
+ ### Bước 3: Tạo page component
84
+ Dùng skill `evnict-kit-create-component` với type=page.
85
+
86
+ #### List Page Pattern
87
+ ```typescript
88
+ @Component({
89
+ selector: 'app-{name}-list',
90
+ templateUrl: './{name}-list.component.html'
91
+ })
92
+ export class {Name}ListComponent implements OnInit {
93
+ data: {Type}[] = [];
94
+ totalRecords = 0;
95
+ loading = false;
96
+ keyword = '';
97
+
98
+ // Dialog
99
+ showDialog = false;
100
+ selectedItem: {Type} | null = null;
101
+
102
+ private destroy$ = new Subject<void>();
103
+
104
+ constructor(
105
+ private service: {Module}Service,
106
+ private messageService: MessageService,
107
+ private confirmService: ConfirmationService
108
+ ) {}
109
+
110
+ ngOnInit(): void { this.search(); }
111
+
112
+ search(event?: any): void {
113
+ this.loading = true;
114
+ const page = event ? event.first / event.rows : 0;
115
+ const size = event ? event.rows : 20;
116
+
117
+ this.service.search(this.keyword, page, size)
118
+ .pipe(takeUntil(this.destroy$), finalize(() => this.loading = false))
119
+ .subscribe(res => {
120
+ if (res.status === 0) {
121
+ this.data = res.data.content;
122
+ this.totalRecords = res.data.totalElements;
123
+ }
124
+ });
125
+ }
126
+
127
+ onCreate(): void {
128
+ this.selectedItem = null;
129
+ this.showDialog = true;
130
+ }
131
+
132
+ onEdit(item: {Type}): void {
133
+ this.selectedItem = { ...item };
134
+ this.showDialog = true;
135
+ }
136
+
137
+ onDelete(item: {Type}): void {
138
+ this.confirmService.confirm({
139
+ message: 'Bạn có chắc chắn muốn xóa?',
140
+ accept: () => {
141
+ this.service.delete(item.id)
142
+ .pipe(takeUntil(this.destroy$))
143
+ .subscribe(res => {
144
+ if (res.status === 0) {
145
+ this.messageService.add({ severity: 'success', detail: 'Xóa thành công' });
146
+ this.search();
147
+ }
148
+ });
149
+ }
150
+ });
151
+ }
152
+
153
+ onSaved(): void {
154
+ this.showDialog = false;
155
+ this.search();
156
+ }
157
+
158
+ ngOnDestroy(): void {
159
+ this.destroy$.next();
160
+ this.destroy$.complete();
161
+ }
162
+ }
163
+ ```
164
+
165
+ #### List Page Template
166
+ ```html
167
+ <div class="page-container">
168
+ <div class="page-header">
169
+ <h2>{{ 'page.{module}.title' | translate }}</h2>
170
+ <button pButton label="{{ 'button.create' | translate }}" icon="pi pi-plus"
171
+ (click)="onCreate()"></button>
172
+ </div>
173
+
174
+ <div class="search-bar">
175
+ <span class="p-input-icon-left">
176
+ <i class="pi pi-search"></i>
177
+ <input pInputText [(ngModel)]="keyword" (keyup.enter)="search()"
178
+ [placeholder]="'placeholder.search' | translate">
179
+ </span>
180
+ </div>
181
+
182
+ <p-table [value]="data" [lazy]="true" [paginator]="true" [rows]="20"
183
+ [totalRecords]="totalRecords" [loading]="loading"
184
+ (onLazyLoad)="search($event)" [responsive]="true" responsiveLayout="scroll">
185
+ <ng-template pTemplate="header">
186
+ <tr>
187
+ <th>{{ 'column.name' | translate }}</th>
188
+ <th>{{ 'column.status' | translate }}</th>
189
+ <th style="width: 120px">{{ 'column.action' | translate }}</th>
190
+ </tr>
191
+ </ng-template>
192
+ <ng-template pTemplate="body" let-item>
193
+ <tr>
194
+ <td>{{ item.name }}</td>
195
+ <td>{{ item.status }}</td>
196
+ <td>
197
+ <button pButton icon="pi pi-pencil" class="p-button-text" (click)="onEdit(item)"></button>
198
+ <button pButton icon="pi pi-trash" class="p-button-text p-button-danger" (click)="onDelete(item)"></button>
199
+ </td>
200
+ </tr>
201
+ </ng-template>
202
+ <ng-template pTemplate="emptymessage">
203
+ <tr><td colspan="3" class="text-center">{{ 'message.noData' | translate }}</td></tr>
204
+ </ng-template>
205
+ </p-table>
206
+
207
+ <!-- Form Dialog -->
208
+ <app-{name}-form *ngIf="showDialog" [visible]="showDialog" [data]="selectedItem"
209
+ (onSave)="onSaved()" (onCancel)="showDialog = false">
210
+ </app-{name}-form>
211
+ </div>
212
+
213
+ <p-confirmDialog></p-confirmDialog>
214
+ ```
215
+
216
+ ### Bước 4: Tạo service (nếu chưa có)
217
+ Dùng pattern từ `04-evnict-kit-frontend-conventions.md`.
218
+
219
+ ### Bước 5: Test page
220
+ ```typescript
221
+ describe('{Name}ListComponent', () => {
222
+ // Test: load data on init
223
+ // Test: search with keyword
224
+ // Test: pagination
225
+ // Test: create dialog opens
226
+ // Test: delete with confirmation
227
+ });
228
+ ```
229
+
230
+ ### Bước 6: Verify
231
+ ```bash
232
+ ng test --watch=false
233
+ ng lint
234
+ ng build
235
+ ```
236
+
237
+ ---
238
+
239
+ ## Tiêu chí hoàn thành
240
+ - [ ] Module tạo/update đúng
241
+ - [ ] Routing configured (lazy-loaded)
242
+ - [ ] Page component với loading/error states
243
+ - [ ] Service created/reused
244
+ - [ ] i18n keys added
245
+ - [ ] Responsive design
246
+ - [ ] Tests viết và PASS
247
+ - [ ] Build OK
@@ -0,0 +1,164 @@
1
+ ---
2
+ name: evnict-kit-database-migration
3
+ description: Tạo migration script chuẩn — naming, UP/DOWN scripts, test, hỗ trợ Oracle + SQL Server.
4
+ compatibility: Oracle 19c, SQL Server 2019+, Flyway/Liquibase
5
+ ---
6
+
7
+ # evnict-kit-database-migration — Database Migration
8
+
9
+ ## Khi nào dùng
10
+ - Thêm/sửa/xóa table, column, index
11
+ - Thay đổi schema database qua migration script
12
+ - Tạo rollback script cho thay đổi DB
13
+
14
+ ## Input Parameters
15
+ - `action` (bắt buộc): create-table | alter-table | add-index | add-column | drop-column | seed-data
16
+ - `description` (bắt buộc): Mô tả thay đổi
17
+ - `database` (optional): oracle | sqlserver (default: từ config)
18
+
19
+ ---
20
+
21
+ ## Workflow Steps
22
+
23
+ ### Bước 1: Xác định thông tin
24
+ Đọc `.evnict/config.yaml` → database type
25
+ Đọc `.agent/rules/05-evnict-kit-project-conventions.md` → RP05 DB conventions
26
+
27
+ ### Bước 2: Tạo migration files
28
+
29
+ #### Naming convention
30
+ ```
31
+ V{YYYYMMDD}_{seq}__{description}.sql ← UP
32
+ V{YYYYMMDD}_{seq}__{description}_ROLLBACK.sql ← DOWN
33
+ ```
34
+ Ví dụ:
35
+ ```
36
+ V20260401_001__create_table_customer.sql
37
+ V20260401_001__create_table_customer_ROLLBACK.sql
38
+ ```
39
+
40
+ ### Bước 3: Viết UP script
41
+
42
+ #### Oracle — CREATE TABLE
43
+ ```sql
44
+ -- V20260401_001__create_table_customer.sql
45
+ CREATE TABLE CUSTOMER (
46
+ ID NUMBER(19) NOT NULL,
47
+ NAME NVARCHAR2(200) NOT NULL,
48
+ PHONE VARCHAR2(20),
49
+ EMAIL VARCHAR2(100),
50
+ DON_VI_ID NUMBER(19) NOT NULL,
51
+ STATUS VARCHAR2(20) DEFAULT 'ACTIVE' NOT NULL,
52
+ IS_DELETED NUMBER(1) DEFAULT 0 NOT NULL,
53
+ CREATED_BY VARCHAR2(50),
54
+ CREATED_DATE TIMESTAMP DEFAULT SYSTIMESTAMP,
55
+ UPDATED_BY VARCHAR2(50),
56
+ UPDATED_DATE TIMESTAMP,
57
+ CONSTRAINT PK_CUSTOMER PRIMARY KEY (ID),
58
+ CONSTRAINT FK_CUSTOMER_DON_VI FOREIGN KEY (DON_VI_ID) REFERENCES DON_VI(ID)
59
+ );
60
+
61
+ CREATE SEQUENCE CUSTOMER_SEQ START WITH 1 INCREMENT BY 1;
62
+
63
+ CREATE INDEX IX_CUSTOMER_DON_VI ON CUSTOMER(DON_VI_ID);
64
+ CREATE INDEX IX_CUSTOMER_STATUS ON CUSTOMER(STATUS);
65
+
66
+ COMMENT ON TABLE CUSTOMER IS 'Bảng khách hàng';
67
+ COMMENT ON COLUMN CUSTOMER.NAME IS 'Tên khách hàng';
68
+ COMMENT ON COLUMN CUSTOMER.STATUS IS 'Trạng thái: ACTIVE, INACTIVE, SUSPENDED';
69
+ ```
70
+
71
+ #### Oracle — ALTER TABLE
72
+ ```sql
73
+ -- V20260402_001__add_customer_address.sql
74
+ ALTER TABLE CUSTOMER ADD (
75
+ ADDRESS NVARCHAR2(500),
76
+ DISTRICT_CODE VARCHAR2(10)
77
+ );
78
+
79
+ CREATE INDEX IX_CUSTOMER_DISTRICT ON CUSTOMER(DISTRICT_CODE);
80
+
81
+ COMMENT ON COLUMN CUSTOMER.ADDRESS IS 'Địa chỉ khách hàng';
82
+ ```
83
+
84
+ #### SQL Server — CREATE TABLE
85
+ ```sql
86
+ -- V20260401_001__create_table_customer.sql
87
+ CREATE TABLE Customer (
88
+ Id BIGINT IDENTITY(1,1) NOT NULL,
89
+ Name NVARCHAR(200) NOT NULL,
90
+ Phone NVARCHAR(20) NULL,
91
+ Email NVARCHAR(100) NULL,
92
+ DonViId BIGINT NOT NULL,
93
+ Status NVARCHAR(20) NOT NULL DEFAULT 'ACTIVE',
94
+ IsDeleted BIT NOT NULL DEFAULT 0,
95
+ CreatedBy NVARCHAR(50) NULL,
96
+ CreatedDate DATETIME2 DEFAULT GETDATE(),
97
+ UpdatedBy NVARCHAR(50) NULL,
98
+ UpdatedDate DATETIME2 NULL,
99
+ CONSTRAINT PK_Customer PRIMARY KEY (Id),
100
+ CONSTRAINT FK_Customer_DonVi FOREIGN KEY (DonViId) REFERENCES DonVi(Id)
101
+ );
102
+
103
+ CREATE INDEX IX_Customer_DonVi ON Customer(DonViId);
104
+ CREATE INDEX IX_Customer_Status ON Customer(Status);
105
+ ```
106
+
107
+ ### Bước 4: Viết ROLLBACK script
108
+
109
+ #### Oracle
110
+ ```sql
111
+ -- V20260401_001__create_table_customer_ROLLBACK.sql
112
+ DROP INDEX IX_CUSTOMER_STATUS;
113
+ DROP INDEX IX_CUSTOMER_DON_VI;
114
+ DROP SEQUENCE CUSTOMER_SEQ;
115
+ DROP TABLE CUSTOMER;
116
+ ```
117
+
118
+ #### SQL Server
119
+ ```sql
120
+ -- V20260401_001__create_table_customer_ROLLBACK.sql
121
+ DROP INDEX IX_Customer_Status ON Customer;
122
+ DROP INDEX IX_Customer_DonVi ON Customer;
123
+ DROP TABLE Customer;
124
+ ```
125
+
126
+ ### Bước 5: Test migration
127
+ ```bash
128
+ # Chạy UP
129
+ flyway migrate
130
+ # hoặc chạy script thủ công trong DB client
131
+
132
+ # Verify: table/column tồn tại
133
+ # Oracle
134
+ SELECT * FROM USER_TABLES WHERE TABLE_NAME = 'CUSTOMER';
135
+ SELECT * FROM USER_TAB_COLUMNS WHERE TABLE_NAME = 'CUSTOMER';
136
+
137
+ # Chạy ROLLBACK
138
+ # Verify: table/column đã xóa
139
+ ```
140
+
141
+ ### Bước 6: KHÔNG làm
142
+ - ❌ KHÔNG sửa DB trực tiếp (phải qua migration script)
143
+ - ❌ KHÔNG DROP TABLE trong production
144
+ - ❌ KHÔNG ALTER column type nếu có data (phải migrate data trước)
145
+ - ❌ KHÔNG hardcode data trong migration (trừ seed data rõ ràng)
146
+
147
+ ---
148
+
149
+ ## Checklist per migration
150
+ - [ ] UP script chạy thành công
151
+ - [ ] ROLLBACK script chạy thành công
152
+ - [ ] Naming đúng convention: `V{date}_{seq}__{desc}.sql`
153
+ - [ ] Có COMMENT cho table và columns quan trọng
154
+ - [ ] Index cho foreign keys và columns hay query
155
+ - [ ] Audit columns (CREATED_BY, CREATED_DATE, UPDATED_BY, UPDATED_DATE)
156
+ - [ ] Soft delete column nếu cần (IS_DELETED)
157
+
158
+ ---
159
+
160
+ ## Tiêu chí hoàn thành
161
+ - [ ] UP script tạo và test pass
162
+ - [ ] ROLLBACK script tạo và test pass
163
+ - [ ] Naming convention đúng
164
+ - [ ] Comments và indexes đầy đủ