132 lines
3.7 KiB
Go
132 lines
3.7 KiB
Go
package handler
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strconv"
|
|
|
|
"awesome_cli/internal/service"
|
|
"awesome_cli/pkg/ui"
|
|
|
|
libErr "code.linberg.su/linberg/awesome-back/pkg/errors"
|
|
)
|
|
|
|
type CoffeeHandler struct {
|
|
coffeeService *service.CoffeeService
|
|
}
|
|
|
|
func NewCoffeeHandler(coffeeService *service.CoffeeService) *CoffeeHandler {
|
|
return &CoffeeHandler{
|
|
coffeeService: coffeeService,
|
|
}
|
|
}
|
|
|
|
func (h *CoffeeHandler) HandleList() error {
|
|
coffees, err := h.coffeeService.GetAllCoffees()
|
|
if err != nil {
|
|
return h.handleError(err, "Failed to list coffees")
|
|
}
|
|
|
|
h.printCoffeesTable(coffees)
|
|
return nil
|
|
}
|
|
|
|
func (h *CoffeeHandler) HandleGet(coffeeID string) error {
|
|
id, err := strconv.Atoi(coffeeID)
|
|
if err != nil {
|
|
return libErr.NewInvalidError("coffee ID must be a number")
|
|
}
|
|
|
|
coffee, err := h.coffeeService.GetCoffeeByID(id)
|
|
if err != nil {
|
|
return h.handleError(err, fmt.Sprintf("Failed to get coffee with ID %d", id))
|
|
}
|
|
|
|
h.printCoffeeDetail(coffee)
|
|
return nil
|
|
}
|
|
|
|
func (h *CoffeeHandler) HandleGetWithRetry(coffeeID string, maxRetries int) error {
|
|
id, err := strconv.Atoi(coffeeID)
|
|
if err != nil {
|
|
return libErr.NewInvalidError("coffee ID must be a number")
|
|
}
|
|
|
|
fmt.Printf("Fetching coffee with ID %d (max retries: %d)...\n", id, maxRetries)
|
|
|
|
coffee, err := h.coffeeService.GetCoffeeByIDWithRetry(id, maxRetries)
|
|
if err != nil {
|
|
return h.handleError(err, fmt.Sprintf("Failed to get coffee with ID %d after retries", id))
|
|
}
|
|
|
|
h.printCoffeeDetail(coffee)
|
|
return nil
|
|
}
|
|
|
|
func (h *CoffeeHandler) printCoffeesTable(coffees []service.Coffee) {
|
|
t := ui.NewTableBuilder()
|
|
t.AddTableHeader("ID", "Name", "Price", "Size", "Description")
|
|
for _, coffee := range coffees {
|
|
t.AddRow(
|
|
strconv.FormatInt(int64(coffee.ID), 10),
|
|
coffee.Name,
|
|
strconv.FormatInt(int64(coffee.Price), 10),
|
|
coffee.Size,
|
|
coffee.Description,
|
|
)
|
|
}
|
|
|
|
fmt.Println(t.CreateTable())
|
|
}
|
|
|
|
func (h *CoffeeHandler) printCoffeeDetail(coffee *service.Coffee) {
|
|
fmt.Printf("ID: %s\n", ui.SetColor(ui.Green, strconv.FormatInt(int64(coffee.ID), 10)))
|
|
fmt.Printf("Name: %s\n", ui.SetColor(ui.Green, coffee.Name))
|
|
fmt.Printf("Price: %s\n", ui.SetColor(ui.Green, fmt.Sprintf("%.2f ₽", coffee.Price)))
|
|
fmt.Printf("Size: %s\n", ui.SetColor(ui.Green, coffee.Size))
|
|
fmt.Printf("Description: %s\n", ui.SetColor(ui.Green, coffee.Description))
|
|
fmt.Println()
|
|
}
|
|
|
|
// handleError демонстрирует продвинутую обработку ошибок
|
|
func (h *CoffeeHandler) handleError(err error, message string) error {
|
|
red := func(s string) string {
|
|
return ui.SetColor(ui.Red, s)
|
|
}
|
|
|
|
fmt.Printf("%s: %s\n", red("Error"), message)
|
|
|
|
// Демонстрация использования errors.Is и errors.As
|
|
switch {
|
|
case libErr.IsNotFound(err):
|
|
fmt.Printf("%s: Resource not found\n", red("Type"))
|
|
fmt.Printf("%s: %v\n", red("Details"), err)
|
|
|
|
case libErr.IsInvalid(err):
|
|
fmt.Printf("%s: Invalid request\n", red("Type"))
|
|
fmt.Printf("%s: %v\n", red("Details"), err)
|
|
|
|
case libErr.IsNetworkError(err):
|
|
fmt.Printf("%s: Network error\n", red("Type"))
|
|
fmt.Printf("%s: Please check your connection and try again\n", red("Details"))
|
|
|
|
default:
|
|
// Используем errors.As для получения дополнительной информации
|
|
var appErr *libErr.AppError
|
|
if errors.As(err, &appErr) {
|
|
fmt.Printf("%s: %s\n", red("Type"), string(appErr.Type))
|
|
fmt.Printf("%s: %s\n", red("Message"), appErr.Message)
|
|
|
|
// Демонстрация unwrap цепочки ошибок
|
|
if appErr.Err != nil {
|
|
fmt.Printf("%s: %v\n", red("Underlying error"), appErr.Err)
|
|
}
|
|
} else {
|
|
fmt.Printf("%s: %v\n", red("Unknown error"), err)
|
|
}
|
|
}
|
|
|
|
fmt.Println() // Пустая строка для читабельности
|
|
return err
|
|
}
|