diff --git a/api/handler.go b/api/handler.go index 6b4151ad..ff2623bf 100644 --- a/api/handler.go +++ b/api/handler.go @@ -3,6 +3,7 @@ package api import ( "context" "encoding/json" + "fmt" "net/http" "github.com/Gleipnir-Technology/nidus-sync/auth" @@ -11,9 +12,12 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/html" nhttp "github.com/Gleipnir-Technology/nidus-sync/http" "github.com/Gleipnir-Technology/nidus-sync/platform" + "github.com/gorilla/schema" "github.com/rs/zerolog/log" ) +var decoder = schema.NewDecoder() + type handlerFunctionGet[T any] func(context.Context, *http.Request, *models.Organization, *models.User) (*T, *nhttp.ErrorWithStatus) type wrappedHandler func(http.ResponseWriter, *http.Request) type contentAuthenticated[T any] struct { @@ -26,7 +30,6 @@ type ErrorAPI struct { Message string `json:"message"` } -// w http.ResponseWriter, r *http.Request, u *models.User) { func authenticatedHandlerJSON[T any](f handlerFunctionGet[T]) http.Handler { return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, u *models.User) { ctx := r.Context() @@ -62,3 +65,52 @@ func authenticatedHandlerJSON[T any](f handlerFunctionGet[T]) http.Handler { w.Write(body) }) } + +type handlerFunctionPost[FormType any, ResponseType any] func(context.Context, *http.Request, *models.Organization, *models.User, FormType) (ResponseType, *nhttp.ErrorWithStatus) + +func authenticatedHandlerJSONPost[FormType any, ResponseType any](f handlerFunctionPost[FormType, ResponseType]) http.Handler { + return auth.NewEnsureAuth(func(w http.ResponseWriter, r *http.Request, u *models.User) { + w.Header().Set("Content-Type", "application/json") + err := r.ParseForm() + if err != nil { + respondError(w, http.StatusBadRequest, "failed to parse form: %w", err) + return + } + + var form FormType + err = decoder.Decode(&form, r.PostForm) + if err != nil { + respondError(w, http.StatusBadRequest, "Failed to decode form: %w", err) + return + } + ctx := r.Context() + org, err := u.Organization().One(ctx, db.PGInstance.BobDB) + if err != nil { + respondError(w, http.StatusInternalServerError, "Failed to get org: %w", err) + return + } + response, e := f(ctx, r, org, u, form) + if e != nil { + http.Error(w, e.Error(), e.Status) + return + } + resp_body, err := json.Marshal(response) + if err != nil { + respondError(w, http.StatusInternalServerError, "Failed to marshal json response: %w", err) + return + } + w.Write(resp_body) + }) +} + +func respondError(w http.ResponseWriter, status int, format string, args ...any) { + outer_err := fmt.Errorf(format, args...) + body, err := json.Marshal(ErrorAPI{ + Message: outer_err.Error(), + }) + if err != nil { + http.Error(w, "{\"message\": \"failed to marshal json\"}", http.StatusInternalServerError) + return + } + http.Error(w, string(body), status) +} diff --git a/api/lead.go b/api/lead.go new file mode 100644 index 00000000..2b36e87a --- /dev/null +++ b/api/lead.go @@ -0,0 +1,24 @@ +package api + +import ( + "context" + "net/http" + + "github.com/Gleipnir-Technology/nidus-sync/db/models" + nhttp "github.com/Gleipnir-Technology/nidus-sync/http" + "github.com/rs/zerolog/log" +) + +type formLeads struct { + SignalIDs []int `schema:"signal_ids"` +} +type createdLead struct { + ID int `json:"id"` +} + +func postLeads(ctx context.Context, r *http.Request, org *models.Organization, user *models.User, f formLeads) (*createdLead, *nhttp.ErrorWithStatus) { + log.Info().Ints("signal ids", f.SignalIDs).Msg("fake post leads") + return &createdLead{ + ID: 0, + }, nil +} diff --git a/api/routes.go b/api/routes.go index 818be715..3771d238 100644 --- a/api/routes.go +++ b/api/routes.go @@ -19,6 +19,7 @@ func AddRoutes(r chi.Router) { r.Method("POST", "/audio/{uuid}/content", auth.NewEnsureAuth(apiAudioContentPost)) r.Method("POST", "/image/{uuid}", auth.NewEnsureAuth(apiImagePost)) r.Method("POST", "/image/{uuid}/content", auth.NewEnsureAuth(apiImageContentPost)) + r.Method("POST", "/leads", authenticatedHandlerJSONPost(postLeads)) // Unauthenticated endpoints r.Get("/district", apiGetDistrict) diff --git a/html/template/sync/intelligence-root.html b/html/template/sync/intelligence-root.html index e7c37b6b..2c521bbf 100644 --- a/html/template/sync/intelligence-root.html +++ b/html/template/sync/intelligence-root.html @@ -152,9 +152,6 @@ }, body: JSON.stringify({ signal_ids: this.selectedSignals.map((s) => s.id), - // Add any other required fields - created_by: "current_user", // Replace with actual user - timestamp: new Date().toISOString(), }), }); diff --git a/sync/dash.go b/sync/dash.go index 22f2e21f..d0915c6b 100644 --- a/sync/dash.go +++ b/sync/dash.go @@ -261,9 +261,10 @@ func dashboard(ctx context.Context, w http.ResponseWriter, org *models.Organizat return } html.RenderOrError(w, "sync/dashboard.html", contentAuthenticated[contentDashboard]{ - C: content, - URL: html.NewContentURL(), - User: userContent, + C: content, + Organization: org, + URL: html.NewContentURL(), + User: userContent, }) } diff --git a/sync/handler.go b/sync/handler.go index 31ccc2fd..95d47c71 100644 --- a/sync/handler.go +++ b/sync/handler.go @@ -10,9 +10,12 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/html" nhttp "github.com/Gleipnir-Technology/nidus-sync/http" "github.com/Gleipnir-Technology/nidus-sync/platform" + "github.com/gorilla/schema" "github.com/rs/zerolog/log" ) +var decoder = schema.NewDecoder() + type handlerFunctionGet[T any] func(context.Context, *http.Request, *models.Organization, *models.User) (*html.Response[T], *nhttp.ErrorWithStatus) type wrappedHandler func(http.ResponseWriter, *http.Request) type contentAuthenticated[T any] struct { diff --git a/sync/sudo.go b/sync/sudo.go index a28efe83..4ffdfff3 100644 --- a/sync/sudo.go +++ b/sync/sudo.go @@ -12,7 +12,6 @@ import ( "github.com/Gleipnir-Technology/nidus-sync/db/models" "github.com/Gleipnir-Technology/nidus-sync/html" nhttp "github.com/Gleipnir-Technology/nidus-sync/http" - "github.com/gorilla/schema" "github.com/rs/zerolog/log" ) @@ -35,8 +34,6 @@ func getSudo(ctx context.Context, r *http.Request, org *models.Organization, use return html.NewResponse("sync/sudo.html", content), nil } -var decoder = schema.NewDecoder() - type FormEmail struct { Body string `schema:"emailBody"` From string `schema:"emailFrom"`