From e33a3f2c8806fa081afe797c696342e852f6442f Mon Sep 17 00:00:00 2001 From: Michael Chus Date: Tue, 3 Feb 2026 07:15:03 +0300 Subject: [PATCH] fix: enable component search and pricing in offline mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem:** Configurator was broken in offline mode - no component search and no price calculation because /api/components returned empty list. **Solution:** Added local component fallback to ComponentHandler: 1. **ComponentHandler with localDB** (component.go) - Added localDB parameter to NewComponentHandler - List() now fallbacks to local_components when offline - Converts LocalComponent to ComponentView format - Preserves prices from local cache 2. **Updated initialization** (main.go) - Pass localDB to NewComponentHandler **Impact:** - ✅ Component search works offline - ✅ Prices load from local_components table - ✅ Configuration creation fully functional offline - ✅ Price calculation works with cached prices **Testing:** - Verified /api/components returns local components - Verified current_price field populated from cache - Search, filtering, and pagination work correctly Fixes critical Phase 2.5 offline mode issue. Co-Authored-By: Claude Sonnet 4.5 --- cmd/server/main.go | 2 +- internal/handlers/component.go | 43 ++++++++++++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/cmd/server/main.go b/cmd/server/main.go index 192991c..3f607f9 100644 --- a/cmd/server/main.go +++ b/cmd/server/main.go @@ -364,7 +364,7 @@ func setupRouter(cfg *config.Config, local *localdb.LocalDB, connMgr *db.Connect configService := services.NewLocalConfigurationService(local, syncService, quoteService, isOnline) // Handlers - componentHandler := handlers.NewComponentHandler(componentService) + componentHandler := handlers.NewComponentHandler(componentService, local) quoteHandler := handlers.NewQuoteHandler(quoteService) exportHandler := handlers.NewExportHandler(exportService, configService, componentService) pricingHandler := handlers.NewPricingHandler(mariaDB, pricingService, alertService, componentRepo, priceRepo, statsRepo) diff --git a/internal/handlers/component.go b/internal/handlers/component.go index 4791ae0..1609c27 100644 --- a/internal/handlers/component.go +++ b/internal/handlers/component.go @@ -5,16 +5,21 @@ import ( "strconv" "github.com/gin-gonic/gin" + "git.mchus.pro/mchus/quoteforge/internal/localdb" "git.mchus.pro/mchus/quoteforge/internal/repository" "git.mchus.pro/mchus/quoteforge/internal/services" ) type ComponentHandler struct { componentService *services.ComponentService + localDB *localdb.LocalDB } -func NewComponentHandler(componentService *services.ComponentService) *ComponentHandler { - return &ComponentHandler{componentService: componentService} +func NewComponentHandler(componentService *services.ComponentService, localDB *localdb.LocalDB) *ComponentHandler { + return &ComponentHandler{ + componentService: componentService, + localDB: localDB, + } } func (h *ComponentHandler) List(c *gin.Context) { @@ -34,6 +39,40 @@ func (h *ComponentHandler) List(c *gin.Context) { return } + // If offline mode (empty result), fallback to local components + if result.Total == 0 && h.localDB != nil { + localFilter := localdb.ComponentFilter{ + Category: filter.Category, + Search: filter.Search, + HasPrice: filter.HasPrice, + } + + offset := (page - 1) * perPage + localComps, total, err := h.localDB.ListComponents(localFilter, offset, perPage) + if err == nil && len(localComps) > 0 { + // Convert local components to ComponentView format + components := make([]services.ComponentView, len(localComps)) + for i, lc := range localComps { + components[i] = services.ComponentView{ + LotName: lc.LotName, + Description: lc.LotDescription, + Category: lc.Category, + CategoryName: lc.Category, // No translation in local mode + Model: lc.Model, + CurrentPrice: lc.CurrentPrice, + } + } + + c.JSON(http.StatusOK, &services.ComponentListResult{ + Components: components, + Total: total, + Page: page, + PerPage: perPage, + }) + return + } + } + c.JSON(http.StatusOK, result) }