Skip to content

refactor: centralize display timezone config#264

Merged
danielhe4rt merged 15 commits into
4.xfrom
feat/centralize-display-timezone
May 20, 2026
Merged

refactor: centralize display timezone config#264
danielhe4rt merged 15 commits into
4.xfrom
feat/centralize-display-timezone

Conversation

@gvieira18
Copy link
Copy Markdown
Member

@gvieira18 gvieira18 commented May 20, 2026

Summary

  • Adds app.display_timezone config key (DISPLAY_TIMEZONE env, default America/Sao_Paulo) to centralize the user-facing timezone
  • Changes app.timezone default from America/Sao_Paulo to UTC
  • Replaces all 15 hardcoded 'America/Sao_Paulo' occurrences across 15 files with config('app.display_timezone')
  • Uses parameterized SQL bindings (?) for AT TIME ZONE clauses instead of string interpolation
  • Adds AT TIME ZONE conversion to moderation heatmap SQL that was missing it entirely
  • Converts all user-facing timestamp displays (SLA deadlines, connection dates, schedule cards) to use the display timezone

Modules affected

  • config/app.php — new config key
  • bot-discord — GreetingsEvent
  • he4rt — heatmap highlight + schedule-card
  • panel-admin — marketing dashboard queries (6 files) + moderation heatmap + appeal views
  • integration-discord — BackfillVoiceLogsCommand CLI output
  • routes/console.php — backup:monitor schedule
  • resources/views — connection-hub

Test plan

  • Rector dry-run — no suggestions
  • Pint — passed
  • PHPStan — 0 errors
  • Tests — 497 passed, 3 skipped
  • Verified AT TIME ZONE ? binding works via tinker
  • Verify heatmaps render correctly in the admin panel
  • Verify SLA deadline times display in Brazil timezone
  • Verify schedule-card shows correct local times

Description

Centralizes the user-facing timezone by adding app.display_timezone (env DISPLAY_TIMEZONE, default America/Sao_Paulo) and switching the application default timezone to UTC. Replaces hard-coded America/Sao_Paulo occurrences with config('app.display_timezone'), parameterizes SQL AT TIME ZONE bindings, fixes a missing AT TIME ZONE in the moderation heatmap, and converts user-facing timestamp displays to the new display timezone.

References

Dependencies & Requirements

  • New config key: app.display_timezone (env: DISPLAY_TIMEZONE, default: America/Sao_Paulo)
  • app.timezone default changed to UTC (env: APP_TIMEZONE)
  • .env.example updated with APP_TIMEZONE=UTC and DISPLAY_TIMEZONE=America/Sao_Paulo
  • No new composer/npm packages added
  • Database must accept parameterized AT TIME ZONE bindings (validated via tinker)
  • Manual verifications pending: admin heatmaps rendering, SLA deadline display, schedule-card local times

Contributor Summary

Contributor Lines Added Lines Removed Files Changed
gvieira18 63 45 15

Changes Summary

File Path Change Description
config/app.php Added display_timezone key; changed default app.timezone to UTC
.env.example Added APP_TIMEZONE and DISPLAY_TIMEZONE entries
app-modules/bot-discord/src/Events/GreetingsEvent.php Use display_timezone for greeting-hour calculation
app-modules/he4rt/resources/views/components/dashboard/heatmap.blade.php Heatmap current-time highlight uses display_timezone
app-modules/he4rt/resources/views/components/schedule-card.blade.php Normalize schedule timestamps to display_timezone
app-modules/integration-discord/src/ETL/Console/BackfillVoiceLogsCommand.php Format CLI log timestamps with display_timezone
app-modules/panel-admin/resources/views/moderation/appeal-queue/appeal-detail.blade.php SLA deadline displays converted to display_timezone with null fallback
app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/ActivityPerDay.php Use display_timezone and bind into SQL AT TIME ZONE
app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/MessageHeatmap.php Parameterized timezone bindings for day/hour extraction
app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoiceHeatmap.php Parameterized timezone bindings in voice heatmap query
app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoicePerDay.php Day-extraction query updated to use display_timezone
app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/PeriodStats.php Compute subdivisions using display_timezone
app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/TopChannels.php Date range calculations use display_timezone
app-modules/panel-admin/src/Marketing/Pages/MeetingShowcasePage.php Parse meeting bounds with display_timezone and convert to UTC
app-modules/panel-admin/src/Moderation/Livewire/ModerationDashboardLivewire.php Added AT TIME ZONE conversion and parameterized bindings for moderation heatmap
resources/views/livewire/connection-hub.blade.php "Connected at" timestamp uses display_timezone; props formatting
routes/console.php Schedule backup:monitor to run at 09:00 in display_timezone
database/migrations/2026_05_20_160249_alter_messages_sent_at_to_timestamptz.php Migration: convert messages.sent_at to timestamptz interpreting existing values as UTC

Review Change Stack

gvieira18 added 7 commits May 20, 2026 12:07
Centralizes the user-facing timezone in app.display_timezone (env
DISPLAY_TIMEZONE) so modules no longer hardcode 'America/Sao_Paulo'.
Replace hardcoded 'America/Sao_Paulo' with config('app.display_timezone')
and use parameterized SQL bindings for AT TIME ZONE clauses.
Add AT TIME ZONE conversion to activity heatmap SQL query and convert
SLA deadline display to use the configured display timezone.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR centralizes a configurable display timezone (config('app.display_timezone')) and replaces hard-coded or server-local time usage across the codebase: config, analytics queries (day/hour bucketing), Blade components and Livewire views (timestamp conversion/status), console command logging, scheduled task timezone, and a migration converting messages.sent_at to timestamptz.

Possibly related PRs

  • he4rt/heartdevs.com#260: Updates Discord dashboard queries and timezone handling that overlap with this PR's query timezone parameterization.

Suggested reviewers

  • Clintonrocha98
  • thalesmengue
  • danielhe4rt
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 72.73% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main objective: centralizing timezone configuration from hardcoded values to a config-driven approach.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoiceHeatmap.php`:
- Around line 23-24: The VoiceHeatmap query uses selectRaw on occurred_at to
extract dow/hour but only applies a single AT TIME ZONE conversion, causing
incorrect buckets for naive UTC timestamps; update the two selectRaw calls in
VoiceHeatmap.php that reference EXTRACT(DOW FROM occurred_at ...) and
EXTRACT(HOUR FROM occurred_at ...) to first interpret the timestamp as UTC then
convert to the target timezone by changing the expression to use AT TIME ZONE
'UTC' AT TIME ZONE ? and keep passing the $tz parameter for both calls.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro

Run ID: d9538447-540c-4ec5-a68e-89a2e869ebb2

📥 Commits

Reviewing files that changed from the base of the PR and between 5a45594 and 3bf669c.

📒 Files selected for processing (16)
  • app-modules/bot-discord/src/Events/GreetingsEvent.php
  • app-modules/he4rt/resources/views/components/dashboard/heatmap.blade.php
  • app-modules/he4rt/resources/views/components/schedule-card.blade.php
  • app-modules/integration-discord/src/ETL/Console/BackfillVoiceLogsCommand.php
  • app-modules/panel-admin/resources/views/moderation/appeal-queue/appeal-detail.blade.php
  • app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/ActivityPerDay.php
  • app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/MessageHeatmap.php
  • app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/PeriodStats.php
  • app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/TopChannels.php
  • app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoiceHeatmap.php
  • app-modules/panel-admin/src/Marketing/Pages/Discord/Dashboard/Queries/VoicePerDay.php
  • app-modules/panel-admin/src/Marketing/Pages/MeetingShowcasePage.php
  • app-modules/panel-admin/src/Moderation/Livewire/ModerationDashboardLivewire.php
  • config/app.php
  • resources/views/livewire/connection-hub.blade.php
  • routes/console.php

…nversion

VoiceHeatmap and VoicePerDay used single AT TIME ZONE which tells
PostgreSQL the naive timestamp IS in that timezone. The correct pattern
is double conversion (AT TIME ZONE 'UTC' AT TIME ZONE ?) to first
interpret as UTC then convert to the display timezone.
@gvieira18 gvieira18 self-assigned this May 20, 2026
@gvieira18 gvieira18 requested a review from danielhe4rt May 20, 2026 15:16
gvieira18 and others added 7 commits May 20, 2026 13:04
Converts the naive timestamp column to timestamptz, interpreting
existing values as UTC. Matches the voice_messages.occurred_at
migration from 2026-05-19.
Now that sent_at and created_at are timestamptz columns, PostgreSQL
already knows they are UTC. Double AT TIME ZONE conversion is only
needed for naive timestamp columns.
Converts the naive timestamp column to timestamptz, interpreting
existing values as UTC to match the Discord API source data.
All timestamp columns (sent_at, occurred_at, created_at) are now
timestamptz — PostgreSQL already knows they are UTC. Double conversion
is only needed for naive timestamp columns.
Align Docker Compose env vars and Dockerfile to use Etc/UTC instead of
America/Sao_Paulo so the database stores and returns timestamps in UTC.
The double conversion (AT TIME ZONE 'UTC' AT TIME ZONE ?) was
inverting the timezone offset, causing dates to shift forward.
A single AT TIME ZONE ? is correct for timestamptz columns.
@danielhe4rt danielhe4rt merged commit c35082e into 4.x May 20, 2026
6 checks passed
@danielhe4rt danielhe4rt deleted the feat/centralize-display-timezone branch May 20, 2026 20:04
danielhe4rt pushed a commit that referenced this pull request May 20, 2026
https://github.com/user-attachments/assets/4175d3ec-095e-4ee9-80de-3e57c4a967ee



<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Description

This pull request introduces a new navbar component for the portal
module with an animated underline hover effect. The navbar displays
navigation links (Comunidade, Sobre, Projetos, Depoimentos, Contato) and
a Discord button. The links feature a smooth CSS animation that expands
an underline bar on hover and focus states, using Tailwind CSS utilities
and CSS custom properties.

## References

Related recent changes:
- PR `#264`: Centralize display timezone config

## Dependencies & Requirements

No new dependencies or configuration changes required. The feature uses
only existing Tailwind CSS utilities and CSS pseudo-elements.

## Contributor Summary

| Contributor | Lines Added | Lines Removed | Files Changed |
|---|---|---|---|
| andrefelipe18 | 43 | 0 | 1 |

## Changes Summary

| File Path | Change Description |
|---|---|
| app-modules/portal/resources/views/components/navbar.blade.php | New
navbar component with navigation links and animated underline hover
effect using `after:` pseudo-elements with transition animations tied to
`--primary` CSS variable |

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/he4rt/heartdevs.com/pull/265?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants