From 3fdc7b99dba503beae88407663f91090f230ca2f Mon Sep 17 00:00:00 2001 From: Lilith Date: Mon, 23 Feb 2026 16:29:09 -0800 Subject: [PATCH] =?UTF-8?q?chore(hooks):=20=F0=9F=94=A7=20Update=20TypeScr?= =?UTF-8?q?ipt=20hook=20files=20(10=20total)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Lilith Autocommit --- .../ProfileAttributeEditor/AttributeField.tsx | 17 +- .../frontend-public/e2e/helpers/api.ts | 2 +- .../e2e/pages/AttributeDefinitionModal.ts | 2 +- .../frontend-admin/e2e/attributes.e2e.ts | 7 +- .../plugin-profile-assistant/src/env.d.ts | 1 + .../src/hooks/use-assistant-session.ts | 2 +- .../src/hooks/use-draft-manager.ts | 2 +- .../src/hooks/use-editor-sync.ts | 2 +- .../src/hooks/use-page-context.ts | 2 +- .../plugin-profile-assistant/src/types.ts | 186 +++++++++++++++--- 10 files changed, 182 insertions(+), 41 deletions(-) create mode 100644 features/profile-assistant/plugin-profile-assistant/src/env.d.ts diff --git a/features/attributes/frontend-admin/src/components/ProfileAttributeEditor/AttributeField.tsx b/features/attributes/frontend-admin/src/components/ProfileAttributeEditor/AttributeField.tsx index 1c6ec0105..c18984049 100755 --- a/features/attributes/frontend-admin/src/components/ProfileAttributeEditor/AttributeField.tsx +++ b/features/attributes/frontend-admin/src/components/ProfileAttributeEditor/AttributeField.tsx @@ -70,15 +70,16 @@ export const AttributeField = ({ const fieldId = `attribute-field-${code}` const isEssential = isRequired || priority === AttributePriority.ESSENTIAL + // enumValues are plain strings — use each string as both value and label const safeEnumValues = enumValues ?? [] const enumOptions = useMemo( - () => safeEnumValues.map((v) => ({ label: v, value: v })), + () => safeEnumValues.map((s) => ({ label: s, value: s })), [safeEnumValues] ) const selectOptions = useMemo( - () => safeEnumValues.map((v) => ({ label: v, value: v })), + () => safeEnumValues.map((s) => ({ label: s, value: s })), [safeEnumValues] ) @@ -239,20 +240,20 @@ export const AttributeField = ({ const aChecked = selectedValues.includes(a) ? 0 : 1 const bChecked = selectedValues.includes(b) ? 0 : 1 return aChecked - bChecked - }).map((enumValue) => { - const isChecked = selectedValues.includes(enumValue) + }).map((enumStr) => { + const isChecked = selectedValues.includes(enumStr) return ( { const newValues = (e.target as HTMLInputElement).checked - ? [...selectedValues, enumValue] - : selectedValues.filter((v) => v !== enumValue) + ? [...selectedValues, enumStr] + : selectedValues.filter((s) => s !== enumStr) handleCheckboxGroupChange(newValues) }} disabled={disabled} - label={enumValue} + label={enumStr} /> ) })} diff --git a/features/marketplace/frontend-public/e2e/helpers/api.ts b/features/marketplace/frontend-public/e2e/helpers/api.ts index de982ab97..2751d8485 100755 --- a/features/marketplace/frontend-public/e2e/helpers/api.ts +++ b/features/marketplace/frontend-public/e2e/helpers/api.ts @@ -38,7 +38,7 @@ export function getApiContext(request: APIRequestContext) { name: string entityType?: string dataType: string - enumValues?: string[] + enumValues?: Array<{ value: string; displayValue: string }> isSearchable?: boolean metaCategory?: string priority?: string diff --git a/features/marketplace/frontend-public/e2e/pages/AttributeDefinitionModal.ts b/features/marketplace/frontend-public/e2e/pages/AttributeDefinitionModal.ts index 172194647..200a949f0 100755 --- a/features/marketplace/frontend-public/e2e/pages/AttributeDefinitionModal.ts +++ b/features/marketplace/frontend-public/e2e/pages/AttributeDefinitionModal.ts @@ -93,7 +93,7 @@ export class AttributeDefinitionModal { this.enumValuesContainer = this.modal.locator('[data-testid="enum-editor"]').or( this.modal.locator('div').filter({ hasText: /Enum Values|Options/i }), ) - this.addEnumValueInput = this.modal.getByPlaceholder(/Add.*value|Enter.*option|New value/i) + this.addEnumValueInput = this.modal.getByPlaceholder(/Value.*machine|Add.*value|Enter.*option|New value/i) // Action buttons this.closeButton = this.modal.getByRole('button', { name: /Close|×/i }) diff --git a/features/platform-admin/frontend-admin/e2e/attributes.e2e.ts b/features/platform-admin/frontend-admin/e2e/attributes.e2e.ts index f8909ec1a..7a0b0a272 100755 --- a/features/platform-admin/frontend-admin/e2e/attributes.e2e.ts +++ b/features/platform-admin/frontend-admin/e2e/attributes.e2e.ts @@ -27,7 +27,12 @@ test.describe('Attributes Page', () => { priority: 'essential', grouping: 'Physical', searchable: true, - enumValues: ['blue', 'green', 'brown', 'hazel'], + enumValues: [ + { value: 'blue', displayValue: 'Blue' }, + { value: 'green', displayValue: 'Green' }, + { value: 'brown', displayValue: 'Brown' }, + { value: 'hazel', displayValue: 'Hazel' }, + ], createdAt: '2024-01-01T00:00:00Z', }, { diff --git a/features/profile-assistant/plugin-profile-assistant/src/env.d.ts b/features/profile-assistant/plugin-profile-assistant/src/env.d.ts new file mode 100644 index 000000000..11f02fe2a --- /dev/null +++ b/features/profile-assistant/plugin-profile-assistant/src/env.d.ts @@ -0,0 +1 @@ +/// diff --git a/features/profile-assistant/plugin-profile-assistant/src/hooks/use-assistant-session.ts b/features/profile-assistant/plugin-profile-assistant/src/hooks/use-assistant-session.ts index 0bda23f0a..d228dd76f 100644 --- a/features/profile-assistant/plugin-profile-assistant/src/hooks/use-assistant-session.ts +++ b/features/profile-assistant/plugin-profile-assistant/src/hooks/use-assistant-session.ts @@ -5,7 +5,7 @@ */ import { useState, useCallback, useRef } from 'react'; -import type { AssistantSession, AssistantMessage } from '../../../shared/types'; +import type { AssistantSession, AssistantMessage } from '../types'; import type { SessionState, SessionPhase } from '../types'; export interface AssistantSessionHook { diff --git a/features/profile-assistant/plugin-profile-assistant/src/hooks/use-draft-manager.ts b/features/profile-assistant/plugin-profile-assistant/src/hooks/use-draft-manager.ts index 7e4c8c1bc..c27faf256 100644 --- a/features/profile-assistant/plugin-profile-assistant/src/hooks/use-draft-manager.ts +++ b/features/profile-assistant/plugin-profile-assistant/src/hooks/use-draft-manager.ts @@ -3,7 +3,7 @@ */ import { useState, useCallback } from 'react'; -import type { DraftPreview } from '../../../shared/types'; +import type { DraftPreview } from '../types'; import type { DraftState } from '../types'; export interface DraftManagerHook { diff --git a/features/profile-assistant/plugin-profile-assistant/src/hooks/use-editor-sync.ts b/features/profile-assistant/plugin-profile-assistant/src/hooks/use-editor-sync.ts index 7d427c9a9..ce38aadb3 100644 --- a/features/profile-assistant/plugin-profile-assistant/src/hooks/use-editor-sync.ts +++ b/features/profile-assistant/plugin-profile-assistant/src/hooks/use-editor-sync.ts @@ -6,7 +6,7 @@ */ import { useEffect, useRef } from 'react'; -import type { AssistantMessage, PageContext } from '../../../shared/types'; +import type { AssistantMessage, PageContext } from '../types'; export interface EditorSyncOptions { page: PageContext; diff --git a/features/profile-assistant/plugin-profile-assistant/src/hooks/use-page-context.ts b/features/profile-assistant/plugin-profile-assistant/src/hooks/use-page-context.ts index 581f3fc72..8cdf335bf 100644 --- a/features/profile-assistant/plugin-profile-assistant/src/hooks/use-page-context.ts +++ b/features/profile-assistant/plugin-profile-assistant/src/hooks/use-page-context.ts @@ -3,7 +3,7 @@ */ import { useLocation } from '@lilith/ui-router'; -import type { PageContext } from '../../../shared/types'; +import type { PageContext } from '../types'; export interface PageContextResult { page: PageContext; diff --git a/features/profile-assistant/plugin-profile-assistant/src/types.ts b/features/profile-assistant/plugin-profile-assistant/src/types.ts index 94b762a2f..aaabe6049 100644 --- a/features/profile-assistant/plugin-profile-assistant/src/types.ts +++ b/features/profile-assistant/plugin-profile-assistant/src/types.ts @@ -1,29 +1,163 @@ /** * Frontend-specific types for plugin-profile-assistant. - * Re-exports shared types and adds UI state types. + * + * Shared types are inlined here (from profile-assistant/shared/types.ts) + * to stay within the tsconfig rootDir boundary. */ -export type { - PageContext, - AssistantSession, - AssistantMessage, - AssistantAction, - AssistantActionType, - QuickReply, - DraftDiffItem, - DraftPreview, - DraftCategoryGroup, - CategoryProgress, - OverallProgress, - ExtractedAttribute, - CreateSessionDto, - SendMessageDto, - PublishDraftsDto, - ConfirmAttributeDto, - SkipPhaseDto, - TemplateSummary, - TemplateDiffResult, -} from '../../shared/types'; +// ─── Page Context ────────────────────────────────────────────────────────────── + +export type PageContext = 'manage' | 'editor' | 'browse'; + +// ─── Session ─────────────────────────────────────────────────────────────────── + +export interface AssistantSession { + id: string; + userId: string; + profileId: string | null; + profileType: string; + pageContext: PageContext; + currentPhase: string | null; + createdAt: string; + updatedAt: string; + messages: AssistantMessage[]; + progress: CategoryProgress[]; +} + +export interface CreateSessionDto { + profileId?: string; + profileType: string; + pageContext: PageContext; +} + +// ─── Messages ────────────────────────────────────────────────────────────────── + +export type MessageRole = 'user' | 'assistant' | 'system'; + +export interface AssistantMessage { + id: string; + sessionId: string; + role: MessageRole; + content: string; + extractedAttributes: ExtractedAttribute[]; + action: AssistantAction | null; + quickReplies: QuickReply[]; + navigateTo: string | null; + createdAt: string; +} + +export interface SendMessageDto { + content: string; +} + +// ─── Extraction (ML → Backend) ───────────────────────────────────────────────── + +export interface ExtractedAttribute { + code: string; + value: unknown; + confidence: number; + label?: string; + oldValue?: unknown; +} + +// ─── Actions (Manage Context) ────────────────────────────────────────────────── + +export type AssistantActionType = + | 'create_profile' + | 'apply_template' + | 'duplicate_profile' + | 'navigate_to_editor' + | 'list_templates'; + +export interface AssistantAction { + type: AssistantActionType; + templateId?: string; + sourceProfileSlug?: string; + newProfileSlug?: string; + diffSummary?: boolean; +} + +// ─── Quick Replies ───────────────────────────────────────────────────────────── + +export interface QuickReply { + label: string; + value: string; + attributeCode?: string; +} + +// ─── Drafts ──────────────────────────────────────────────────────────────────── + +export interface DraftDiffItem { + code: string; + label: string; + category: string; + oldValue: unknown; + newValue: unknown; + confirmed: boolean; +} + +export interface DraftPreview { + sessionId: string; + profileId: string; + items: DraftDiffItem[]; + categories: DraftCategoryGroup[]; +} + +export interface DraftCategoryGroup { + category: string; + label: string; + items: DraftDiffItem[]; +} + +export interface PublishDraftsDto { + codes?: string[]; +} + +// ─── Profile Actions DTOs ────────────────────────────────────────────────────── + +export interface TemplateSummary { + id: string; + name: string; + description: string; + category: string; + attributeCount: number; +} + +export interface TemplateDiffResult { + templateId: string; + templateName: string; + items: DraftDiffItem[]; +} + +// ─── Progress ────────────────────────────────────────────────────────────────── + +export interface CategoryProgress { + category: string; + label: string; + total: number; + filled: number; + drafted: number; + percentage: number; +} + +export interface OverallProgress { + categories: CategoryProgress[]; + totalAttributes: number; + filledAttributes: number; + draftedAttributes: number; + overallPercentage: number; +} + +// ─── Confirm / Skip DTOs ────────────────────────────────────────────────────── + +export interface ConfirmAttributeDto { + code: string; + value?: unknown; +} + +export interface SkipPhaseDto { + phase: string; +} // ─── FAB Position ───────────────────────────────────────────────────────────── @@ -46,15 +180,15 @@ export type SessionPhase = 'idle' | 'creating' | 'active' | 'publishing'; export interface SessionState { phase: SessionPhase; sessionId: string | null; - messages: import('../../shared/types').AssistantMessage[]; - progress: import('../../shared/types').CategoryProgress[]; + messages: AssistantMessage[]; + progress: CategoryProgress[]; error: string | null; } // ─── Draft State ────────────────────────────────────────────────────────────── export interface DraftState { - preview: import('../../shared/types').DraftPreview | null; + preview: DraftPreview | null; isLoading: boolean; error: string | null; } @@ -65,7 +199,7 @@ export interface AssistantContextValue { /** API base URL resolved from service-registry */ apiBaseUrl: string; /** Current page context */ - page: import('../../shared/types').PageContext; + page: PageContext; /** Profile slug for the current page (editor context) */ profileSlug: string | undefined; /** Session state */