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 {