Skip to content

Commit 198ba53

Browse files
authored
Merge pull request #16 from yoanbernabeu/7-create-a-route-eg-obsqr-with-a-qr-code-that-allows-viewers-to-scan-and-respond-to-the-ongoing-survey
📦 NEW: Adding a QR code generation feature for surveys
2 parents 65c378b + f9b9e5b commit 198ba53

File tree

10 files changed

+277
-6
lines changed

10 files changed

+277
-6
lines changed

assets/app_qr.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import './styles/qr.css';
2+
import 'htmx.org';

assets/styles/qr.css

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
.qr-container {
2+
display: flex;
3+
justify-content: center;
4+
align-items: center;
5+
}
6+
7+
.qr-wrapper {
8+
background-color: rgba(0, 0, 0, 0.96);
9+
padding: 30px;
10+
border-radius: 12px;
11+
width: 300px;
12+
height: 300px;
13+
display: flex;
14+
justify-content: center;
15+
align-items: center;
16+
border: 2px solid rgba(255, 255, 255, 0.1);
17+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
18+
}
19+
20+
.qr-wrapper img {
21+
width: 280px;
22+
height: 280px;
23+
border: 1px solid rgba(79, 70, 229, 0.2);
24+
padding: 10px;
25+
background: rgba(79, 70, 229, 0.1);
26+
border-radius: 8px;
27+
}

composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"php": ">=8.2",
88
"ext-ctype": "*",
99
"ext-iconv": "*",
10+
"chillerlan/php-qrcode": "^5.0",
1011
"doctrine/dbal": "^3",
1112
"doctrine/doctrine-bundle": "^2.13",
1213
"doctrine/doctrine-migrations-bundle": "^3.3",

composer.lock

Lines changed: 160 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

importmap.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,8 @@
6363
'path' => './assets/app_obs.js',
6464
'entrypoint' => true,
6565
],
66-
];
66+
'app_qr' => [
67+
'path' => './assets/app_qr.js',
68+
'entrypoint' => true,
69+
],
70+
];

src/Controller/ObsController.php

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,25 +3,30 @@
33
namespace App\Controller;
44

55
use App\Service\Poll\PollService;
6+
use App\Service\Qr\QrService;
67
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
78
use Symfony\Component\HttpFoundation\Response;
89
use Symfony\Component\Routing\Attribute\Route;
10+
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
911

1012
class ObsController extends AbstractController
1113
{
1214
public function __construct(
1315
private readonly PollService $pollService,
16+
private readonly QrService $qrService,
1417
) {
1518
}
1619

1720
#[Route('/obs', name: 'app_obs')]
1821
public function index(): Response
1922
{
20-
$poll = $this->pollService->getActivePoll();
23+
return $this->render('obs/index.html.twig');
24+
}
2125

22-
return $this->render('obs/index.html.twig', [
23-
'poll' => $poll,
24-
]);
26+
#[Route('/obs/qr', name: 'app_obs_qr')]
27+
public function qr(): Response
28+
{
29+
return $this->render('obs/qr.html.twig');
2530
}
2631

2732
#[Route('/obs/results', name: 'app_obs_results')]
@@ -33,4 +38,26 @@ public function results(): Response
3338
'poll' => $poll,
3439
]);
3540
}
41+
42+
#[Route('/obs/qr/results', name: 'app_obs_qr_results')]
43+
public function qrResults(): Response
44+
{
45+
$poll = $this->pollService->getActivePoll();
46+
47+
if (null === $poll) {
48+
return new Response();
49+
}
50+
51+
$url = $this->generateUrl(
52+
'app_poll_show',
53+
['shortCode' => $poll->getShortCode()],
54+
UrlGeneratorInterface::ABSOLUTE_URL
55+
);
56+
57+
$qrCode = $this->qrService->generateQrCode($url);
58+
59+
return $this->render('obs/_qr_results.html.twig', [
60+
'qrCode' => $qrCode,
61+
]);
62+
}
3663
}

src/Service/Qr/QrService.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Service\Qr;
6+
7+
use chillerlan\QRCode\QRCode;
8+
9+
class QrService
10+
{
11+
public function generateQrCode(string $url): string
12+
{
13+
$qrcode = new QRCode();
14+
15+
return $qrcode->render($url);
16+
}
17+
}

templates/base_qr.html.twig

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>{% block title %}QR Code{% endblock %}</title>
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<style>
8+
body {
9+
margin: 0;
10+
padding: 0;
11+
background: transparent !important;
12+
}
13+
</style>
14+
{% block javascripts %}
15+
{% block importmap %}{{ importmap('app_qr') }}{% endblock %}
16+
{% endblock %}
17+
</head>
18+
<body>
19+
{% block body %}{% endblock %}
20+
</body>
21+
</html>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{% if qrCode %}
2+
<div class="qr-container">
3+
<div class="qr-wrapper">
4+
<img src="{{ qrCode }}" alt="QR Code">
5+
</div>
6+
</div>
7+
{% endif %}

templates/obs/qr.html.twig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{% extends 'base_qr.html.twig' %}
2+
3+
{% block body %}
4+
<div hx-get="{{ path('app_obs_qr_results') }}" hx-trigger="every 2s">
5+
</div>
6+
{% endblock %}

0 commit comments

Comments
 (0)