AI Implementation feature(869): Admin Area Blog and Blog Page (#58)

This commit was merged in pull request #58.
This commit is contained in:
2026-07-23 10:17:55 +00:00
parent d468cca766
commit 294873240b
32 changed files with 1798 additions and 117 deletions
+82
View File
@@ -0,0 +1,82 @@
# Fix Plan: TS2459 PostFormSubmitPayload not exported
## 1. Root Cause
`frontend/src/app/features/admin/blog/blog-form.pure.ts` declares `PostFormSubmitPayload` and `PostFormMode` as exports, but `frontend/src/app/features/admin/blog/blog-form-modal.component.ts` only **imports** them — it does not re-export them.
`frontend/src/app/features/admin/blog/blog.component.ts:10` imports `PostFormSubmitPayload` from `./blog-form-modal.component`, which has no such export. Under `ng build --configuration production` (which uses `compilationMode: "full"` Angular strict template/type-check), this is a hard `TS2459` error and the bundle fails.
The existing codebase convention is the opposite: `category-form-modal.component.ts` declares `CategoryFormSubmit` / `CategoryFormMode` **inside** the modal file and consumers (`categories.component.ts`) import them from the modal component directly. My initial layout diverged from that pattern by colocating the modal-output types in the `.pure.ts` module.
## 2. Fix (chosen approach: match the existing `CategoryFormSubmit` convention)
Move the two UI-emit types out of `blog-form.pure.ts` and into `blog-form-modal.component.ts`, then update the two importers.
### 2.1 `frontend/src/app/features/admin/blog/blog-form-modal.component.ts` (modify)
Add at the top (right after the existing imports from `./blog-form.pure`):
```ts
export type PostFormMode = 'create' | 'edit';
export interface PostFormSubmitPayload {
mode: PostFormMode;
title: string;
bodyMd: string;
action: 'draft' | 'publish';
}
```
Remove these two names from the import list at line 19-20:
```ts
// before
import {
PostFormGroup,
PostFormMode, // ← remove
PostFormSubmitPayload, // ← remove
buildPostBody,
syncPostForm,
validatePostForm,
} from './blog-form.pure';
// after
import {
PostFormGroup,
buildPostBody,
syncPostForm,
validatePostForm,
} from './blog-form.pure';
```
`PostFormGroup` stays imported from the `.pure.ts` module (it is the pure form-shape type, used internally by the modal).
### 2.2 `frontend/src/app/features/admin/blog/blog-form.pure.ts` (modify)
Remove the two declarations (lines 4 and 11-16) so the pure module no longer leaks UI-emit types:
- Delete `export type PostFormMode = 'create' | 'edit';`
- Delete the entire `export interface PostFormSubmitPayload { ... }` block.
Keep the rest of the file unchanged:
- `PostFormGroup`
- `MAX_TITLE_LENGTH` / `MAX_BODY_LENGTH`
- `validatePostForm`, `syncPostForm`, `buildPostBody`, `statusBadgeClass`, `statusLabel`
### 2.3 No other edits required
- `frontend/src/app/features/admin/blog/blog.component.ts` already imports `PostFormSubmitPayload` from `./blog-form-modal.component` — after step 2.1 that import resolves correctly. No change.
- `tests/frontend/blog-admin-form.spec.ts` does **not** import `PostFormMode` or `PostFormSubmitPayload` (verified — only `PostFormGroup`, `buildPostBody`, `statusBadgeClass`, `statusLabel`, `syncPostForm`, `validatePostForm`). No change.
- `tests/frontend/blog-page.spec.ts` is unaffected.
## 3. Verification
After the fix:
1. `cd /repo && npx ng build --configuration production` must succeed (the original failing command).
2. `cd /repo && npm test` must continue to pass (89 suites, 678 tests).
3. The `BlogFormModalComponent.submit` output still emits the same `PostFormSubmitPayload` shape — `blog.component.ts:onFormSubmit` is unchanged.
## 4. Why this fix over the alternative
Alternative considered: change the import in `blog.component.ts` from `'./blog-form-modal.component'` to `'./blog-form.pure'`. This is a one-line change but it diverges from the established `CategoryFormSubmit` pattern (modal-emit types live with the modal), and it forces every future consumer of the form payload to import from the `.pure.ts` module instead of the modal. The chosen fix aligns this feature with the rest of the codebase and keeps the modal's public API self-contained.
-70
View File
@@ -1,70 +0,0 @@
# Implementation Plan: Fix Job 913 Build Error (missing `auth` injection in AdminUsersComponent)
## 1. Root cause
The `onToggleRole` handler added in the previous turn calls
`this.auth.currentUser()`, `this.auth.applyPeerRoleChange(...)`, and
`this.auth.publishRoleChange(...)`
(`frontend/src/app/features/admin/admin-users.component.ts:244-247`), but
`AdminUsersComponent` never declared an `auth` field. The component only injects
`AdminService` (`admin`) and `NotificationService` (`notify`). TypeScript build
(`ng build --configuration production`) therefore fails with `TS2339: Property
'auth' does not exist on type 'AdminUsersComponent'` at lines 244, 246, 247.
The Jest tests passed because they exercise pure modules and
`admin-players.pure`, not the component class — so the missing field was not
caught at test time.
## 2. Required changes (single file)
**File:** `frontend/src/app/features/admin/admin-users.component.ts`
1. **Add the import** alongside the existing core-service imports (lines 10-11
currently import `AdminService` and `NotificationService`):
```ts
import { AuthService, AdminUser } from '...';
```
The `AdminUser` type can be left on the existing `AdminService` import line. We
must add `AuthService` and import only the value (not the type) — `AuthService`
is the singleton provided in `'root'` by `core/services/auth.service.ts`.
The accurate edit is:
- Replace the existing `import { AdminService, AdminUser } from '...admin.service';`
with two separate imports, or add the new import:
```ts
import { AdminService, AdminUser } from '../../core/services/admin.service';
import { AuthService } from '../../core/services/auth.service';
```
2. **Inject the service** alongside the two existing injections (lines ~170-171):
```ts
private readonly admin = inject(AdminService);
private readonly notify = inject(NotificationService);
private readonly auth = inject(AuthService);
```
That is the only change required — the existing `onToggleRole` body already
references `this.auth.currentUser`, `this.auth.applyPeerRoleChange`, and
`this.auth.publishRoleChange`, all of which exist on `AuthService`.
## 3. Verification
- `npm --workspace frontend run build` should pass (no TypeScript errors).
- `npm test` should still pass — the existing pure tests
(`tests/frontend/admin-players.pure.spec.ts`,
`tests/frontend/auth-session-events.spec.ts`,
`tests/backend/admin-players.spec.ts`) are unaffected by adding the
injection.
- No public API, route, store, or service signature changes are required.
## 4. Out of scope
- No backend changes.
- No test additions (the build error is a pure TypeScript declaration
issue; tests already cover the behaviour).
- No re-architecture of cross-tab role-change handling — the previous turn's
implementation is correct, only the missing field declaration is needed.