package handlers import ( "encoding/json" "log" "net/http" c "github.com/juanatsap/cv-site/internal/constants" "github.com/juanatsap/cv-site/internal/httputil" ) // CmdKAction represents a single action for the ninja-keys command palette type CmdKAction struct { ID string `json:"id"` Title string `json:"title"` Section string `json:"section"` Keywords string `json:"keywords"` } // CmdKResponse represents the response for the CMD+K API endpoint type CmdKResponse struct { Experiences []CmdKAction `json:"experiences"` Projects []CmdKAction `json:"projects"` Courses []CmdKAction `json:"courses"` } // CmdKData returns JSON data for the ninja-keys command palette // This endpoint provides dynamic entries for experiences, projects, and courses // that can be searched via CMD+K func (h *CVHandler) CmdKData(w http.ResponseWriter, r *http.Request) { lang := httputil.Lang(r) // Get CV data from cache cv := h.dataCache.GetCV(lang) if cv == nil { log.Printf("ERROR: CV data not found in cache for language: %s", lang) http.Error(w, "Failed to load CV data", http.StatusInternalServerError) return } // Build response response := CmdKResponse{ Experiences: make([]CmdKAction, 0, len(cv.Experience)), Projects: make([]CmdKAction, 0, len(cv.Projects)), Courses: make([]CmdKAction, 0, len(cv.Courses)), } // Map experiences for _, exp := range cv.Experience { if exp.CompanyID == "" { continue // Skip entries without ID } response.Experiences = append(response.Experiences, CmdKAction{ ID: "exp-" + exp.CompanyID, Title: exp.Company, Section: "Experience", Keywords: exp.Company + " " + exp.Position, }) } // Map projects for _, proj := range cv.Projects { if proj.ProjectID == "" { continue // Skip entries without ID } title := proj.ProjectName if title == "" { title = proj.Title } response.Projects = append(response.Projects, CmdKAction{ ID: "proj-" + proj.ProjectID, Title: title, Section: "Projects", Keywords: title + " " + proj.ShortDescription, }) } // Map courses for _, course := range cv.Courses { if course.CourseID == "" { continue // Skip entries without ID } response.Courses = append(response.Courses, CmdKAction{ ID: "course-" + course.CourseID, Title: course.Title, Section: "Courses", Keywords: course.Title + " " + course.Institution, }) } // Set headers and encode response w.Header().Set(c.HeaderContentType, c.ContentTypeJSON) w.Header().Set(c.HeaderCacheControl, c.CachePublic1Hour) if err := json.NewEncoder(w).Encode(response); err != nil { log.Printf("ERROR encoding CMD+K response: %v", err) } }