diff --git a/src/components/admin/admin-dashboard.tsx b/src/components/admin/admin-dashboard.tsx index 11c610a..db72856 100644 --- a/src/components/admin/admin-dashboard.tsx +++ b/src/components/admin/admin-dashboard.tsx @@ -56,6 +56,8 @@ function AdminDashboardContent() { const { unreadCount, removeByReference } = useAdminNotifications() + console.log("pendingFeatures__", pendingFeatures) + // Load dashboard data const loadDashboardData = async () => { try { @@ -184,18 +186,9 @@ function AdminDashboardContent() { // Get the feature details first const feature = pendingFeatures.find(f => f.id === item.id) if (feature) { - // Create new approved feature in main template_features table - await adminApi.createApprovedFeature({ - template_id: feature.template_id, - name: feature.name, - description: feature.description, - complexity: feature.complexity, - business_rules: feature.business_rules, - technical_requirements: feature.technical_requirements - }) - - // Update the custom feature status to approved - await adminApi.reviewCustomFeature(item.id, { status: 'approved', admin_notes: 'Approved and created in main templates' }) + // Only update the custom feature status to approved + // The backend reviewFeature method will handle mirroring to template_features if needed + await adminApi.reviewCustomFeature(item.id, { status: 'approved', admin_notes: 'Approved by admin' }) // already optimistically removed // Remove related notifications for this feature @@ -532,7 +525,7 @@ function AdminDashboardContent() { )}
- Template: {feature.template_title || 'Unknown'} + Template Type: {feature.template_type || 'Unknown'} Submitted: {formatDate(feature.created_at)} {feature.similarity_score && ( Similarity: {(feature.similarity_score * 100).toFixed(1)}% diff --git a/src/components/main-dashboard.tsx b/src/components/main-dashboard.tsx index e8a2c72..73a99e6 100644 --- a/src/components/main-dashboard.tsx +++ b/src/components/main-dashboard.tsx @@ -904,9 +904,21 @@ function FeatureSelectionStep({ const load = async () => { try { setLoading(true) + console.log('[FeatureSelectionStep] Loading features for template:', template.id) + console.log('[FeatureSelectionStep] Template object:', template) const data = await fetchFeatures(template.id) + console.log('[FeatureSelectionStep] Raw features received:', data) + console.log('[FeatureSelectionStep] API endpoint called:', `/api/templates/${template.id}/features`) + console.log('[FeatureSelectionStep] Features by type:', { + essential: data.filter(f => f.feature_type === 'essential').length, + suggested: data.filter(f => f.feature_type === 'suggested').length, + custom: data.filter(f => f.feature_type === 'custom').length, + total: data.length + }) + console.log('[FeatureSelectionStep] All features with types:', data.map(f => ({ name: f.name, type: f.feature_type }))) setFeatures(data) } catch (e) { + console.error('[FeatureSelectionStep] Error loading features:', e) setError(e instanceof Error ? e.message : 'Failed to load features') } finally { setLoading(false) @@ -1076,8 +1088,7 @@ function FeatureSelectionStep({

Choose defaults or add your own custom features.

- {section('Essential Features', essentials)} - {/* {section('Suggested Features', suggested)} */} + {features.length > 0 && section('Template Features', features)} {/* Add custom feature with AI */}
diff --git a/src/config/backend.ts b/src/config/backend.ts index 0fce8d5..f570ef0 100644 --- a/src/config/backend.ts +++ b/src/config/backend.ts @@ -4,7 +4,7 @@ */ // Main backend URL - change this to update all API calls -export const BACKEND_URL = 'http://192.168.1.25:8000'; +export const BACKEND_URL = 'http://192.168.1.20:8000'; // export const BACKEND_URL = 'https://backend.codenuk.com'; diff --git a/src/lib/template-service.ts b/src/lib/template-service.ts index a625576..e394d18 100644 --- a/src/lib/template-service.ts +++ b/src/lib/template-service.ts @@ -54,7 +54,6 @@ export interface TemplatesByCategory { } - class TemplateService { private async makeRequest(endpoint: string, requireAuth: boolean = false): Promise { try { @@ -391,9 +390,9 @@ class TemplateService { const toKey = (f: TemplateFeature) => { const normName = (f.name || '').trim().toLowerCase() - // For custom features, dedupe by normalized name; for others, prefer feature_id - if (f.feature_type === 'custom') return `custom:${normName}` - return `std:${f.feature_id || normName}` + // Use normalized name for all features to enable proper deduplication + // between template_features and custom_features tables + return normName } const prefer = (a: TemplateFeature, b: TemplateFeature): TemplateFeature => { @@ -419,6 +418,12 @@ class TemplateService { } } + console.log('[getFeaturesForTemplate] Deduplication results:', { + originalCount: items.length, + deduplicatedCount: byKey.size, + duplicatesRemoved: items.length - byKey.size + }) + return Array.from(byKey.values()) } @@ -468,13 +473,28 @@ class TemplateService { // Only include normalized fields if valid business_rules: normalizeJsonField(featureData.business_rules) as CreateFeaturePayload['business_rules'], logic_rules: normalizeJsonField(featureData.logic_rules) as CreateFeaturePayload['logic_rules'], - // @ts-expect-error: allow passthrough of optional technical_requirements if present in callers technical_requirements: normalizeJsonField((featureData as any).technical_requirements), } + // Check if this is for a custom template by checking if template exists in custom_templates + let isCustomTemplate = false + if (cleanedFeatureData.template_id) { + try { + // Check if template exists in custom_templates table + const templateCheckResponse = await fetch(`${BACKEND_URL}/api/templates/${cleanedFeatureData.template_id}`) + if (templateCheckResponse.ok) { + const templateData = await templateCheckResponse.json() + // If template has is_custom flag or comes from custom_templates, route to custom endpoint + isCustomTemplate = templateData.data?.is_custom === true || templateData.data?.template_type === 'custom' + } + } catch (error) { + console.warn('Could not check template type, defaulting to regular endpoint:', error) + } + } + if ( cleanedFeatureData && - (cleanedFeatureData.feature_type === 'custom') + (cleanedFeatureData.feature_type === 'custom' || isCustomTemplate) ) { const customHeaders: Record = { 'Content-Type': 'application/json' } const customToken = getAccessToken() diff --git a/src/types/admin.types.ts b/src/types/admin.types.ts index c995efb..a5a66e6 100644 --- a/src/types/admin.types.ts +++ b/src/types/admin.types.ts @@ -22,6 +22,7 @@ export interface AdminFeature { similarity_score?: number; // Additional fields from joins template_title?: string; + template_type?: string; } export interface AdminNotification {