refactor: restructure in entirety
This commit is contained in:
@@ -1,12 +1,11 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"billit/internal/handler"
|
||||
"billit/internal/logic"
|
||||
"billit/internal/view"
|
||||
"net/http"
|
||||
|
||||
"billit/internal/api"
|
||||
"billit/internal/auth"
|
||||
"billit/internal/web"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/labstack/echo/v4/middleware"
|
||||
)
|
||||
@@ -25,23 +24,24 @@ func (s *Server) RegisterRoutes() http.Handler {
|
||||
}))
|
||||
|
||||
// Static files
|
||||
fileServer := http.FileServer(http.FS(web.Files))
|
||||
e.GET("/assets/*", echo.WrapHandler(fileServer))
|
||||
if s.assetsFS != nil {
|
||||
fileServer := http.FileServer(http.FS(s.assetsFS))
|
||||
e.GET("/assets/*", echo.WrapHandler(fileServer))
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// Auth Setup
|
||||
// ========================================
|
||||
userStore := auth.NewDBUserStore(s.db)
|
||||
authService := auth.NewService(userStore)
|
||||
authHandlers := web.NewAuthHandlers(authService)
|
||||
authService := logic.NewAuthService(s.db)
|
||||
authHandlers := handler.NewAuthHandlers(authService)
|
||||
|
||||
// ========================================
|
||||
// API Routes (JSON responses) - Health only, products/invoice via web UI
|
||||
// API Routes (JSON responses) - Health only
|
||||
// ========================================
|
||||
apiHandlers := api.NewHandlers(s.db)
|
||||
healthHandlers := handler.NewHealthHandlers(s.db)
|
||||
apiGroup := e.Group("/api")
|
||||
{
|
||||
apiGroup.GET("/health", apiHandlers.HealthHandler)
|
||||
apiGroup.GET("/health", healthHandlers.HealthHandler)
|
||||
}
|
||||
|
||||
// ========================================
|
||||
@@ -60,17 +60,17 @@ func (s *Server) RegisterRoutes() http.Handler {
|
||||
protected.Use(authHandlers.AuthMiddleware)
|
||||
|
||||
// Home
|
||||
homeHandlers := web.NewHomeHandlers(s.db)
|
||||
homeHandlers := handler.NewHomeHandlers(s.db)
|
||||
protected.GET("/home", homeHandlers.HomePageHandler)
|
||||
|
||||
// Account routes
|
||||
accountHandlers := web.NewAccountHandlers(s.db, authService)
|
||||
accountHandlers := handler.NewAccountHandlers(s.db, authService)
|
||||
protected.GET("/account", accountHandlers.AccountPageHandler)
|
||||
protected.POST("/account/details", accountHandlers.UpdateDetailsHandler)
|
||||
protected.POST("/account/password", accountHandlers.ChangePasswordHandler)
|
||||
|
||||
// Buyer routes
|
||||
buyerHandlers := web.NewBuyerHandlers(s.db)
|
||||
buyerHandlers := handler.NewBuyerHandlers(s.db)
|
||||
protected.GET("/buyer", buyerHandlers.BuyerListHandler)
|
||||
protected.GET("/buyer/create", buyerHandlers.BuyerCreatePageHandler)
|
||||
protected.POST("/buyer/create", buyerHandlers.BuyerCreateHandler)
|
||||
@@ -79,11 +79,15 @@ func (s *Server) RegisterRoutes() http.Handler {
|
||||
protected.DELETE("/buyer/:id", buyerHandlers.BuyerDeleteHandler)
|
||||
|
||||
// Invoices list
|
||||
invoicesHandlers := web.NewInvoicesHandlers(s.db)
|
||||
invoicesHandlers := handler.NewInvoicesHandlers(s.db)
|
||||
protected.GET("/invoice", invoicesHandlers.InvoicesListHandler)
|
||||
|
||||
// Modal routes
|
||||
modalHandlers := handler.NewModalHandlers()
|
||||
protected.GET("/modal/confirm", modalHandlers.ConfirmHandler)
|
||||
|
||||
// Product routes (web UI)
|
||||
productHandlers := web.NewProductHandlers(s.db)
|
||||
productHandlers := handler.NewProductHandlers(s.db)
|
||||
protected.GET("/product", productHandlers.ProductListHandler)
|
||||
protected.GET("/product/create", productHandlers.ProductCreatePageHandler)
|
||||
protected.POST("/product/create", productHandlers.ProductCreateHandler)
|
||||
@@ -92,7 +96,7 @@ func (s *Server) RegisterRoutes() http.Handler {
|
||||
protected.DELETE("/product/:sku", productHandlers.ProductDeleteHandler)
|
||||
|
||||
// Billing routes (web UI)
|
||||
billingHandlers := web.NewBillingHandlers(s.db)
|
||||
billingHandlers := handler.NewBillingHandlers(s.db)
|
||||
protected.GET("/billing", billingHandlers.BillingPageHandler)
|
||||
protected.POST("/billing/calculate", billingHandlers.CalculateBillHandler)
|
||||
protected.POST("/billing/generate", billingHandlers.GenerateBillHandler)
|
||||
@@ -102,17 +106,17 @@ func (s *Server) RegisterRoutes() http.Handler {
|
||||
protected.GET("/invoice/:id", billingHandlers.ShowInvoiceHandler)
|
||||
|
||||
// Legacy health check (kept for backward compatibility)
|
||||
e.GET("/health", apiHandlers.HealthHandler)
|
||||
e.GET("/health", healthHandlers.HealthHandler)
|
||||
|
||||
// Custom 404 handler for Echo HTTP errors
|
||||
e.HTTPErrorHandler = func(err error, c echo.Context) {
|
||||
if he, ok := err.(*echo.HTTPError); ok {
|
||||
switch he.Code {
|
||||
case http.StatusNotFound:
|
||||
_ = web.RenderNotFound(c, "")
|
||||
_ = view.RenderNotFound(c, "")
|
||||
return
|
||||
case http.StatusInternalServerError:
|
||||
_ = web.RenderServerError(c, "")
|
||||
_ = view.RenderServerError(c, "")
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -122,8 +126,8 @@ func (s *Server) RegisterRoutes() http.Handler {
|
||||
|
||||
// Catch-all for undefined routes (must be last)
|
||||
e.RouteNotFound("/*", func(c echo.Context) error {
|
||||
return web.RenderNotFound(c, "")
|
||||
return view.RenderNotFound(c, "")
|
||||
})
|
||||
|
||||
return e
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
|
||||
"billit/internal/database"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func TestHomeRoute(t *testing.T) {
|
||||
// Create a minimal server with db for testing
|
||||
db := database.New()
|
||||
s := &Server{db: db}
|
||||
handler := s.RegisterRoutes()
|
||||
|
||||
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
handler.ServeHTTP(resp, req)
|
||||
|
||||
if resp.Code != http.StatusOK {
|
||||
t.Errorf("home route wrong status code = %v, want %v", resp.Code, http.StatusOK)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRouterSetup(t *testing.T) {
|
||||
// Test that Echo router can be set up without panic
|
||||
e := echo.New()
|
||||
if e == nil {
|
||||
t.Error("failed to create echo instance")
|
||||
}
|
||||
}
|
||||
@@ -10,20 +10,22 @@ import (
|
||||
_ "github.com/joho/godotenv/autoload"
|
||||
|
||||
"billit/internal/database"
|
||||
"io/fs"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
port int
|
||||
|
||||
db database.Service
|
||||
db database.Service
|
||||
assetsFS fs.FS
|
||||
}
|
||||
|
||||
func NewServer() *http.Server {
|
||||
func NewServer(assetsFS fs.FS) *http.Server {
|
||||
port, _ := strconv.Atoi(os.Getenv("PORT"))
|
||||
NewServer := &Server{
|
||||
port: port,
|
||||
|
||||
db: database.New(),
|
||||
port: port,
|
||||
db: database.New(),
|
||||
assetsFS: assetsFS,
|
||||
}
|
||||
|
||||
// Declare Server config
|
||||
|
||||
Reference in New Issue
Block a user