chore: restructure project into backend and frontend folders
- Move all frontend code to frontend/ directory - Add backend/ with Go project structure (cmd, internal, pkg) - Add docker-compose.yml for orchestration
This commit is contained in:
181
backend/internal/delivery/handler.go
Normal file
181
backend/internal/delivery/handler.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package delivery
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
sqlc "github.com/chedius/delivery-tracker/internal/db/sqlc"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
queries *sqlc.Queries
|
||||
}
|
||||
|
||||
// DeliveryRequest represents the request body for creating or updating a delivery
|
||||
type DeliveryRequest struct {
|
||||
Date string `json:"date" binding:"required"` // DD-MM-YYYY
|
||||
PickupLocation string `json:"pickup_location" binding:"required,oneof=warehouse symbat nursaya galaktika"`
|
||||
ProductName string `json:"product_name" binding:"required"`
|
||||
Address string `json:"address" binding:"required"`
|
||||
Phone string `json:"phone" binding:"required"`
|
||||
AdditionalPhone string `json:"additional_phone"`
|
||||
HasElevator bool `json:"has_elevator"`
|
||||
Comment string `json:"comment"`
|
||||
}
|
||||
|
||||
func NewHandler(queries *sqlc.Queries) *Handler {
|
||||
return &Handler{queries: queries}
|
||||
}
|
||||
|
||||
// GET /api/deliveries/:id
|
||||
func (h *Handler) GetDeliveryByID(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "ID is required"})
|
||||
return
|
||||
}
|
||||
parsedID, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid UUID format", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
delivery, err := h.queries.GetDeliveryByID(c.Request.Context(), pgtype.UUID{Bytes: parsedID, Valid: true})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get delivery", "details": err.Error(), "id": id, "bytes": [16]byte([]byte(id))})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"delivery": delivery})
|
||||
}
|
||||
|
||||
// GET /api/deliveries?date=DD-MM-YYYY
|
||||
func (h *Handler) GetDeliveries(c *gin.Context) {
|
||||
t, err := parseDate(c.Query("date"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid date format", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
date := pgtype.Date{Time: t, Valid: true}
|
||||
deliveries, err := h.queries.GetDeliveriesByDate(c.Request.Context(), date)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to get deliveries", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"deliveries": deliveries})
|
||||
}
|
||||
|
||||
// POST /api/deliveries
|
||||
func (h *Handler) CreateDelivery(c *gin.Context) {
|
||||
var req DeliveryRequest = DeliveryRequest{}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
// Parse date from DD-MM-YYYY
|
||||
t, err := parseDate(req.Date)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid date format", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
params := sqlc.CreateDeliveryParams{
|
||||
Date: pgtype.Date{Time: t, Valid: true},
|
||||
PickupLocation: req.PickupLocation,
|
||||
ProductName: req.ProductName,
|
||||
Address: req.Address,
|
||||
Phone: req.Phone,
|
||||
AdditionalPhone: pgtype.Text{String: req.AdditionalPhone, Valid: req.AdditionalPhone != ""},
|
||||
HasElevator: req.HasElevator,
|
||||
Comment: pgtype.Text{String: req.Comment, Valid: true},
|
||||
}
|
||||
res, err := h.queries.CreateDelivery(c.Request.Context(), params)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create delivery", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Delivery created", "id": res.ID.String()})
|
||||
}
|
||||
|
||||
// PATCH /api/deliveries/:id
|
||||
func (h *Handler) UpdateDelivery(c *gin.Context) {
|
||||
var req DeliveryRequest = DeliveryRequest{}
|
||||
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid request body", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
id := c.Param("id")
|
||||
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "ID is required"})
|
||||
return
|
||||
}
|
||||
|
||||
parsedID, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid UUID format", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
t, err := parseDate(req.Date)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid date format", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.queries.UpdateDelivery(c.Request.Context(), sqlc.UpdateDeliveryParams{
|
||||
ID: pgtype.UUID{Bytes: parsedID, Valid: true},
|
||||
Date: pgtype.Date{Time: t, Valid: true},
|
||||
PickupLocation: req.PickupLocation,
|
||||
ProductName: req.ProductName,
|
||||
Address: req.Address,
|
||||
Phone: req.Phone,
|
||||
AdditionalPhone: pgtype.Text{String: req.AdditionalPhone, Valid: req.AdditionalPhone != ""},
|
||||
HasElevator: req.HasElevator,
|
||||
Comment: pgtype.Text{String: req.Comment, Valid: true},
|
||||
}); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update delivery", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Delivery updated"})
|
||||
}
|
||||
|
||||
// DELETE /api/deliveries/:id
|
||||
func (h *Handler) DeleteDelivery(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "ID is required"})
|
||||
return
|
||||
}
|
||||
|
||||
parsedID, err := uuid.Parse(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid UUID format", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.queries.DeleteDelivery(c.Request.Context(), pgtype.UUID{Bytes: parsedID, Valid: true}); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to delete delivery", "details": err.Error()})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Delivery deleted"})
|
||||
}
|
||||
|
||||
func parseDate(dateStr string) (time.Time, error) {
|
||||
t, err := time.Parse("02-01-2006", dateStr)
|
||||
if err != nil {
|
||||
return time.Time{}, err
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
Reference in New Issue
Block a user