167 lines
4.5 KiB
Go
167 lines
4.5 KiB
Go
// Updated admin_post.go with better image handling
|
|
|
|
package handlers
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/patel-mann/poll-system/app/internal/models"
|
|
"github.com/patel-mann/poll-system/app/internal/utils"
|
|
)
|
|
|
|
func PostsHandler(w http.ResponseWriter, r *http.Request) {
|
|
userID := r.Context().Value("user_id").(int)
|
|
role := r.Context().Value("user_role").(int)
|
|
username,_ := models.GetCurrentUserName(r)
|
|
|
|
|
|
if r.Method == http.MethodPost {
|
|
// Parse multipart form
|
|
err := r.ParseMultipartForm(10 << 20) // 10MB max
|
|
if err != nil {
|
|
fmt.Printf("Error parsing form: %v\n", err)
|
|
http.Error(w, "Invalid form", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
content := r.FormValue("content")
|
|
if strings.TrimSpace(content) == "" {
|
|
http.Error(w, "Content cannot be empty", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
var imagePath string
|
|
file, handler, err := r.FormFile("image")
|
|
if err == nil && file != nil {
|
|
defer file.Close()
|
|
|
|
// Validate file type
|
|
allowedTypes := map[string]bool{
|
|
".jpg": true,
|
|
".jpeg": true,
|
|
".png": true,
|
|
".gif": true,
|
|
".webp": true,
|
|
}
|
|
|
|
ext := strings.ToLower(filepath.Ext(handler.Filename))
|
|
if !allowedTypes[ext] {
|
|
http.Error(w, "Invalid file type. Only images allowed.", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
// Ensure uploads folder exists
|
|
uploadDir := "uploads"
|
|
if err := os.MkdirAll(uploadDir, 0755); err != nil {
|
|
fmt.Printf("Error creating upload directory: %v\n", err)
|
|
http.Error(w, "Unable to create upload directory", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// Create unique filename
|
|
filename := fmt.Sprintf("%d_%d%s", userID, time.Now().UnixNano(), ext)
|
|
savePath := filepath.Join(uploadDir, filename)
|
|
|
|
out, err := os.Create(savePath)
|
|
if err != nil {
|
|
fmt.Printf("Error creating file: %v\n", err)
|
|
http.Error(w, "Unable to save file", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer out.Close()
|
|
|
|
_, err = io.Copy(out, file)
|
|
if err != nil {
|
|
fmt.Printf("Error copying file: %v\n", err)
|
|
http.Error(w, "Failed to save file", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
// Save path relative to the static route
|
|
imagePath = "/uploads/" + filename
|
|
fmt.Printf("Image saved at: %s\n", imagePath)
|
|
} else if err != http.ErrMissingFile {
|
|
fmt.Printf("Error getting file: %v\n", err)
|
|
}
|
|
|
|
// Insert post
|
|
_, err = models.DB.Exec(`INSERT INTO post (author_id, content, image_url) VALUES ($1, $2, $3)`,
|
|
userID, content, imagePath)
|
|
if err != nil {
|
|
fmt.Printf("Database error: %v\n", err)
|
|
http.Error(w, "Failed to create post", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
fmt.Printf("Post created successfully with image: %s\n", imagePath)
|
|
http.Redirect(w, r, "/posts", http.StatusSeeOther)
|
|
return
|
|
}
|
|
|
|
CurrentUserID := models.GetCurrentUserID(w, r)
|
|
|
|
|
|
// GET request: fetch posts
|
|
rows, err := models.DB.Query(`
|
|
SELECT p.post_id, p.author_id, u.first_name || ' ' || u.last_name AS author_name,
|
|
p.content, COALESCE(p.image_url, '') as image_url, p.created_at
|
|
FROM post p
|
|
JOIN users u ON p.author_id = u.user_id
|
|
WHERE p.author_id = $1
|
|
ORDER BY p.created_at DESC
|
|
`, CurrentUserID)
|
|
if err != nil {
|
|
fmt.Printf("Database query error: %v\n", err)
|
|
http.Error(w, "Failed to fetch posts", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
defer rows.Close()
|
|
|
|
var posts []models.Post
|
|
for rows.Next() {
|
|
var p models.Post
|
|
err := rows.Scan(&p.PostID, &p.AuthorID, &p.AuthorName, &p.Content, &p.ImageURL, &p.CreatedAt)
|
|
if err != nil {
|
|
fmt.Printf("Row scan error: %v\n", err)
|
|
continue
|
|
}
|
|
posts = append(posts, p)
|
|
}
|
|
|
|
// Add cache busting parameter to image URLs
|
|
for i := range posts {
|
|
if posts[i].ImageURL != "" {
|
|
posts[i].ImageURL += "?t=" + strconv.FormatInt(time.Now().UnixNano(), 10)
|
|
fmt.Printf("Post %d image URL: %s\n", posts[i].PostID, posts[i].ImageURL)
|
|
}
|
|
}
|
|
|
|
// Get navigation flags
|
|
showAdminNav, showVolunteerNav := getNavFlags(role)
|
|
|
|
fmt.Printf("Rendering %d posts\n", len(posts))
|
|
|
|
utils.Render(w, "posts.html", map[string]interface{}{
|
|
"Title": "Posts",
|
|
"IsAuthenticated": true,
|
|
"ShowAdminNav": showAdminNav,
|
|
"ShowVolunteerNav": showVolunteerNav,
|
|
"UserName": username,
|
|
"Posts": posts,
|
|
"ActiveSection": "posts",
|
|
})
|
|
}
|
|
|
|
// Helper function (add this to your main.go if not already there)
|
|
func getNavFlags(role int) (bool, bool) {
|
|
showAdminNav := role == 1 // Admin role
|
|
showVolunteerNav := role == 3 || role == 2
|
|
return showAdminNav, showVolunteerNav
|
|
} |