Add optimized doctor search endpoint
This commit is contained in:
103
internal/http/dokter.go
Normal file
103
internal/http/dokter.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"primaya-api/cpone-middleware/internal/repository"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultDokterPerPage = 15
|
||||
maxDokterPerPage = 100
|
||||
)
|
||||
|
||||
type DokterPaginationResponse struct {
|
||||
CurrentPage int `json:"current_page"`
|
||||
Data []repository.Dokter `json:"data"`
|
||||
FirstPageURL string `json:"first_page_url"`
|
||||
From *int `json:"from"`
|
||||
LastPage int `json:"last_page"`
|
||||
LastPageURL string `json:"last_page_url"`
|
||||
Links map[string]any `json:"links"`
|
||||
NextPageURL *string `json:"next_page_url"`
|
||||
Total int `json:"total"`
|
||||
PerPage int `json:"per_page"`
|
||||
}
|
||||
|
||||
func (h Handler) ListDokter(w http.ResponseWriter, r *http.Request) {
|
||||
page := parseDokterPage(r.URL.Query().Get("page"))
|
||||
perPage := parseDokterPerPage(r.URL.Query().Get("per_page"))
|
||||
|
||||
doctorIDs := queryValues(r, "DokterID_in", "DokterID_in[]")
|
||||
doctorIDs = splitDoctorIDs(doctorIDs)
|
||||
|
||||
result, err := h.dokterRepository(r.Context()).ListDokter(r.Context(), repository.DokterListParams{
|
||||
Search: strings.TrimSpace(r.URL.Query().Get("search")), DoctorIDs: doctorIDs,
|
||||
Page: page, PerPage: perPage,
|
||||
})
|
||||
if err != nil {
|
||||
WriteJSON(w, http.StatusInternalServerError, Response{Success: false, Message: "internal server error", Data: nil})
|
||||
return
|
||||
}
|
||||
|
||||
lastPage := (result.Total + perPage - 1) / perPage
|
||||
if lastPage < 1 {
|
||||
lastPage = 1
|
||||
}
|
||||
var from *int
|
||||
if len(result.Items) > 0 {
|
||||
value := (page-1)*perPage + 1
|
||||
from = &value
|
||||
}
|
||||
var nextPageURL *string
|
||||
if page < lastPage {
|
||||
value := currentRequestURL(r, page+1)
|
||||
nextPageURL = &value
|
||||
}
|
||||
|
||||
WriteJSON(w, http.StatusOK, DokterPaginationResponse{
|
||||
CurrentPage: page, Data: result.Items, FirstPageURL: "", From: from,
|
||||
LastPage: lastPage, LastPageURL: "", Links: map[string]any{},
|
||||
NextPageURL: nextPageURL, Total: result.Total, PerPage: perPage,
|
||||
})
|
||||
}
|
||||
|
||||
func parseDokterPage(raw string) int {
|
||||
value, err := strconv.Atoi(raw)
|
||||
if err != nil || value < 1 {
|
||||
return 1
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func parseDokterPerPage(raw string) int {
|
||||
value, err := strconv.Atoi(raw)
|
||||
if err != nil || value < 1 {
|
||||
return defaultDokterPerPage
|
||||
}
|
||||
if value > maxDokterPerPage {
|
||||
return maxDokterPerPage
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
func splitDoctorIDs(values []string) []string {
|
||||
seen := make(map[string]struct{}, len(values))
|
||||
result := make([]string, 0, len(values))
|
||||
for _, value := range values {
|
||||
for _, part := range strings.Split(value, ",") {
|
||||
part = strings.TrimSpace(part)
|
||||
if part == "" {
|
||||
continue
|
||||
}
|
||||
if _, exists := seen[part]; exists {
|
||||
continue
|
||||
}
|
||||
seen[part] = struct{}{}
|
||||
result = append(result, part)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user