Redesign configurator UI with tabs and remove Excel export

- Add tab-based configurator (Base, Storage, PCI, Power, Accessories, Other)
- Base tab: single-select with autocomplete for MB, CPU, MEM
- Other tabs: multi-select with autocomplete and quantity input
- Table view with LOT, Description, Price, Quantity, Total columns
- Add configuration list page with create modal (opportunity number)
- Remove Excel export functionality and excelize dependency
- Increase component list limit from 100 to 5000
- Add web templates (base, index, configs, login, admin_pricing)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Mikhail Chusavitin
2026-01-26 15:57:15 +03:00
parent 44ccb01203
commit a93644131c
14 changed files with 2041 additions and 201 deletions

View File

@@ -6,9 +6,9 @@ import (
"time"
"github.com/gin-gonic/gin"
"github.com/mchus/quoteforge/internal/middleware"
"github.com/mchus/quoteforge/internal/models"
"github.com/mchus/quoteforge/internal/services"
"git.mchus.pro/mchus/quoteforge/internal/middleware"
"git.mchus.pro/mchus/quoteforge/internal/models"
"git.mchus.pro/mchus/quoteforge/internal/services"
)
type ExportHandler struct {
@@ -59,26 +59,6 @@ func (h *ExportHandler) ExportCSV(c *gin.Context) {
c.Data(http.StatusOK, "text/csv; charset=utf-8", csvData)
}
func (h *ExportHandler) ExportXLSX(c *gin.Context) {
var req ExportRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
data := h.buildExportData(&req)
xlsxData, err := h.exportService.ToXLSX(data)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
filename := fmt.Sprintf("%s_%s.xlsx", req.Name, time.Now().Format("20060102"))
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", xlsxData)
}
func (h *ExportHandler) buildExportData(req *ExportRequest) *services.ExportData {
items := make([]services.ExportItem, len(req.Items))
var total float64
@@ -126,29 +106,6 @@ func (h *ExportHandler) ExportConfigCSV(c *gin.Context) {
c.Data(http.StatusOK, "text/csv; charset=utf-8", csvData)
}
func (h *ExportHandler) ExportConfigXLSX(c *gin.Context) {
userID := middleware.GetUserID(c)
uuid := c.Param("uuid")
config, err := h.configService.GetByUUID(uuid, userID)
if err != nil {
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
return
}
data := h.configToExportData(config)
xlsxData, err := h.exportService.ToXLSX(data)
if err != nil {
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
return
}
filename := fmt.Sprintf("%s_%s.xlsx", config.Name, config.CreatedAt.Format("20060102"))
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
c.Data(http.StatusOK, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", xlsxData)
}
func (h *ExportHandler) configToExportData(config *models.Configuration) *services.ExportData {
items := make([]services.ExportItem, len(config.Items))
var total float64