Polling / Live Updates

Watch the stats update automatically every 2 seconds.

Uses hx-trigger="every 2s" for automatic polling.

Visitors

618

Online now
Orders

71

Today
Revenue

$7816

Today
CPU Usage
56%
Memory Usage
41%

Last updated: 07:46:34

How it works
Source Code View on GitHub
<?php

declare(strict_types=1);

namespace App\Controller;

use DateTime;
use Mdxpl\HtmxBundle\Attribute\HtmxOnly;
use Mdxpl\HtmxBundle\Request\HtmxRequest;
use Mdxpl\HtmxBundle\Response\HtmxResponse;
use Mdxpl\HtmxBundle\Response\HtmxResponseBuilder;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Routing\Attribute\Route;

#[Route('/polling')]
final class PollingController extends AbstractController
{
    #[Route('', name: 'app_polling')]
    public function index(HtmxRequest $htmx): HtmxResponse
    {
        return HtmxResponseBuilder::create($htmx->isHtmx)
            ->success()
            ->view('polling.html.twig', ['stats' => $this->generateStats()])
            ->build();
    }

    #[Route('/stats', name: 'app_polling_stats')]
    #[HtmxOnly]
    public function stats(HtmxRequest $htmx): HtmxResponse
    {
        return HtmxResponseBuilder::create($htmx->isHtmx)
            ->success()
            ->viewBlock('polling.html.twig', 'statsContent', ['stats' => $this->generateStats()])
            ->build();
    }

    /**
     * @return array{visitors: int, orders: int, revenue: int, cpu: int, memory: int, updated_at: string}
     */
    private function generateStats(): array
    {
        return [
            'visitors' => rand(100, 999),
            'orders' => rand(10, 99),
            'revenue' => rand(1000, 9999),
            'cpu' => rand(20, 95),
            'memory' => rand(40, 85),
            'updated_at' => new DateTime()->format('H:i:s'),
        ];
    }
}
{% block statsContent %}
<div class="grid">
    <article>
        <header><strong>Visitors</strong></header>
        <p style="font-size: 2rem; color: var(--pico-primary);">{{ stats.visitors }}</p>
        <footer><small>Online now</small></footer>
    </article>

    <article>
        <header><strong>Orders</strong></header>
        <p style="font-size: 2rem; color: var(--pico-secondary);">{{ stats.orders }}</p>
        <footer><small>Today</small></footer>
    </article>

    <article>
        <header><strong>Revenue</strong></header>
        <p style="font-size: 2rem; color: var(--pico-ins-color);">${{ stats.revenue }}</p>
        <footer><small>Today</small></footer>
    </article>
</div>

<div class="grid">
    <article>
        <header><strong>CPU Usage</strong></header>
        <progress value="{{ stats.cpu }}" max="100"></progress>
        <footer><small>{{ stats.cpu }}%</small></footer>
    </article>

    <article>
        <header><strong>Memory Usage</strong></header>
        <progress value="{{ stats.memory }}" max="100"></progress>
        <footer><small>{{ stats.memory }}%</small></footer>
    </article>
</div>

<p style="text-align: center;"><small>Last updated: {{ stats.updated_at }}</small></p>
{% endblock %}