diff --git a/database/schema/schema.sql b/database/schema/schema.sql index e0c445b..8789292 100644 --- a/database/schema/schema.sql +++ b/database/schema/schema.sql @@ -32,6 +32,7 @@ CREATE TABLE IF NOT EXISTS users ( theme VARCHAR(50) DEFAULT 'tokyo-night', max_devices INTEGER DEFAULT 10, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), + timezone VARCHAR(50) DEFAULT 'UTC', updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); @@ -47,7 +48,8 @@ CREATE TABLE IF NOT EXISTS system_settings ( -- Insert default system settings INSERT INTO system_settings (setting_key, setting_value, description) VALUES ('scan_poll_interval_seconds', '60', 'How often to scan all libraries in minutes'), -('auto_scan_enabled', 'true', 'Whether auto-scanning is enabled system-wide') +('auto_scan_enabled', 'true', 'Whether auto-scanning is enabled system-wide'), +('default_timezone', 'UTC', 'System default timezone') ON CONFLICT (setting_key) DO NOTHING; -- Create refresh_tokens table @@ -457,6 +459,7 @@ CREATE TABLE IF NOT EXISTS reading_history ( -- Create indexes for better query performance CREATE INDEX IF NOT EXISTS idx_users_email ON users(email); CREATE INDEX IF NOT EXISTS idx_users_username ON users(username); +CREATE INDEX IF NOT EXISTS idx_users_timezone ON users(timezone); CREATE INDEX IF NOT EXISTS idx_library_types_name ON library_types(name); CREATE INDEX IF NOT EXISTS idx_refresh_tokens_token ON refresh_tokens(token); CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_id ON refresh_tokens(user_id); diff --git a/internal/database/models.go b/internal/database/models.go index b20110a..3fb239b 100644 --- a/internal/database/models.go +++ b/internal/database/models.go @@ -507,5 +507,6 @@ type Users struct { Theme pgtype.Text `db:"theme" json:"theme"` MaxDevices pgtype.Int4 `db:"max_devices" json:"max_devices"` CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"` + Timezone pgtype.Text `db:"timezone" json:"timezone"` UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"` } diff --git a/internal/database/querier.go b/internal/database/querier.go index e902dd1..0b41efd 100644 --- a/internal/database/querier.go +++ b/internal/database/querier.go @@ -247,6 +247,7 @@ type Querier interface { GetSystemConfig(ctx context.Context, key string) (SystemConfig, error) // System Settings queries GetSystemSetting(ctx context.Context, settingKey string) (string, error) + GetSystemTimezone(ctx context.Context) (string, error) // Get universal progress for a book GetUniversalProgress(ctx context.Context, arg GetUniversalProgressParams) (GetUniversalProgressRow, error) // Get unlinked book by ContentId @@ -373,6 +374,7 @@ type Querier interface { UpdateUserProfile(ctx context.Context, arg UpdateUserProfileParams) error UpdateUserRole(ctx context.Context, arg UpdateUserRoleParams) (UpdateUserRoleRow, error) UpdateUserTheme(ctx context.Context, arg UpdateUserThemeParams) error + UpdateUserTimezone(ctx context.Context, arg UpdateUserTimezoneParams) error UpdateUsername(ctx context.Context, arg UpdateUsernameParams) error UpsertDashboardPreferences(ctx context.Context, arg UpsertDashboardPreferencesParams) (UserDashboardPreferences, error) UpsertPanelData(ctx context.Context, arg UpsertPanelDataParams) (PanelData, error) diff --git a/internal/database/queries.sql.go b/internal/database/queries.sql.go index 5274924..19ab276 100644 --- a/internal/database/queries.sql.go +++ b/internal/database/queries.sql.go @@ -5408,6 +5408,17 @@ func (q *Queries) GetSystemSetting(ctx context.Context, settingKey string) (stri return setting_value, err } +const GetSystemTimezone = `-- name: GetSystemTimezone :one +SELECT setting_value FROM system_settings WHERE setting_key = 'default_timezone' +` + +func (q *Queries) GetSystemTimezone(ctx context.Context) (string, error) { + row := q.db.QueryRow(ctx, GetSystemTimezone) + var setting_value string + err := row.Scan(&setting_value) + return setting_value, err +} + const GetUniversalProgress = `-- name: GetUniversalProgress :one SELECT rp.id, @@ -10256,7 +10267,7 @@ func (q *Queries) UpdateUniversalProgress(ctx context.Context, arg UpdateUnivers const UpdateUserMaxDevices = `-- name: UpdateUserMaxDevices :one UPDATE users SET max_devices = $2, updated_at = NOW() WHERE id = $1 -RETURNING id, email, username, password_hash, first_name, last_name, role, theme, max_devices, created_at, updated_at +RETURNING id, email, username, password_hash, first_name, last_name, role, theme, max_devices, created_at, timezone, updated_at ` type UpdateUserMaxDevicesParams struct { @@ -10278,6 +10289,7 @@ func (q *Queries) UpdateUserMaxDevices(ctx context.Context, arg UpdateUserMaxDev &i.Theme, &i.MaxDevices, &i.CreatedAt, + &i.Timezone, &i.UpdatedAt, ) return i, err @@ -10341,6 +10353,20 @@ func (q *Queries) UpdateUserTheme(ctx context.Context, arg UpdateUserThemeParams return err } +const UpdateUserTimezone = `-- name: UpdateUserTimezone :exec +UPDATE users SET timezone = $2, updated_at = NOW() WHERE id = $1 +` + +type UpdateUserTimezoneParams struct { + ID pgtype.UUID `db:"id" json:"id"` + Timezone pgtype.Text `db:"timezone" json:"timezone"` +} + +func (q *Queries) UpdateUserTimezone(ctx context.Context, arg UpdateUserTimezoneParams) error { + _, err := q.db.Exec(ctx, UpdateUserTimezone, arg.ID, arg.Timezone) + return err +} + const UpdateUsername = `-- name: UpdateUsername :exec UPDATE users SET username = $2, updated_at = NOW() WHERE id = $1 ` diff --git a/internal/database/queries/queries.sql b/internal/database/queries/queries.sql index f1b8131..202a8cb 100644 --- a/internal/database/queries/queries.sql +++ b/internal/database/queries/queries.sql @@ -300,6 +300,12 @@ RETURNING *; UPDATE users SET role = $2, updated_at = NOW() WHERE id = $1 RETURNING id, email, username, role; +-- name: UpdateUserTimezone :exec +UPDATE users SET timezone = $2, updated_at = NOW() WHERE id = $1; + +-- name: GetSystemTimezone :one +SELECT setting_value FROM system_settings WHERE setting_key = 'default_timezone'; + -- name: CountUserDevices :one SELECT COUNT(*) FROM devices WHERE user_id = $1;