# Structured Catalog Architecture - Frontend Example ## ❌ **OLD WAY (Bad)**: Name Matching in Frontend ```typescript // WRONG: Frontend doing business logic and name matching const [plans, setPlans] = useState([]); // Bad API call - flat structure requiring guesswork const catalog = await api.get<{internet: InternetPlan[]}>("/catalog"); // Terrible: Guessing product types by name matching const isSilver = plan.name?.toLowerCase().includes('silver'); const isGold = plan.name?.toLowerCase().includes('gold'); const isPlatinum = plan.name?.toLowerCase().includes('platinum'); // Bad: SKU parsing in frontend const hikariService = addons.find(addon => addon.sku.includes('HOME-PHONE') || addon.sku.includes('HIKARI-DENWA') ); // Bad: Installation type guessing const installationProduct = installations.find(inst => inst.sku.toLowerCase().includes('12') || inst.name.toLowerCase().includes('12') ); // Frontend doing business logic it shouldn't {isSilver && (
Basic setup - bring your own router
)} {isGold && (
Complete solution with v6plus router
)} ``` ## ✅ **NEW WAY (Good)**: Structured Data from Backend ```typescript // CORRECT: Backend organizes everything, frontend just displays const [catalogData, setCatalogData] = useState(null); // Good API call - fully structured data const catalog = await api.get("/catalog/structured"); // No name matching needed! Backend already organized everything const { internet } = catalog; const { plans, installations, addons } = internet; // Frontend just displays structured data {plans.map(plan => ( ))} // Add-ons are properly typed and organized {addons .filter(addon => addon.type === 'hikari-denwa-service') .map(addon => ( ))} // Installation options - no guessing needed {installations.map(inst => ( ))} ``` ## 🔄 **API Response Structure** ### Old Response (Bad) ```json { "internet": [ {"id": "1", "name": "Internet Gold Plan (Home 1G)", "sku": "INTERNET-GOLD-HOME-1G"}, {"id": "2", "name": "Internet Silver Plan (Home 1G)", "sku": "INTERNET-SILVER-HOME-1G"} ] } ``` *Frontend has to guess everything from names/SKUs! 😞* ### New Response (Good) ```json { "internet": { "plans": [ { "id": "1", "name": "Internet Gold Plan (Home 1G)", "sku": "INTERNET-GOLD-HOME-1G", "tier": "Gold", "offeringType": "Home 1G", "monthlyPrice": 6500, "description": "Complete solution with v6plus router included", "features": [ "1 NTT Wireless Home Gateway Router (v6plus compatible)", "1 SonixNet ISP (IPoE-HGW) Activation + Monthly", "Professional setup included" ], "tierDescription": "Recommended", "isRecommended": true } ], "installations": [ { "id": "10", "name": "NTT Installation Fee (12-Month Plan)", "sku": "INTERNET-INSTALL-12M", "type": "12-Month", "price": 1900, "billingCycle": "Monthly", "description": "NTT Installation Fee (12-Month Plan)" } ], "addons": [ { "id": "20", "name": "Hikari Denwa (Home Phone)", "sku": "INTERNET-ADDON-HOME-PHONE", "type": "hikari-denwa-service", "monthlyPrice": 450, "autoAdd": false, "requiredWith": ["INTERNET-ADDON-HIKARI-DENWA-INSTALL"] }, { "id": "21", "name": "Hikari Denwa Installation Fee", "sku": "INTERNET-ADDON-HIKARI-DENWA-INSTALL", "type": "hikari-denwa-installation", "activationPrice": 1000, "autoAdd": true, "requiredWith": [] } ] } } ``` *Everything pre-organized! Frontend just displays! 🎉* ## 🎯 **Benefits of Structured Approach** ### 1. **No Name Matching** - ❌ `plan.name.includes('gold')` - ✅ `plan.tier === 'Gold'` ### 2. **No SKU Parsing** - ❌ `addon.sku.includes('HIKARI-DENWA')` - ✅ `addon.type === 'hikari-denwa-service'` ### 3. **Business Logic in Right Place** - ❌ Frontend calculating features based on tier names - ✅ Backend provides pre-computed `plan.features` array ### 4. **Salesforce Field Mapping** - ❌ Frontend guessing product types - ✅ Backend uses actual `Internet_Plan_Tier__c`, `Addon_Type__c`, `Installation_Type__c` fields ### 5. **Extensible Without Code Changes** - ❌ New product types break name matching - ✅ New Salesforce fields automatically supported ### 6. **Type Safety** - ❌ String matching is error-prone - ✅ Strongly typed enums: `'Silver' | 'Gold' | 'Platinum'` ## 🚀 **Implementation Steps** 1. **Add Salesforce Fields** (if missing): ```sql -- Custom fields for proper categorization Internet_Plan_Tier__c (Picklist): Silver | Gold | Platinum Addon_Type__c (Text): Hikari Denwa Service | Hikari Denwa Installation Installation_Type__c (Picklist): One-time | 12-Month | 24-Month ``` 2. **Use New Backend Endpoint**: ```typescript // Replace this: const catalog = await api.get("/catalog"); // With this: const catalog = await api.get("/catalog/structured"); ``` 3. **Update Frontend Components**: ```typescript // Remove all name matching logic // Use structured data properties instead // Old: plan.name?.toLowerCase().includes('gold') // New: plan.tier === 'Gold' ``` 4. **Add New Salesforce Fields to Field Mapping**: ```typescript // In field-map.ts internetPlanTier: "Internet_Plan_Tier__c", addonType: "Addon_Type__c", installationType: "Installation_Type__c" ``` This approach makes the frontend much simpler, more reliable, and fully leverages Salesforce's structured data instead of relying on fragile name matching!