change to gorilla
This commit is contained in:
parent
54970ae013
commit
f0c7fc472a
9 changed files with 632 additions and 162 deletions
61
cmd/main.go
61
cmd/main.go
|
|
@ -3,9 +3,10 @@ package main
|
|||
import (
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
"go_selva/internal/api"
|
||||
"go_selva/internal/db"
|
||||
|
|
@ -19,44 +20,48 @@ func main() {
|
|||
}
|
||||
defer database.Close()
|
||||
|
||||
// Initialize Gin router
|
||||
router := gin.Default()
|
||||
// Initialize Gorilla Mux router
|
||||
router := mux.NewRouter()
|
||||
|
||||
// Register the safeHTML function
|
||||
router.SetFuncMap(template.FuncMap{
|
||||
// Create a template registry and register the safeHTML function
|
||||
funcMap := template.FuncMap{
|
||||
"safeHTML": func(s string) template.HTML {
|
||||
return template.HTML(s)
|
||||
},
|
||||
})
|
||||
}
|
||||
tmpl := template.New("").Funcs(funcMap)
|
||||
|
||||
// Load HTML templates
|
||||
router.LoadHTMLGlob("templates/*")
|
||||
|
||||
// Serve static files (CSS)
|
||||
router.Static("/static", "./static")
|
||||
|
||||
// Initialize API handlers
|
||||
apiHandler := api.NewAPIHandler(database)
|
||||
|
||||
// Define API routes
|
||||
apiGroup := router.Group("/nombres")
|
||||
{
|
||||
apiGroup.GET("/search", apiHandler.SearchNombres)
|
||||
apiGroup.POST("", apiHandler.CreateNombre)
|
||||
apiGroup.GET("", apiHandler.GetNombres)
|
||||
apiGroup.GET("/:id", apiHandler.GetNombreByID)
|
||||
apiGroup.PUT("/:id", apiHandler.UpdateNombre)
|
||||
apiGroup.DELETE("/:id", apiHandler.DeleteNombre)
|
||||
apiGroup.GET("/html/edit/:id", apiHandler.EditNombreHTML)
|
||||
apiGroup.POST("/html/update/:id", apiHandler.UpdateNombreHTML)
|
||||
tmpl, err = tmpl.ParseGlob("templates/*")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to load HTML templates: %v", err)
|
||||
}
|
||||
|
||||
// Serve static files (CSS)
|
||||
router.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServer(http.Dir("./static"))))
|
||||
|
||||
// Initialize API handlers
|
||||
apiHandler := api.NewAPIHandler(database, tmpl) // Pass the loaded templates
|
||||
|
||||
// Define API routes
|
||||
apiGroup := router.PathPrefix("/nombres").Subrouter()
|
||||
apiGroup.HandleFunc("/search", apiHandler.SearchNombres).Methods("GET")
|
||||
apiGroup.HandleFunc("", apiHandler.CreateNombre).Methods("POST")
|
||||
apiGroup.HandleFunc("", apiHandler.GetNombres).Methods("GET")
|
||||
apiGroup.HandleFunc("/{id}", apiHandler.GetNombreByID).Methods("GET")
|
||||
apiGroup.HandleFunc("/{id}", apiHandler.UpdateNombre).Methods("PUT")
|
||||
apiGroup.HandleFunc("/{id}", apiHandler.DeleteNombre).Methods("DELETE")
|
||||
apiGroup.HandleFunc("/html/edit/{id}", apiHandler.EditNombreHTML).Methods("GET")
|
||||
apiGroup.HandleFunc("/html/update/{id}", apiHandler.UpdateNombreHTML).Methods("POST")
|
||||
|
||||
// HTML Routes
|
||||
apiGroup.GET("/html", apiHandler.GetNombresHTML)
|
||||
apiGroup.GET("/html/:id", apiHandler.GetNombreByIDHTML)
|
||||
router.HandleFunc("/", apiHandler.GetIndexPlantsHTML).Methods("GET")
|
||||
router.HandleFunc("/nombres/html", apiHandler.GetNombresHTML).Methods("GET")
|
||||
router.HandleFunc("/nombres/html/{id}", apiHandler.GetNombreByIDHTML).Methods("GET")
|
||||
|
||||
// Start the server
|
||||
if err := router.Run(":8080"); err != nil {
|
||||
log.Println("Server started on :8080")
|
||||
if err := http.ListenAndServe(":8080", router); err != nil {
|
||||
log.Fatalf("Failed to start server: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
5
go.mod
5
go.mod
|
|
@ -2,6 +2,8 @@ module go_selva
|
|||
|
||||
go 1.21.1
|
||||
|
||||
require github.com/joho/godotenv v1.5.1
|
||||
|
||||
require (
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/bytedance/sonic v1.11.6 // indirect
|
||||
|
|
@ -16,7 +18,7 @@ require (
|
|||
github.com/go-playground/validator/v10 v10.20.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.9.1 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/joho/godotenv v1.5.1 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
|
|
@ -33,5 +35,4 @@ require (
|
|||
golang.org/x/text v0.15.0 // indirect
|
||||
google.golang.org/protobuf v1.34.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
github.com/joho/godotenv v1.5.1
|
||||
)
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -27,6 +27,8 @@ github.com/go-sql-driver/mysql v1.9.1/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI6
|
|||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
|
||||
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
|
||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
|
|
|
|||
|
|
@ -2,14 +2,16 @@ package api
|
|||
|
||||
import (
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/mux"
|
||||
)
|
||||
|
||||
// Nombre represents the structure of the Nombres table.
|
||||
// Nombre representa la estructura de la tabla Nombres (assuming this is your plant table).
|
||||
type Nombre struct {
|
||||
NombreID int `json:"NombreID"`
|
||||
FamiliaID int `json:"FamiliaID"`
|
||||
|
|
@ -18,44 +20,91 @@ type Nombre struct {
|
|||
ProveedorID int `json:"ProveedorID"`
|
||||
Precio float64 `json:"Precio"`
|
||||
Inactivo bool `json:"Inactivo"`
|
||||
// Add other relevant fields if you want to display them
|
||||
}
|
||||
|
||||
// APIHandler ... (rest of your struct definition)
|
||||
|
||||
// NewAPIHandler ... (rest of your function)
|
||||
|
||||
// GetIndexPlantsHTML recupera the first 20 plants from the Nombres table.
|
||||
// internal/api/api.go
|
||||
|
||||
func (h *APIHandler) GetIndexPlantsHTML(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println("GetIndexPlantsHTML called")
|
||||
|
||||
rows, err := h.DB.Query("SELECT NombreID, FamiliaID, Nombre, Fecha, ProveedorID, Precio, Inactivo FROM Nombres WHERE Inactivo = 0 LIMIT 20")
|
||||
if err != nil {
|
||||
log.Println("Database query error:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
var plants []Nombre
|
||||
for rows.Next() {
|
||||
var plant Nombre
|
||||
if err := rows.Scan(&plant.NombreID, &plant.FamiliaID, &plant.Nombre, &plant.Fecha, &plant.ProveedorID, &plant.Precio, &plant.Inactivo); err != nil {
|
||||
log.Println("Row scan error:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
plants = append(plants, plant)
|
||||
}
|
||||
|
||||
log.Println("Retrieved plants:", plants)
|
||||
|
||||
if err := h.template.ExecuteTemplate(w, "index.html", plants); err != nil {
|
||||
log.Println("Template execution error:", err)
|
||||
http.Error(w, "Failed to render HTML", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
log.Println("index.html rendered")
|
||||
}
|
||||
|
||||
// APIHandler maneja las operaciones de la API para la tabla Nombres.
|
||||
type APIHandler struct {
|
||||
DB *sql.DB
|
||||
template *template.Template // To store loaded HTML templates
|
||||
}
|
||||
|
||||
func NewAPIHandler(db *sql.DB) *APIHandler {
|
||||
return &APIHandler{DB: db}
|
||||
// NewAPIHandler crea una nueva instancia de APIHandler.
|
||||
func NewAPIHandler(db *sql.DB, tmpl *template.Template) *APIHandler {
|
||||
return &APIHandler{DB: db, template: tmpl}
|
||||
}
|
||||
|
||||
func (h *APIHandler) CreateNombre(c *gin.Context) {
|
||||
// CreateNombre crea un nuevo registro en la tabla Nombres.
|
||||
func (h *APIHandler) CreateNombre(w http.ResponseWriter, r *http.Request) {
|
||||
var nombre Nombre
|
||||
if err := c.ShouldBindJSON(&nombre); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
if err := json.NewDecoder(r.Body).Decode(&nombre); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
result, err := h.DB.Exec("INSERT INTO Nombres (FamiliaID, Nombre, Fecha, ProveedorID, Precio, Inactivo) VALUES (?, ?, ?, ?, ?, ?)",
|
||||
nombre.FamiliaID, nombre.Nombre, nombre.Fecha, nombre.ProveedorID, nombre.Precio, nombre.Inactivo)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
id, err := result.LastInsertId()
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
nombre.NombreID = int(id)
|
||||
c.JSON(http.StatusCreated, nombre)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
json.NewEncoder(w).Encode(nombre)
|
||||
}
|
||||
|
||||
func (h *APIHandler) GetNombres(c *gin.Context) {
|
||||
// GetNombres recupera todos los registros de la tabla Nombres.
|
||||
func (h *APIHandler) GetNombres(w http.ResponseWriter, r *http.Request) {
|
||||
rows, err := h.DB.Query("SELECT NombreID, FamiliaID, Nombre, Fecha, ProveedorID, Precio, Inactivo FROM Nombres")
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
|
@ -64,19 +113,27 @@ func (h *APIHandler) GetNombres(c *gin.Context) {
|
|||
for rows.Next() {
|
||||
var nombre Nombre
|
||||
if err := rows.Scan(&nombre.NombreID, &nombre.FamiliaID, &nombre.Nombre, &nombre.Fecha, &nombre.ProveedorID, &nombre.Precio, &nombre.Inactivo); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
nombres = append(nombres, nombre)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, nombres)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(nombres)
|
||||
}
|
||||
|
||||
func (h *APIHandler) GetNombreByID(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
// GetNombreByID recupera un registro de la tabla Nombres por su ID.
|
||||
func (h *APIHandler) GetNombreByID(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
idStr, ok := vars["id"]
|
||||
if !ok {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -85,50 +142,60 @@ func (h *APIHandler) GetNombreByID(c *gin.Context) {
|
|||
&nombre.NombreID, &nombre.FamiliaID, &nombre.Nombre, &nombre.Fecha, &nombre.ProveedorID, &nombre.Precio, &nombre.Inactivo)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Nombre not found"})
|
||||
http.Error(w, "Nombre not found", http.StatusNotFound)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, nombre)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(nombre)
|
||||
}
|
||||
|
||||
func (h *APIHandler) UpdateNombre(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
// UpdateNombre actualiza un registro existente en la tabla Nombres.
|
||||
func (h *APIHandler) UpdateNombre(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
idStr, ok := vars["id"]
|
||||
if !ok {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var nombre Nombre
|
||||
if err := c.ShouldBindJSON(&nombre); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
if err := json.NewDecoder(r.Body).Decode(&nombre); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = h.DB.Exec("UPDATE Nombres SET FamiliaID = ?, Nombre = ?, Fecha = ?, ProveedorID = ?, Precio = ?, Inactivo = ? WHERE NombreID = ?",
|
||||
nombre.FamiliaID, nombre.Nombre, nombre.Fecha, nombre.ProveedorID, nombre.Precio, nombre.Inactivo, id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
nombre.NombreID = id
|
||||
c.JSON(http.StatusOK, nombre)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(nombre)
|
||||
}
|
||||
|
||||
func (h *APIHandler) SearchNombres(c *gin.Context) {
|
||||
nombre := c.Query("nombre")
|
||||
// SearchNombres busca registros en la tabla Nombres por nombre.
|
||||
func (h *APIHandler) SearchNombres(w http.ResponseWriter, r *http.Request) {
|
||||
nombre := r.URL.Query().Get("nombre")
|
||||
if nombre == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Nombre parameter is required"})
|
||||
http.Error(w, "Nombre parameter is required", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
rows, err := h.DB.Query("SELECT NombreID, FamiliaID, Nombre, Fecha, ProveedorID, Precio, Inactivo FROM Nombres WHERE Nombre = ?", nombre)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
|
@ -137,37 +204,47 @@ func (h *APIHandler) SearchNombres(c *gin.Context) {
|
|||
for rows.Next() {
|
||||
var nombre Nombre
|
||||
if err := rows.Scan(&nombre.NombreID, &nombre.FamiliaID, &nombre.Nombre, &nombre.Fecha, &nombre.ProveedorID, &nombre.Precio, &nombre.Inactivo); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
nombres = append(nombres, nombre)
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, nombres)
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(nombres)
|
||||
}
|
||||
|
||||
func (h *APIHandler) DeleteNombre(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
// DeleteNombre elimina un registro de la tabla Nombres por su ID.
|
||||
func (h *APIHandler) DeleteNombre(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
idStr, ok := vars["id"]
|
||||
if !ok {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
_, err = h.DB.Exec("DELETE FROM Nombres WHERE NombreID = ?", id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "Nombre deleted"})
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
json.NewEncoder(w).Encode(map[string]string{"message": "Nombre deleted"})
|
||||
}
|
||||
|
||||
func (h *APIHandler) GetNombresHTML(c *gin.Context) {
|
||||
log.Println("GetNombresHTML called") // Add logging
|
||||
// GetNombresHTML recupera todos los registros de la tabla Nombres y los muestra en una página HTML.
|
||||
func (h *APIHandler) GetNombresHTML(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println("GetNombresHTML called")
|
||||
rows, err := h.DB.Query("SELECT NombreID, FamiliaID, Nombre, Fecha, ProveedorID, Precio, Inactivo FROM Nombres")
|
||||
if err != nil {
|
||||
log.Println("Database query error:", err) // Add logging
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
log.Println("Database query error:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
|
@ -176,94 +253,185 @@ func (h *APIHandler) GetNombresHTML(c *gin.Context) {
|
|||
for rows.Next() {
|
||||
var nombre Nombre
|
||||
if err := rows.Scan(&nombre.NombreID, &nombre.FamiliaID, &nombre.Nombre, &nombre.Fecha, &nombre.ProveedorID, &nombre.Precio, &nombre.Inactivo); err != nil {
|
||||
log.Println("Row scan error:", err) // Add logging
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
log.Println("Row scan error:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
nombres = append(nombres, nombre)
|
||||
}
|
||||
|
||||
log.Println("Retrieved nombres:", nombres) // Add logging
|
||||
c.HTML(http.StatusOK, "nombres.html", nombres)
|
||||
log.Println("nombres.html rendered") //add log
|
||||
log.Println("Retrieved nombres:", nombres)
|
||||
if err := h.template.ExecuteTemplate(w, "nombres.html", nombres); err != nil {
|
||||
log.Println("Template execution error:", err)
|
||||
http.Error(w, "Failed to render HTML", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
log.Println("nombres.html rendered")
|
||||
}
|
||||
|
||||
func (h *APIHandler) GetNombreByIDHTML(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
// GetNombreByIDHTML recupera un registro de la tabla Nombres por su ID, el nombre de su familia,
|
||||
// y el nombre del proveedor, luego los muestra en una página HTML.
|
||||
func (h *APIHandler) GetNombreByIDHTML(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
idStr, ok := vars["id"]
|
||||
if !ok {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var nombreDetalle struct {
|
||||
Nombre Nombre
|
||||
FamiliaName string
|
||||
ProveedorName string
|
||||
}
|
||||
|
||||
// Join nombres, familias, and proveedores tables
|
||||
err = h.DB.QueryRow(`
|
||||
SELECT
|
||||
n.NombreID,
|
||||
n.FamiliaID,
|
||||
n.Nombre,
|
||||
n.Fecha,
|
||||
n.ProveedorID,
|
||||
n.Precio,
|
||||
n.Inactivo,
|
||||
f.Familia,
|
||||
p.Nombre
|
||||
FROM nombres n
|
||||
INNER JOIN familias f ON n.FamiliaID = f.FamiliaID
|
||||
INNER JOIN proveedores p ON n.ProveedorID = p.ProveedorID
|
||||
WHERE n.NombreID = ?
|
||||
`, id).Scan(
|
||||
&nombreDetalle.Nombre.NombreID,
|
||||
&nombreDetalle.Nombre.FamiliaID,
|
||||
&nombreDetalle.Nombre.Nombre,
|
||||
&nombreDetalle.Nombre.Fecha,
|
||||
&nombreDetalle.Nombre.ProveedorID,
|
||||
&nombreDetalle.Nombre.Precio,
|
||||
&nombreDetalle.Nombre.Inactivo,
|
||||
&nombreDetalle.FamiliaName,
|
||||
&nombreDetalle.ProveedorName,
|
||||
)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
http.Error(w, "Nombre not found", http.StatusNotFound)
|
||||
} else {
|
||||
log.Println("Database query error:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.template.ExecuteTemplate(w, "nombre.html", nombreDetalle); err != nil {
|
||||
log.Println("Template execution error:", err)
|
||||
http.Error(w, "Failed to render HTML", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (h *APIHandler) EditNombreHTML(w http.ResponseWriter, r *http.Request) {
|
||||
log.Println("EditNombreHTML called")
|
||||
vars := mux.Vars(r)
|
||||
idStr, ok := vars["id"]
|
||||
log.Printf("Extracted ID string: %s, ok: %v", idStr, ok)
|
||||
if !ok {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
id, err := strconv.Atoi(idStr)
|
||||
log.Printf("Converted ID: %d, error: %v", id, err)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var nombre Nombre
|
||||
err = h.DB.QueryRow("SELECT NombreID, FamiliaID, Nombre, Fecha, ProveedorID, Precio, Inactivo FROM Nombres WHERE NombreID = ?", id).Scan(
|
||||
&nombre.NombreID, &nombre.FamiliaID, &nombre.Nombre, &nombre.Fecha, &nombre.ProveedorID, &nombre.Precio, &nombre.Inactivo)
|
||||
log.Printf("Database query result: %+v, error: %v", nombre, err)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Nombre not found"})
|
||||
http.Error(w, "Nombre not found", http.StatusNotFound)
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
log.Println("Database query error:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "nombre.html", nombre)
|
||||
}
|
||||
log.Printf("Data passed to template: %+v", nombre)
|
||||
|
||||
func (h *APIHandler) EditNombreHTML(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
w.Header().Set("Content-Type", "text/html; charset=utf-8") // Set header BEFORE executing template
|
||||
|
||||
if err := h.template.ExecuteTemplate(w, "edit_nombre.html", nombre); err != nil {
|
||||
log.Println("Template execution error:", err)
|
||||
http.Error(w, "Failed to render HTML", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var nombre Nombre
|
||||
err = h.DB.QueryRow("SELECT NombreID, FamiliaID, Nombre, Fecha, ProveedorID, Precio, Inactivo FROM Nombres WHERE NombreID = ?", id).Scan(
|
||||
&nombre.NombreID, &nombre.FamiliaID, &nombre.Nombre, &nombre.Fecha, &nombre.ProveedorID, &nombre.Precio, &nombre.Inactivo)
|
||||
if err != nil {
|
||||
if err == sql.ErrNoRows {
|
||||
c.JSON(http.StatusNotFound, gin.H{"error": "Nombre not found"})
|
||||
} else {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
log.Println("edit_nombre.html rendered")
|
||||
}
|
||||
|
||||
// UpdateNombreHTML actualiza un registro en la tabla Nombres desde una página HTML.
|
||||
func (h *APIHandler) UpdateNombreHTML(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
idStr, ok := vars["id"]
|
||||
if !ok {
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
c.HTML(http.StatusOK, "edit_nombre.html", nombre)
|
||||
}
|
||||
|
||||
func (h *APIHandler) UpdateNombreHTML(c *gin.Context) {
|
||||
id, err := strconv.Atoi(c.Param("id")) // Declare id and err
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
log.Println("Invalid ID:", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid ID"})
|
||||
http.Error(w, "Invalid ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var nombre Nombre
|
||||
if err := c.ShouldBind(&nombre); err != nil { // Declare err
|
||||
log.Println("Binding error:", err)
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||||
if err := r.ParseForm(); err != nil {
|
||||
log.Println("Form parsing error:", err)
|
||||
http.Error(w, "Failed to parse form", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
nombre := Nombre{
|
||||
NombreID: id,
|
||||
FamiliaID: atoi(r.FormValue("FamiliaID")),
|
||||
Nombre: r.FormValue("Nombre"),
|
||||
Fecha: r.FormValue("Fecha"),
|
||||
ProveedorID: atoi(r.FormValue("ProveedorID")),
|
||||
Precio: atof64(r.FormValue("Precio")),
|
||||
Inactivo: r.FormValue("Inactivo") == "on",
|
||||
}
|
||||
|
||||
log.Println("Updating nombre:", nombre)
|
||||
|
||||
// Handle empty date
|
||||
fecha := nombre.Fecha
|
||||
if fecha == "" {
|
||||
fecha = "0000-00-00" // Or "NULL", if your database allows it
|
||||
fecha = "0000-00-00"
|
||||
}
|
||||
|
||||
_, err = h.DB.Exec("UPDATE Nombres SET FamiliaID = ?, Nombre = ?, Fecha = ?, ProveedorID = ?, Precio = ?, Inactivo = ? WHERE NombreID = ?",
|
||||
nombre.FamiliaID, nombre.Nombre, fecha, nombre.ProveedorID, nombre.Precio, nombre.Inactivo, id) // Use declared id and err
|
||||
nombre.FamiliaID, nombre.Nombre, fecha, nombre.ProveedorID, nombre.Precio, nombre.Inactivo, id)
|
||||
if err != nil {
|
||||
log.Println("Database update error:", err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
log.Println("Nombre updated successfully")
|
||||
|
||||
c.Redirect(http.StatusFound, "/nombres/html/"+strconv.Itoa(id))
|
||||
http.Redirect(w, r, "/nombres/html/"+strconv.Itoa(id), http.StatusFound)
|
||||
}
|
||||
|
||||
func atoi(s string) int {
|
||||
i, _ := strconv.Atoi(s) // Ignore error for simplicity in this context
|
||||
return i
|
||||
}
|
||||
|
||||
func atof64(s string) float64 {
|
||||
f, _ := strconv.ParseFloat(s, 64) // Ignore error for simplicity
|
||||
return f
|
||||
}
|
||||
|
|
|
|||
173
misc/go_selva.sql
Normal file
173
misc/go_selva.sql
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
-- --------------------------------------------------------
|
||||
-- Host: 127.0.0.1
|
||||
-- Server version: 11.7.2-MariaDB - mariadb.org binary distribution
|
||||
-- Server OS: Win64
|
||||
-- HeidiSQL Version: 12.10.0.7000
|
||||
-- --------------------------------------------------------
|
||||
|
||||
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
|
||||
/*!40101 SET NAMES utf8 */;
|
||||
/*!50503 SET NAMES utf8mb4 */;
|
||||
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
|
||||
/*!40103 SET TIME_ZONE='+00:00' */;
|
||||
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
|
||||
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
|
||||
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
|
||||
|
||||
|
||||
-- Dumping database structure for go_selva
|
||||
CREATE DATABASE IF NOT EXISTS `go_selva` /*!40100 DEFAULT CHARACTER SET utf32 COLLATE utf32_unicode_ci */;
|
||||
USE `go_selva`;
|
||||
|
||||
-- Dumping structure for table go_selva.familias
|
||||
CREATE TABLE IF NOT EXISTS `familias` (
|
||||
`FamiliaID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`Familia` varchar(35) NOT NULL,
|
||||
PRIMARY KEY (`FamiliaID`),
|
||||
UNIQUE KEY `Familia` (`Familia`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=112 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
-- Dumping structure for table go_selva.fotos
|
||||
CREATE TABLE IF NOT EXISTS `fotos` (
|
||||
`FotoID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`NombreID` int(11) NOT NULL DEFAULT 0,
|
||||
`Direccion` varchar(75) NOT NULL,
|
||||
`HayVideo` char(1) DEFAULT '0',
|
||||
`Video` varchar(75) DEFAULT '',
|
||||
PRIMARY KEY (`FotoID`),
|
||||
KEY `NombreID` (`NombreID`),
|
||||
CONSTRAINT `Fotos_ibfk_1` FOREIGN KEY (`NombreID`) REFERENCES `nombres` (`NombreID`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1093 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
-- Dumping structure for table go_selva.logs
|
||||
CREATE TABLE IF NOT EXISTS `logs` (
|
||||
`LogID` int(9) NOT NULL AUTO_INCREMENT,
|
||||
`Tiempo` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`UsuarioID` int(4) NOT NULL DEFAULT 0,
|
||||
`Query` text NOT NULL,
|
||||
PRIMARY KEY (`LogID`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=14427 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
-- Dumping structure for table go_selva.logs20191029
|
||||
CREATE TABLE IF NOT EXISTS `logs20191029` (
|
||||
`LogID` int(9) NOT NULL DEFAULT 0,
|
||||
`Tiempo` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
|
||||
`UsuarioID` int(4) NOT NULL DEFAULT 0,
|
||||
`Query` text NOT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
-- Dumping structure for table go_selva.nombres
|
||||
CREATE TABLE IF NOT EXISTS `nombres` (
|
||||
`NombreID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`FamiliaID` int(6) NOT NULL DEFAULT 1,
|
||||
`Nombre` varchar(75) NOT NULL,
|
||||
`Fecha` date NOT NULL DEFAULT '0000-00-00',
|
||||
`ProveedorID` int(4) NOT NULL DEFAULT 1,
|
||||
`Precio` float(10,2) NOT NULL DEFAULT 0.00,
|
||||
`Inactivo` tinyint(1) NOT NULL DEFAULT 0,
|
||||
PRIMARY KEY (`NombreID`),
|
||||
UNIQUE KEY `Nombre` (`Nombre`),
|
||||
KEY `FamiliaID` (`FamiliaID`),
|
||||
KEY `ProveedorID` (`ProveedorID`),
|
||||
CONSTRAINT `Nombres_ibfk_1` FOREIGN KEY (`FamiliaID`) REFERENCES `familias` (`FamiliaID`),
|
||||
CONSTRAINT `Nombres_ibfk_2` FOREIGN KEY (`ProveedorID`) REFERENCES `proveedores` (`ProveedorID`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1140 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
-- Dumping structure for table go_selva.nombresvulgares
|
||||
CREATE TABLE IF NOT EXISTS `nombresvulgares` (
|
||||
`NombreVulgarID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`NombreID` int(11) NOT NULL DEFAULT 0,
|
||||
`NombreVulgar` varchar(50) DEFAULT NULL,
|
||||
PRIMARY KEY (`NombreVulgarID`),
|
||||
KEY `NombreID` (`NombreID`),
|
||||
CONSTRAINT `NombresVulgares_ibfk_1` FOREIGN KEY (`NombreID`) REFERENCES `nombres` (`NombreID`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=2453 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
-- Dumping structure for table go_selva.notas
|
||||
CREATE TABLE IF NOT EXISTS `notas` (
|
||||
`NotaID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`NombreID` int(11) NOT NULL,
|
||||
`Nota` tinytext DEFAULT NULL,
|
||||
PRIMARY KEY (`NotaID`),
|
||||
KEY `NombreID` (`NombreID`),
|
||||
CONSTRAINT `Notas_ibfk_1` FOREIGN KEY (`NombreID`) REFERENCES `nombres` (`NombreID`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6426 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
-- Dumping structure for table go_selva.proveedores
|
||||
CREATE TABLE IF NOT EXISTS `proveedores` (
|
||||
`ProveedorID` int(3) NOT NULL AUTO_INCREMENT,
|
||||
`Nombre` varchar(95) NOT NULL DEFAULT '',
|
||||
`RFC` varchar(15) DEFAULT '',
|
||||
`Direccion` varchar(75) DEFAULT '',
|
||||
`Colonia` varchar(50) DEFAULT '',
|
||||
`Ciudad` varchar(25) DEFAULT '',
|
||||
`Estado` varchar(40) DEFAULT '',
|
||||
`Pais` varchar(25) DEFAULT '',
|
||||
`CP` varchar(20) DEFAULT '',
|
||||
`Tel1` varchar(20) DEFAULT '',
|
||||
`Tel2` varchar(20) DEFAULT '',
|
||||
`URL` varchar(75) DEFAULT NULL,
|
||||
`Desactivado` char(1) NOT NULL DEFAULT 'N',
|
||||
`Observaciones` varchar(150) DEFAULT NULL,
|
||||
`Contacto1Nombre` varchar(75) DEFAULT '',
|
||||
`Contacto1Tel` varchar(20) DEFAULT '',
|
||||
`Contacto1Cel` varchar(20) DEFAULT '',
|
||||
`Contacto1EMail` varchar(75) DEFAULT '',
|
||||
`Contacto2Nombre` varchar(75) DEFAULT '',
|
||||
`Contacto2Tel` varchar(20) DEFAULT '',
|
||||
`Contacto2Cel` varchar(20) DEFAULT '',
|
||||
`Contacto2EMail` varchar(75) DEFAULT '',
|
||||
PRIMARY KEY (`ProveedorID`),
|
||||
UNIQUE KEY `Nombre` (`Nombre`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=58 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
-- Dumping structure for table go_selva.ubicaciones
|
||||
CREATE TABLE IF NOT EXISTS `ubicaciones` (
|
||||
`UbiID` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`NombreID` int(11) NOT NULL,
|
||||
`Ubicacion` varchar(20) NOT NULL,
|
||||
PRIMARY KEY (`UbiID`),
|
||||
KEY `NombreID` (`NombreID`),
|
||||
CONSTRAINT `Ubicaciones_ibfk_1` FOREIGN KEY (`NombreID`) REFERENCES `nombres` (`NombreID`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=1665 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
-- Dumping structure for table go_selva.usuarios
|
||||
CREATE TABLE IF NOT EXISTS `usuarios` (
|
||||
`UID` int(5) NOT NULL AUTO_INCREMENT,
|
||||
`ApellidoPaterno` varchar(25) NOT NULL DEFAULT '',
|
||||
`ApellidoMaterno` varchar(25) DEFAULT '',
|
||||
`Nombres` varchar(30) NOT NULL DEFAULT '',
|
||||
`Login` varchar(25) NOT NULL DEFAULT '',
|
||||
`PWD` varchar(70) NOT NULL DEFAULT '',
|
||||
`Fecha` date NOT NULL DEFAULT '0000-00-00',
|
||||
`Nivel` enum('Admin','Capturista','Almacenista','Consulta','Instalador','Vendedor','PedOrdInv') DEFAULT NULL,
|
||||
`Deshabilitado` char(1) NOT NULL DEFAULT 'N',
|
||||
PRIMARY KEY (`UID`),
|
||||
UNIQUE KEY `Login` (`Login`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_unicode_ci;
|
||||
|
||||
-- Data exporting was unselected.
|
||||
|
||||
/*!40103 SET TIME_ZONE=IFNULL(@OLD_TIME_ZONE, 'system') */;
|
||||
/*!40101 SET SQL_MODE=IFNULL(@OLD_SQL_MODE, '') */;
|
||||
/*!40014 SET FOREIGN_KEY_CHECKS=IFNULL(@OLD_FOREIGN_KEY_CHECKS, 1) */;
|
||||
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
|
||||
/*!40111 SET SQL_NOTES=IFNULL(@OLD_SQL_NOTES, 1) */;
|
||||
|
|
@ -1,22 +1,105 @@
|
|||
body {
|
||||
font-family: sans-serif;
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
margin: 20px;
|
||||
background-color: #f4f4f4;
|
||||
color: #333;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
h1, h2 {
|
||||
color: #007bff;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
background-color: white;
|
||||
border-radius: 8px;
|
||||
overflow: hidden; /* Para que los bordes redondeados funcionen bien */
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
border: 1px solid #e0e0e0;
|
||||
padding: 12px 15px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
background-color: #f0f8ff; /* Un azul muy claro para los encabezados */
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
tr:nth-child(even) {
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
tr:hover {
|
||||
background-color: #f0f0f0; /* Efecto hover para las filas */
|
||||
}
|
||||
|
||||
a.button, button.button {
|
||||
display: inline-block;
|
||||
padding: 10px 15px;
|
||||
background-color: #007bff;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
a.button:hover, button.button:hover {
|
||||
background-color: #0056b3;
|
||||
}
|
||||
|
||||
.button.delete {
|
||||
background-color: #dc3545;
|
||||
}
|
||||
|
||||
.button.delete:hover {
|
||||
background-color: #c82333;
|
||||
}
|
||||
|
||||
form {
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
label {
|
||||
display: block;
|
||||
margin-bottom: 5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
input[type="date"],
|
||||
select {
|
||||
width: calc(100% - 22px); /* Ajuste para el padding y el borde */
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
input[type="checkbox"]{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
@media (max-width: 600px) {
|
||||
table, form {
|
||||
width: 100%;
|
||||
}
|
||||
th, td {
|
||||
padding: 8px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Editar Nombre</title>
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Editar Nombre</h1>
|
||||
|
||||
<form action="/nombres/html/update/{{ .NombreID }}" method="POST">
|
||||
<label for="FamiliaID">FamiliaID:</label>
|
||||
<input type="number" id="FamiliaID" name="FamiliaID" value="{{ .FamiliaID }}"><br><br>
|
||||
|
|
@ -12,10 +25,17 @@
|
|||
<input type="number" id="ProveedorID" name="ProveedorID" value="{{ .ProveedorID }}"><br><br>
|
||||
|
||||
<label for="Precio">Precio:</label>
|
||||
<input type="number" id="Precio" name="Precio" value="{{ .Precio }}"><br><br>
|
||||
<input type="number" step="0.01" id="Precio" name="Precio" value="{{ .Precio }}"><br><br>
|
||||
|
||||
<label for="Inactivo">Inactivo:</label>
|
||||
<input type="checkbox" id="Inactivo" name="Inactivo" {{ if .Inactivo }}checked{{ end }}><br><br>
|
||||
|
||||
<input type="submit" value="Update">
|
||||
<button type="submit">Guardar Cambios</button>
|
||||
</form>
|
||||
|
||||
<form action="/nombres/html/{{ .NombreID }}" method="GET">
|
||||
<button type="submit">Volver al Detalle</button>
|
||||
</form>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
22
templates/index.html
Normal file
22
templates/index.html
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Plant Index</title>
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Our Plants</h1>
|
||||
<ul>
|
||||
{{ range . }}
|
||||
<li>
|
||||
<a href="/nombres/html/{{ .NombreID }}">{{ .Nombre }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -1,53 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<title>Nombre Details</title>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Detalle del Nombre</title>
|
||||
<link rel="stylesheet" href="/static/style.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Nombre Details</h1>
|
||||
<h1>Detalle del Nombre</h1>
|
||||
|
||||
{{ if . }}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Field</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>NombreID</td>
|
||||
<td>{{ .NombreID }}</td>
|
||||
<th>Nombre:</th>
|
||||
<td>{{ .Nombre.Nombre }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>FamiliaID</td>
|
||||
<td>{{ .FamiliaID }}</td>
|
||||
<th>Familia:</th>
|
||||
<td>{{ .FamiliaName }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Nombre</td>
|
||||
<td>{{ .Nombre | safeHTML }}</td>
|
||||
<th>Fecha:</th>
|
||||
<td>{{ .Nombre.Fecha }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Fecha</td>
|
||||
<td>{{ .Fecha }}</td>
|
||||
<th>Proveedor:</th>
|
||||
<td>{{ .ProveedorName }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>ProveedorID</td>
|
||||
<td>{{ .ProveedorID }}</td>
|
||||
<th>Precio:</th>
|
||||
<td>{{ .Nombre.Precio }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Precio</td>
|
||||
<td>{{ .Precio }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Inactivo</td>
|
||||
<td>{{ .Inactivo }}</td>
|
||||
<th>Inactivo:</th>
|
||||
<td>{{ .Nombre.Inactivo }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<a href="/nombres/html">Back to List</a>
|
||||
<a href="/nombres/html/edit/{{ .NombreID }}">Edit</a>
|
||||
<p><a href="/nombres/html/edit/{{ .Nombre.NombreID }}">Editar</a> | <a href="/nombres/html">Volver</a></p>
|
||||
{{ else }}
|
||||
<p>Nombre no encontrado.</p>
|
||||
{{ end }}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Loading…
Reference in a new issue