Add timezone backend support (handlers, utilities, user context)
- Add FormatInTimezone and FormatTimestamptzInTimezone helpers in templates/utils.go for timezone-aware time display - Add Timezone field to templates.User struct - Pass user timezone from DB to template context in helpers.go - Add timezone update handling in auth.go UpdateProfile with validation via time.LoadLocation - Add UpdateTimezoneSettings handler in system_settings.go for admin system-wide default timezone using UpdateSystemSetting
This commit is contained in:
@@ -87,6 +87,7 @@ type UpdateProfileRequest struct {
|
||||
FirstName string `json:"first_name,omitempty" validate:"omitempty,max=100"`
|
||||
LastName string `json:"last_name,omitempty" validate:"omitempty,max=100"`
|
||||
Theme string `json:"theme,omitempty" validate:"omitempty"`
|
||||
Timezone string `json:"timezone,omitempty" validate:"omitempty"`
|
||||
}
|
||||
|
||||
type AdminUpdateUserRequest struct {
|
||||
@@ -564,6 +565,22 @@ func (h *AuthHandler) UpdateProfile(c *echo.Context) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Update timezone
|
||||
if req.Timezone != "" {
|
||||
if _, err := time.LoadLocation(req.Timezone); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{
|
||||
"error": "Invalid timezone",
|
||||
})
|
||||
}
|
||||
err := h.db.UpdateUserTimezone(ctx, database.UpdateUserTimezoneParams{
|
||||
ID: pgtype.UUID{Bytes: userUUID, Valid: true},
|
||||
Timezone: pgtype.Text{String: req.Timezone, Valid: true},
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Update email (if provided)
|
||||
if req.Email != "" {
|
||||
existingUser, err := h.db.GetUserByEmail(c.Request().Context(), req.Email)
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/pgx/v5"
|
||||
"github.com/labstack/echo/v5"
|
||||
@@ -31,6 +32,28 @@ type ScanSettingsResponse struct {
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
type UpdateTimezoneSettingsRequest struct {
|
||||
DefaultTimezone string `json:"default_timezone" validate:"required"`
|
||||
}
|
||||
|
||||
func (h *SystemSettingsHandler) UpdateTimezoneSettings(c *echo.Context) error {
|
||||
var req UpdateTimezoneSettingsRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid request"})
|
||||
}
|
||||
if _, err := time.LoadLocation(req.DefaultTimezone); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "Invalid timezone"})
|
||||
}
|
||||
err := h.db.UpdateSystemSetting(c.Request().Context(), database.UpdateSystemSettingParams{
|
||||
SettingKey: "default_timezone",
|
||||
SettingValue: req.DefaultTimezone,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return c.JSON(http.StatusOK, map[string]string{"message": "Timezone updated"})
|
||||
}
|
||||
|
||||
func (h *SystemSettingsHandler) UpdateScanSettings(c *echo.Context) error {
|
||||
var req UpdateScanSettingsRequest
|
||||
if err := c.Bind(&req); err != nil {
|
||||
|
||||
@@ -35,6 +35,11 @@ func getTemplateUserWithTheme(c *echo.Context, cfg *Config) (templates.User, err
|
||||
userTheme = userDB.Theme.String
|
||||
}
|
||||
|
||||
userTimezone := "UTC"
|
||||
if userDB.Timezone.Valid {
|
||||
userTimezone = userDB.Timezone.String
|
||||
}
|
||||
|
||||
// Extract JWT token for WebSocket authentication
|
||||
token := ""
|
||||
if cookie, err := c.Cookie("token"); err == nil {
|
||||
@@ -48,6 +53,7 @@ func getTemplateUserWithTheme(c *echo.Context, cfg *Config) (templates.User, err
|
||||
Role: userRole,
|
||||
Theme: userTheme,
|
||||
Token: token,
|
||||
Timezone: userTimezone,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ type User struct {
|
||||
LastName string
|
||||
CreatedAt time.Time
|
||||
Token string
|
||||
Timezone string
|
||||
}
|
||||
|
||||
type PageData struct {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
@@ -197,3 +198,25 @@ func formatAlternateInfo(data []byte) string {
|
||||
|
||||
return strings.Join(parts, " ")
|
||||
}
|
||||
|
||||
// FormatInTimezone formats a time.Time in the specified timezone as MM-DD-YYYY HH:MM
|
||||
func FormatInTimezone(t time.Time, timezone string) string {
|
||||
if t.IsZero() {
|
||||
return ""
|
||||
}
|
||||
|
||||
loc, err := time.LoadLocation(timezone)
|
||||
if err != nil {
|
||||
loc = time.UTC
|
||||
}
|
||||
|
||||
return t.In(loc).Format("01-02-2006 03:04 PM")
|
||||
}
|
||||
|
||||
// FormatTimestamptzInTimezone formats a pgtype.Timestamptz in the specified timezone
|
||||
func FormatTimestamptzInTimezone(t pgtype.Timestamptz, timezone string) string {
|
||||
if !t.Valid {
|
||||
return ""
|
||||
}
|
||||
return FormatInTimezone(t.Time, timezone)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user