Compare commits
1 Commits
auth
...
developmen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56b851aba6 |
329
cmd/server/main.go
Normal file
329
cmd/server/main.go
Normal file
@@ -0,0 +1,329 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"log"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type Product struct {
|
||||
ID int `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Price float64 `json:"price"`
|
||||
}
|
||||
|
||||
var (
|
||||
products []Product
|
||||
mu sync.Mutex // Для безопасного доступа к списку продуктов
|
||||
nextID int = 1 // Для автоматической генерации ID
|
||||
)
|
||||
|
||||
// Структура для передачи данных в шаблон
|
||||
type PageData struct {
|
||||
Products []Product
|
||||
Cart []CartItem
|
||||
}
|
||||
|
||||
type CartItem struct {
|
||||
ProductID int `json:"product_id"`
|
||||
UserID int `json:"user_id"`
|
||||
Quantity int `json:"quantity"`
|
||||
CreatedID int `json:"created_id"`
|
||||
}
|
||||
|
||||
// Получение корзины из cookies
|
||||
func GetCartFromCookie(r *http.Request) ([]CartItem, error) {
|
||||
// Read the cookie
|
||||
cookie, err := r.Cookie("cart")
|
||||
if err != nil {
|
||||
if err == http.ErrNoCookie {
|
||||
// If no cookie, return an empty cart
|
||||
return []CartItem{}, nil
|
||||
}
|
||||
return nil, fmt.Errorf("failed to read cart cookie: %w", err)
|
||||
}
|
||||
|
||||
// Check if the cookie value looks like JSON
|
||||
var cart []CartItem
|
||||
err = json.Unmarshal([]byte(cookie.Value), &cart)
|
||||
if err != nil {
|
||||
log.Println("Invalid cart cookie value, resetting cart.")
|
||||
return []CartItem{}, nil // Reset to an empty cart on error
|
||||
}
|
||||
|
||||
return cart, nil
|
||||
}
|
||||
|
||||
// Сохранение корзины в cookies
|
||||
func SetCartCookie(w http.ResponseWriter, cart []CartItem) error {
|
||||
cartJSON, err := json.Marshal(cart)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to serialize cart: %w", err)
|
||||
}
|
||||
|
||||
// Устанавливаем cookie с корзиной
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: "cart",
|
||||
Value: string(cartJSON),
|
||||
Path: "/",
|
||||
})
|
||||
return nil
|
||||
}
|
||||
func renderTemplate(w http.ResponseWriter, r *http.Request, cart []CartItem) {
|
||||
tmpl, err := template.New("index").Parse(`
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Products</title>
|
||||
<style>
|
||||
body { font-family: Arial, sans-serif; }
|
||||
table { width: 50%; border-collapse: collapse; margin: 20px 0; }
|
||||
th, td { padding: 8px 12px; text-align: left; border: 1px solid #ddd; }
|
||||
h1 { text-align: center; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Products</h1>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Product ID</th>
|
||||
<th>Name</th>
|
||||
<th>Price</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
{{range .Products}}
|
||||
<tr>
|
||||
<td>{{.ID}}</td>
|
||||
<td>{{.Name}}</td>
|
||||
<td>{{.Price}}</td>
|
||||
<td>
|
||||
<a href="/edit/{{.ID}}">Edit</a> |
|
||||
<a href="/delete/{{.ID}}">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
|
||||
<h2>Add a New Product</h2>
|
||||
<form action="/add" method="POST">
|
||||
<label for="name">Product Name:</label>
|
||||
<input type="text" name="name" required><br><br>
|
||||
|
||||
<label for="price">Price:</label>
|
||||
<input type="number" step="0.01" name="price" required><br><br>
|
||||
|
||||
<button type="submit">Add Product</button>
|
||||
</form>
|
||||
|
||||
<h2>Cart</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Product ID</th>
|
||||
<th>Quantity</th>
|
||||
</tr>
|
||||
{{range .Cart}}
|
||||
<tr>
|
||||
<td>{{.ProductID}}</td>
|
||||
<td>{{.Quantity}}</td>
|
||||
</tr>
|
||||
{{end}}
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
`)
|
||||
if err != nil {
|
||||
log.Println("Error parsing template:", err)
|
||||
http.Error(w, "Error parsing template", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Передаем данные продукта и корзины в шаблон
|
||||
data := PageData{
|
||||
Products: products,
|
||||
Cart: cart,
|
||||
}
|
||||
|
||||
err = tmpl.Execute(w, data)
|
||||
if err != nil {
|
||||
log.Println("Error executing template:", err)
|
||||
http.Error(w, "Error executing template", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func AddProduct(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method == http.MethodPost {
|
||||
// Получаем данные из формы
|
||||
name := r.FormValue("name")
|
||||
price := r.FormValue("price")
|
||||
|
||||
// Преобразуем цену в float
|
||||
var priceFloat float64
|
||||
_, err := fmt.Sscanf(price, "%f", &priceFloat)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid price", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Создаем новый продукт
|
||||
mu.Lock()
|
||||
product := Product{
|
||||
ID: nextID,
|
||||
Name: name,
|
||||
Price: priceFloat,
|
||||
}
|
||||
nextID++
|
||||
products = append(products, product)
|
||||
mu.Unlock()
|
||||
|
||||
// Перенаправляем пользователя на главную страницу после добавления продукта
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Получаем корзину из cookies
|
||||
cart, err := GetCartFromCookie(r)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Error reading cart: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Отображаем шаблон с обновленным списком продуктов и корзиной
|
||||
renderTemplate(w, r, cart)
|
||||
}
|
||||
|
||||
func EditProduct(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := r.URL.Path[len("/edit/"):]
|
||||
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid product ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Ищем продукт по ID
|
||||
var product *Product
|
||||
for i := range products {
|
||||
if products[i].ID == id {
|
||||
product = &products[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if product == nil {
|
||||
http.Error(w, "Product not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
if r.Method == http.MethodPost {
|
||||
// Обновляем детали продукта
|
||||
product.Name = r.FormValue("name")
|
||||
price := r.FormValue("price")
|
||||
var priceFloat float64
|
||||
_, err := fmt.Sscanf(price, "%f", &priceFloat)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid price", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
product.Price = priceFloat
|
||||
|
||||
// Перенаправляем на главную страницу
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
return
|
||||
}
|
||||
|
||||
// Получаем корзину из cookies
|
||||
// cart, err := GetCartFromCookie(r)
|
||||
// if err != nil {
|
||||
// http.Error(w, fmt.Sprintf("Error reading cart: %v", err), http.StatusInternalServerError)
|
||||
// return
|
||||
// }
|
||||
|
||||
// Отображаем форму редактирования продукта
|
||||
tmpl := `<html><body>
|
||||
<h1>Edit Product</h1>
|
||||
<form action="/edit/{{.ID}}" method="POST">
|
||||
<label for="name">Product Name:</label>
|
||||
<input type="text" name="name" value="{{.Name}}" required><br><br>
|
||||
|
||||
<label for="price">Price:</label>
|
||||
<input type="text" name="price" value="{{.Price}}" required><br><br>
|
||||
|
||||
<button type="submit">Save Changes</button>
|
||||
</form>
|
||||
</body></html>`
|
||||
|
||||
tmplParsed, err := template.New("edit").Parse(tmpl)
|
||||
if err != nil {
|
||||
http.Error(w, "Error parsing template", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Передаем данные продукта в шаблон
|
||||
tmplParsed.Execute(w, product)
|
||||
}
|
||||
|
||||
func DeleteProduct(w http.ResponseWriter, r *http.Request) {
|
||||
idStr := r.URL.Path[len("/delete/"):]
|
||||
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err != nil {
|
||||
http.Error(w, "Invalid product ID", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// Находим индекс продукта для удаления
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
for i, product := range products {
|
||||
if product.ID == id {
|
||||
// Удаляем продукт из списка
|
||||
products = append(products[:i], products[i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// Получаем корзину из cookies
|
||||
cart, err := GetCartFromCookie(r)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Error reading cart: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Сохраняем обновленную корзину в cookies (если необходимо)
|
||||
err = SetCartCookie(w, cart)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Error setting cart cookie: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Перенаправляем на главную страницу
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
}
|
||||
|
||||
func main() {
|
||||
// Обработчики маршрутов
|
||||
http.HandleFunc("/add", AddProduct)
|
||||
http.HandleFunc("/edit/", EditProduct)
|
||||
http.HandleFunc("/delete/", DeleteProduct)
|
||||
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
|
||||
// Получаем корзину из cookies
|
||||
cart, err := GetCartFromCookie(r)
|
||||
if err != nil {
|
||||
http.Error(w, fmt.Sprintf("Error reading cart: %v", err), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Отображаем шаблон с корзиной
|
||||
renderTemplate(w, r, cart)
|
||||
})
|
||||
|
||||
log.Println("Server is running on http://localhost:8080")
|
||||
log.Fatal(http.ListenAndServe(":8080", nil))
|
||||
}
|
||||
Reference in New Issue
Block a user