feat(api): get cover letters with api
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
|||||||
res "backend/utils/responses"
|
res "backend/utils/responses"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/go-playground/validator/v10"
|
"github.com/go-playground/validator/v10"
|
||||||
@@ -16,7 +17,61 @@ import (
|
|||||||
|
|
||||||
var validate = validator.New()
|
var validate = validator.New()
|
||||||
|
|
||||||
|
type CoverGet struct {
|
||||||
|
Id int `json:"id"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
func Get(c *gin.Context) {
|
func Get(c *gin.Context) {
|
||||||
|
user, err := jwt.GetUser(c)
|
||||||
|
if err != nil {
|
||||||
|
res.NeedsToLogin(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
covers, err := cover.Get("user_id = $1", user.Id)
|
||||||
|
if err != nil {
|
||||||
|
res.Error(c, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Asign only id and name, for efficieny
|
||||||
|
coverPreviews := make([]CoverGet, len(covers))
|
||||||
|
for i, cover := range covers {
|
||||||
|
coverPreviews[i] = CoverGet{
|
||||||
|
Id: cover.ID,
|
||||||
|
Name: cover.Name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Success(c, gin.H{"covers": coverPreviews})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetID(c *gin.Context) {
|
||||||
|
id, err := strconv.Atoi(c.Param("id"))
|
||||||
|
if err != nil {
|
||||||
|
res.Error(c, err.Error(), http.StatusBadRequest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := jwt.GetUser(c)
|
||||||
|
if err != nil {
|
||||||
|
res.NeedsToLogin(c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cover, err := cover.Get("id = $1 AND user_id = $2", id, user.Id)
|
||||||
|
if err != nil {
|
||||||
|
res.Error(c, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cover) == 0 {
|
||||||
|
res.Error(c, "Cover not found", http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
res.Success(c, gin.H{"cover": cover[0]})
|
||||||
}
|
}
|
||||||
|
|
||||||
type CoverPost struct {
|
type CoverPost struct {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Template struct {
|
type Cover struct {
|
||||||
ID int `json:"id"`
|
ID int `json:"id"`
|
||||||
UserID int `json:"user_id"`
|
UserID int `json:"user_id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
@@ -14,7 +14,7 @@ type Template struct {
|
|||||||
CreatedAt time.Time `json:"created_at"`
|
CreatedAt time.Time `json:"created_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func Get(where string, args ...any) ([]Template, error) {
|
func Get(where string, args ...any) ([]Cover, error) {
|
||||||
// Create timeout context
|
// Create timeout context
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
@@ -36,9 +36,9 @@ func Get(where string, args ...any) ([]Template, error) {
|
|||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
// Prepeare results now
|
// Prepeare results now
|
||||||
var results []Template
|
var results []Cover
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var t Template
|
var t Cover
|
||||||
if err := rows.Scan(&t.ID, &t.UserID, &t.Name, &t.Letter, &t.CreatedAt); err != nil {
|
if err := rows.Scan(&t.ID, &t.UserID, &t.Name, &t.Letter, &t.CreatedAt); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ func SetupRoutes() *gin.Engine {
|
|||||||
|
|
||||||
// Cover letter routes
|
// Cover letter routes
|
||||||
covers := auth.Group("/cover")
|
covers := auth.Group("/cover")
|
||||||
|
covers.GET("", cover.Get)
|
||||||
|
covers.GET("/:id", cover.GetID)
|
||||||
covers.POST("", cover.Post)
|
covers.POST("", cover.Post)
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|||||||
@@ -37,12 +37,12 @@ func GenerateCoverLetter(templateHTML string, jobHTML string) (GeneratedCover, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
payload := ChatRequest{
|
payload := ChatRequest{
|
||||||
Model: "gpt-4o", // o4-mini
|
Model: "gpt-4o", // o4-mini
|
||||||
ResponseFormat: &ResponseFormat{Type: "json_object"},
|
ResponseFormat: &ResponseFormat{Type: "json_object"},
|
||||||
Messages: []ChatMessage{
|
Messages: []ChatMessage{
|
||||||
{
|
{
|
||||||
Role: "system",
|
Role: "system",
|
||||||
Content: `You are a helpful assistant that fills out cover letter templates in HTML format and provides a name for it. Replace all <...> tags like <company>, <experience>, etc., with appropriate content based on the job application. You must respond with a JSON object with two keys: "name" for the cover letter title (e.g., "Cover Letter for a Software Engineer"), and "cover" for the filled HTML cover letter.`,
|
Content: `You are a helpful assistant that fills out cover letter templates in HTML format and provides a name for it. Replace all <...> tags like <company>, <experience>, etc., with appropriate content based on the job application. You must respond with a JSON object with two keys: "name" for the cover letter title (e.g., "Software Engineer at OpenAi"), and "cover" for the filled HTML cover letter.`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Role: "user",
|
Role: "user",
|
||||||
|
|||||||
Reference in New Issue
Block a user