Add a way of validating answers and render whole group of questions not just one file at a time. Add a cs-fixer package
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -14,3 +14,8 @@
|
||||
/public/assets/
|
||||
/assets/vendor/
|
||||
###< symfony/asset-mapper ###
|
||||
|
||||
###> php-cs-fixer/shim ###
|
||||
/.php-cs-fixer.php
|
||||
/.php-cs-fixer.cache
|
||||
###< php-cs-fixer/shim ###
|
||||
|
||||
13
.php-cs-fixer.dist.php
Normal file
13
.php-cs-fixer.dist.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
$finder = (new PhpCsFixer\Finder())
|
||||
->in(__DIR__)
|
||||
->exclude('var')
|
||||
;
|
||||
|
||||
return (new PhpCsFixer\Config())
|
||||
->setRules([
|
||||
'@Symfony' => true,
|
||||
])
|
||||
->setFinder($finder)
|
||||
;
|
||||
@@ -8,6 +8,7 @@
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"efficience-it/certification-symfony": "^1.0",
|
||||
"php-cs-fixer/shim": "^3.64",
|
||||
"symfony/asset": "7.1.*",
|
||||
"symfony/asset-mapper": "7.1.*",
|
||||
"symfony/console": "7.1.*",
|
||||
|
||||
54
composer.lock
generated
54
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "37fda8896febb7725269604fcf26625b",
|
||||
"content-hash": "4cecbae9a6775775e8fcd1192a4860ae",
|
||||
"packages": [
|
||||
{
|
||||
"name": "composer/semver",
|
||||
@@ -97,6 +97,58 @@
|
||||
},
|
||||
"type": "library"
|
||||
},
|
||||
{
|
||||
"name": "php-cs-fixer/shim",
|
||||
"version": "v3.64.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-CS-Fixer/shim.git",
|
||||
"reference": "81ccfd24baf3a10810dab1152c403981a790b837"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-CS-Fixer/shim/zipball/81ccfd24baf3a10810dab1152c403981a790b837",
|
||||
"reference": "81ccfd24baf3a10810dab1152c403981a790b837",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"php": "^7.4 || ^8.0"
|
||||
},
|
||||
"replace": {
|
||||
"friendsofphp/php-cs-fixer": "self.version"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-dom": "For handling output formats in XML",
|
||||
"ext-mbstring": "For handling non-UTF8 characters."
|
||||
},
|
||||
"bin": [
|
||||
"php-cs-fixer",
|
||||
"php-cs-fixer.phar"
|
||||
],
|
||||
"type": "application",
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Dariusz Rumiński",
|
||||
"email": "dariusz.ruminski@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A tool to automatically fix PHP code style",
|
||||
"support": {
|
||||
"issues": "https://github.com/PHP-CS-Fixer/shim/issues",
|
||||
"source": "https://github.com/PHP-CS-Fixer/shim/tree/v3.64.0"
|
||||
},
|
||||
"time": "2024-08-30T23:10:11+00:00"
|
||||
},
|
||||
{
|
||||
"name": "psr/cache",
|
||||
"version": "3.0.0",
|
||||
|
||||
@@ -4,29 +4,56 @@ namespace App\Controller;
|
||||
|
||||
use App\Service\QuestionsService;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class ChallengeController extends AbstractController
|
||||
{
|
||||
|
||||
#[Route('/challenge', name: 'app_challenge')]
|
||||
#[Route('/challenge', name: 'app_challenges')]
|
||||
public function randomChallenge(): Response
|
||||
{
|
||||
return $this->render('challenge/start.html.twig');
|
||||
}
|
||||
|
||||
#[Route('/list', name: 'app_list')]
|
||||
#[Route('/', name: 'app_home')]
|
||||
public function list(QuestionsService $questionsService): Response
|
||||
{
|
||||
$listOfChallenges = $questionsService->getList();
|
||||
|
||||
return $this->render('challenge/list.html.twig', ['list' => $listOfChallenges]);
|
||||
}
|
||||
|
||||
#[Route('/challenge/{challenge<.*>}', name: 'app_challenge')]
|
||||
#[Route('/challenge/{challenge<.*>}', name: 'app_challenge', methods: ['GET'])]
|
||||
public function challenge(QuestionsService $questionsService, string $challenge): Response
|
||||
{
|
||||
$questions = $questionsService->getQuestions($challenge);
|
||||
return $this->render('challenge/list.html.twig', ['list' => $questions, 'challenge' => $challenge]);
|
||||
|
||||
return $this->render('challenge/start.html.twig', ['questions' => $questions, 'challenge' => $challenge]);
|
||||
}
|
||||
|
||||
|
||||
#[Route('/challenge/{challenge<.*>}', name: 'app_challenge2', methods: ['POST'])]
|
||||
public function challengeSubmit(Request $request, QuestionsService $questionsService, string $challenge): Response
|
||||
{
|
||||
$answers = $request->getPayload()->all('answer');
|
||||
$questions = $questionsService->questionsById($request->getPayload()->all('question_id'));
|
||||
|
||||
//dd($answers);
|
||||
//dd($questionsService->questionsById($request->getPayload()->all('question_id')));
|
||||
//$x = $request->getPayload()->get('question_id');
|
||||
//dd($questionsService->questionsById($request->getPayload()->all('question_id')));
|
||||
//dd($request->getPayload()->all());
|
||||
|
||||
//$questions = $questionsService->getQuestions($challenge);
|
||||
return $this->render('challenge/submit.html.twig', ['questions' => $questions, 'challenge' => $challenge, 'answers' => $answers]);
|
||||
}
|
||||
|
||||
#[Route('/challenge_group/{group<.*>}', name: 'app_challenge_group')]
|
||||
public function randomChallengeGroup(QuestionsService $questionsService, string $group): Response
|
||||
{
|
||||
$questions = $questionsService->getQuestionsGroup($group);
|
||||
|
||||
return $this->render('challenge/start_group.html.twig', ['questions' => $questions, 'group' => $group]);
|
||||
}
|
||||
}
|
||||
@@ -9,12 +9,11 @@ use Symfony\Component\Routing\Attribute\Route;
|
||||
|
||||
class HomeController extends AbstractController
|
||||
{
|
||||
#[Route('/', name: 'app_home')]
|
||||
#[Route('/home')]
|
||||
public function home(QuestionsService $questionsService): Response
|
||||
{
|
||||
$questions = $questionsService->getQuestions();
|
||||
|
||||
return $this->render('home/index.html.twig', ['questions' => $questions]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,27 +12,66 @@ class QuestionsService
|
||||
{
|
||||
}
|
||||
|
||||
public function getQuestions(?string $file): array
|
||||
public function getQuestions(?string $file = null, bool $shuffle = true): array
|
||||
{
|
||||
$questions = [];
|
||||
foreach ($this->getQuestionFiles($file) as $file) {
|
||||
foreach ($this->getQuestionFiles(file: $file) as $file) {
|
||||
$yamlFile = Yaml::parseFile($file->getRealPath());
|
||||
$questions = array_merge($questions, $yamlFile['questions']);
|
||||
}
|
||||
if ($shuffle) {
|
||||
shuffle($questions);
|
||||
array_walk($questions, static function (array &$value): void {
|
||||
shuffle($value['answers']);
|
||||
$answers = 0;
|
||||
foreach ($value['answers'] as $answer) {
|
||||
$answers += $answer['correct'];
|
||||
}
|
||||
$value['type'] = $answers > 1 ? 'multiple' : 'single';
|
||||
$value['count'] = $answers;
|
||||
});
|
||||
}
|
||||
|
||||
return $questions;
|
||||
}
|
||||
|
||||
private function getQuestionFiles(?string $file = null): array
|
||||
public function questionsById(array $questionIds): array
|
||||
{
|
||||
$questions = [];
|
||||
foreach ($this->getQuestionFiles() as $file) {
|
||||
$yamlFile = Yaml::parseFile($file->getRealPath());
|
||||
if (isset($yamlFile['questions'])) {
|
||||
//dd(array_column($yamlFile['questions'], 'uuid'));
|
||||
//dd($yamlFile['questions']);
|
||||
$questions += array_combine(array_column($yamlFile['questions'], 'uuid'), $yamlFile['questions']);
|
||||
//$questions = array_merge($questions, $yamlFile['questions']);
|
||||
}
|
||||
}
|
||||
|
||||
return array_filter($questions, fn(array $value): bool => in_array($value['uuid'], $questionIds, true));
|
||||
}
|
||||
|
||||
private function getQuestionFiles(?string $file = null, ?string $group = null): array
|
||||
{
|
||||
$finder = new Finder();
|
||||
if (null !== $file) {
|
||||
if ($file) {
|
||||
$finder->name($file);
|
||||
} else {
|
||||
$finder->name('*.yaml');
|
||||
}
|
||||
$finder->in($this->paths);
|
||||
}
|
||||
if (null !== $group) {
|
||||
$paths = array_filter(array_map(fn(string $path): string => $path . DIRECTORY_SEPARATOR . $group, $this->paths), 'is_dir');
|
||||
$finder->in($paths);
|
||||
$finder->name('*.yaml');
|
||||
}
|
||||
if (null === $group and null === $file) {
|
||||
$finder->in($this->paths);
|
||||
}
|
||||
|
||||
return iterator_to_array($finder->files()->in($this->paths));
|
||||
return iterator_to_array($finder->files());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -43,4 +82,18 @@ class QuestionsService
|
||||
return $this->getQuestionFiles();
|
||||
}
|
||||
|
||||
public function getQuestionsGroup(string $group, bool $shuffle = true): array
|
||||
{
|
||||
$questions = [];
|
||||
foreach ($this->getQuestionFiles(group: $group) as $file) {
|
||||
$yamlFile = Yaml::parseFile($file->getRealPath());
|
||||
$questions = array_merge($questions, $yamlFile['questions']);
|
||||
}
|
||||
if ($shuffle) {
|
||||
shuffle($questions);
|
||||
array_walk($questions, static fn(array &$value): true => shuffle($value['answers']));
|
||||
}
|
||||
|
||||
return $questions;
|
||||
}
|
||||
}
|
||||
12
symfony.lock
12
symfony.lock
@@ -1,4 +1,16 @@
|
||||
{
|
||||
"php-cs-fixer/shim": {
|
||||
"version": "3.64",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "main",
|
||||
"version": "3.0",
|
||||
"ref": "16422bf8eac6c3be42afe07d37e2abc89d2bdf6b"
|
||||
},
|
||||
"files": [
|
||||
".php-cs-fixer.dist.php"
|
||||
]
|
||||
},
|
||||
"symfony/asset-mapper": {
|
||||
"version": "7.1",
|
||||
"recipe": {
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<div class="flex flex-shrink-0 items-center">
|
||||
{# <img class="h-8 w-auto" src="https://tailwindui.com/plus/img/logos/mark.svg?color=indigo&shade=500" alt="Your Company"> #}
|
||||
|
||||
<a href="">
|
||||
<a href="{{ path('app_home') }}">
|
||||
<img class="h-[40px]" src="{{ asset('images/logo.png') }}" alt="logo">
|
||||
</a>
|
||||
|
||||
@@ -53,10 +53,10 @@
|
||||
<div class="hidden sm:ml-6 sm:block">
|
||||
<div class="flex space-x-4">
|
||||
<!-- Current: "bg-gray-900 text-white", Default: "text-gray-300 hover:bg-gray-700 hover:text-white" -->
|
||||
<a href="#" class="rounded-md bg-gray-900 px-3 py-2 text-sm font-medium text-white" aria-current="page">Dashboard</a>
|
||||
<a href="#" class="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Team</a>
|
||||
<a href="#" class="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Projects</a>
|
||||
<a href="#" class="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Calendar</a>
|
||||
<a href="#" class="rounded-md bg-gray-900 px-3 py-2 text-sm font-medium text-white" aria-current="page">Home</a>
|
||||
{# <a href="#" class="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Team</a>#}
|
||||
{# <a href="#" class="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Projects</a>#}
|
||||
{# <a href="#" class="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700 hover:text-white">Calendar</a>#}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,16 +3,16 @@
|
||||
{% block body %}
|
||||
<div class="mx-auto mt-5 max-w-7xl px-2 sm:px-6 lg:px-8">
|
||||
<div class="mt-5 max-w-7xl px-2 sm:px-6 lg:px-8">
|
||||
{% set test = '' %}
|
||||
{% set currentGroup = '' %}
|
||||
{% for challenge in list %}
|
||||
{% if test != challenge.getRelativePath %}
|
||||
{% if currentGroup != challenge.getRelativePath %}
|
||||
<h2 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight">
|
||||
<a href="">{{ challenge.getRelativePath|replace({'_': ' '})|capitalize }} / All</a>
|
||||
<a href="{{ path('app_challenge_group', {'group': challenge.getRelativePath}) }}">{{ challenge.getRelativePath|replace({'_': ' '})|capitalize }} / All</a>
|
||||
</h2>
|
||||
{% endif %}
|
||||
<h2 class="leading-7 hover:text-cyan-600 text-gray-900 sm:truncate sm:tracking-tight ms-8">
|
||||
<h2 class="leading-7 hover:text-cyan-600 text-gray-900 sm:truncate sm:tracking-tight ms-8 text-sm">
|
||||
<a href="{{ path('app_challenge', {'challenge': challenge.getfilename}) }}">{{ challenge.getFilenameWithoutExtension|replace({'_': ' '})|capitalize }}</a></h2>
|
||||
{% set test = challenge.getRelativePath %}
|
||||
{% set currentGroup = challenge.getRelativePath %}
|
||||
{% endfor %}
|
||||
<div class="lg:flex lg:items-center lg:justify-between">
|
||||
<div class="min-w-0 flex-1">
|
||||
|
||||
@@ -1,99 +1,52 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<div class="mx-auto mt-5 max-w-7xl px-2 sm:px-6 lg:px-8">
|
||||
<div class="mx-auto mt-5 max-w-7xl px-2 sm:px-6 lg:px-8 pb-10">
|
||||
|
||||
<div class="lg:flex lg:items-center lg:justify-between">
|
||||
<div class="min-w-0 flex-1">
|
||||
<h2 class="text-2xl font-bold leading-7 text-gray-900 sm:truncate sm:text-3xl sm:tracking-tight">Back End Developer</h2>
|
||||
<div class="mt-1 flex flex-col sm:mt-0 sm:flex-row sm:flex-wrap sm:space-x-6">
|
||||
<div class="mt-2 flex items-center text-sm text-gray-500">
|
||||
<svg class="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path fill-rule="evenodd"
|
||||
d="M6 3.75A2.75 2.75 0 0 1 8.75 1h2.5A2.75 2.75 0 0 1 14 3.75v.443c.572.055 1.14.122 1.706.2C17.053 4.582 18 5.75 18 7.07v3.469c0 1.126-.694 2.191-1.83 2.54-1.952.599-4.024.921-6.17.921s-4.219-.322-6.17-.921C2.694 12.73 2 11.665 2 10.539V7.07c0-1.321.947-2.489 2.294-2.676A41.047 41.047 0 0 1 6 4.193V3.75Zm6.5 0v.325a41.622 41.622 0 0 0-5 0V3.75c0-.69.56-1.25 1.25-1.25h2.5c.69 0 1.25.56 1.25 1.25ZM10 10a1 1 0 0 0-1 1v.01a1 1 0 0 0 1 1h.01a1 1 0 0 0 1-1V11a1 1 0 0 0-1-1H10Z"
|
||||
clip-rule="evenodd"/>
|
||||
<path d="M3 15.055v-.684c.126.053.255.1.39.142 2.092.642 4.313.987 6.61.987 2.297 0 4.518-.345 6.61-.987.135-.041.264-.089.39-.142v.684c0 1.347-.985 2.53-2.363 2.686a41.454 41.454 0 0 1-9.274 0C3.985 17.585 3 16.402 3 15.055Z"/>
|
||||
</svg>
|
||||
Full-time
|
||||
</div>
|
||||
<div class="mt-2 flex items-center text-sm text-gray-500">
|
||||
<svg class="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path fill-rule="evenodd"
|
||||
d="m9.69 18.933.003.001C9.89 19.02 10 19 10 19s.11.02.308-.066l.002-.001.006-.003.018-.008a5.741 5.741 0 0 0 .281-.14c.186-.096.446-.24.757-.433.62-.384 1.445-.966 2.274-1.765C15.302 14.988 17 12.493 17 9A7 7 0 1 0 3 9c0 3.492 1.698 5.988 3.355 7.584a13.731 13.731 0 0 0 2.273 1.765 11.842 11.842 0 0 0 .976.544l.062.029.018.008.006.003ZM10 11.25a2.25 2.25 0 1 0 0-4.5 2.25 2.25 0 0 0 0 4.5Z"
|
||||
clip-rule="evenodd"/>
|
||||
</svg>
|
||||
Remote
|
||||
</div>
|
||||
<div class="mt-2 flex items-center text-sm text-gray-500">
|
||||
<svg class="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path d="M10.75 10.818v2.614A3.13 3.13 0 0 0 11.888 13c.482-.315.612-.648.612-.875 0-.227-.13-.56-.612-.875a3.13 3.13 0 0 0-1.138-.432ZM8.33 8.62c.053.055.115.11.184.164.208.16.46.284.736.363V6.603a2.45 2.45 0 0 0-.35.13c-.14.065-.27.143-.386.233-.377.292-.514.627-.514.909 0 .184.058.39.202.592.037.051.08.102.128.152Z"/>
|
||||
<path fill-rule="evenodd"
|
||||
d="M18 10a8 8 0 1 1-16 0 8 8 0 0 1 16 0Zm-8-6a.75.75 0 0 1 .75.75v.316a3.78 3.78 0 0 1 1.653.713c.426.33.744.74.925 1.2a.75.75 0 0 1-1.395.55 1.35 1.35 0 0 0-.447-.563 2.187 2.187 0 0 0-.736-.363V9.3c.698.093 1.383.32 1.959.696.787.514 1.29 1.27 1.29 2.13 0 .86-.504 1.616-1.29 2.13-.576.377-1.261.603-1.96.696v.299a.75.75 0 1 1-1.5 0v-.3c-.697-.092-1.382-.318-1.958-.695-.482-.315-.857-.717-1.078-1.188a.75.75 0 1 1 1.359-.636c.08.173.245.376.54.569.313.205.706.353 1.138.432v-2.748a3.782 3.782 0 0 1-1.653-.713C6.9 9.433 6.5 8.681 6.5 7.875c0-.805.4-1.558 1.097-2.096a3.78 3.78 0 0 1 1.653-.713V4.75A.75.75 0 0 1 10 4Z"
|
||||
clip-rule="evenodd"/>
|
||||
</svg>
|
||||
$120k – $140k
|
||||
</div>
|
||||
<div class="mt-2 flex items-center text-sm text-gray-500">
|
||||
<svg class="mr-1.5 h-5 w-5 flex-shrink-0 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path fill-rule="evenodd"
|
||||
d="M5.75 2a.75.75 0 0 1 .75.75V4h7V2.75a.75.75 0 0 1 1.5 0V4h.25A2.75 2.75 0 0 1 18 6.75v8.5A2.75 2.75 0 0 1 15.25 18H4.75A2.75 2.75 0 0 1 2 15.25v-8.5A2.75 2.75 0 0 1 4.75 4H5V2.75A.75.75 0 0 1 5.75 2Zm-1 5.5c-.69 0-1.25.56-1.25 1.25v6.5c0 .69.56 1.25 1.25 1.25h10.5c.69 0 1.25-.56 1.25-1.25v-6.5c0-.69-.56-1.25-1.25-1.25H4.75Z"
|
||||
clip-rule="evenodd"/>
|
||||
</svg>
|
||||
Closing on January 9, 2020
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 flex lg:ml-4 lg:mt-0">
|
||||
<span class="hidden sm:block">
|
||||
<button type="button" class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
|
||||
<svg class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path d="m2.695 14.762-1.262 3.155a.5.5 0 0 0 .65.65l3.155-1.262a4 4 0 0 0 1.343-.886L17.5 5.501a2.121 2.121 0 0 0-3-3L3.58 13.419a4 4 0 0 0-.885 1.343Z"/>
|
||||
</svg>
|
||||
Edit
|
||||
</button>
|
||||
</span>
|
||||
<h1 class="mx-4 mb-4 font-semibold text-2xl">{{ challenge|replace({'.yaml': '', '_': ' '})|capitalize }}</h1>
|
||||
|
||||
<span class="ml-3 hidden sm:block">
|
||||
<button type="button" class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
|
||||
<svg class="-ml-0.5 mr-1.5 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path d="M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"/>
|
||||
<path d="M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"/>
|
||||
</svg>
|
||||
View
|
||||
</button>
|
||||
</span>
|
||||
<form method="post">
|
||||
<div>
|
||||
{% for question in questions %}
|
||||
<input name="question_id[]" type="hidden" value="{{ question.uuid }}"/>
|
||||
<div class="mx-4 mb-8">
|
||||
<h2 class="mb-3 text-sm">{{ loop.index }}. {{ question.question }}</h2>
|
||||
{% for answer in question.answers %}
|
||||
<div class="mb-2">
|
||||
<label class="ms-4 mb-2 text-gray-800 text-sm">
|
||||
<input type="{% if question.type == 'single' %}radio{% else %}checkbox{% endif %}" class="rounded text-pink-500" value="{{ answer.value }}"
|
||||
name="answer[{{ question.uuid }}][]">
|
||||
{{ answer.value }}
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
|
||||
<span class="sm:ml-3">
|
||||
<button type="button"
|
||||
<button type="submit"
|
||||
class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
|
||||
<svg class="-ml-0.5 mr-1.5 h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z"
|
||||
clip-rule="evenodd"/>
|
||||
</svg>
|
||||
Publish
|
||||
Submit
|
||||
</button>
|
||||
</span>
|
||||
<span class="sm:ml-3">
|
||||
|
||||
<!-- Dropdown -->
|
||||
<div class="relative ml-3 sm:hidden">
|
||||
<button type="button"
|
||||
class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:ring-gray-400"
|
||||
id="mobile-menu-button" aria-expanded="false" aria-haspopup="true">
|
||||
More
|
||||
<svg class="-mr-1 ml-1.5 h-5 w-5 text-gray-400" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path fill-rule="evenodd" d="M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z"
|
||||
clip-rule="evenodd"/>
|
||||
</svg>
|
||||
<button type="reset"
|
||||
class="inline-flex items-center rounded-md bg-gray-200 px-3 py-2 text-sm font-semibold text-gray-400 shadow-sm hover:bg-gray-400 hover:text-gray-100 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="-ml-0.5 mr-1.5 h-5 w-5" >
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m9.75 9.75 4.5 4.5m0-4.5-4.5 4.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z"/>
|
||||
</svg>
|
||||
Reset
|
||||
</button>
|
||||
|
||||
<div class="absolute right-0 z-10 -mr-1 mt-2 w-48 origin-top-right rounded-md bg-white py-1 shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none" role="menu"
|
||||
aria-orientation="vertical" aria-labelledby="mobile-menu-button" tabindex="-1">
|
||||
<!-- Active: "bg-gray-100", Not Active: "" -->
|
||||
<a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="mobile-menu-item-0">Edit</a>
|
||||
<a href="#" class="block px-4 py-2 text-sm text-gray-700" role="menuitem" tabindex="-1" id="mobile-menu-item-1">View</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
30
templates/challenge/start_group.html.twig
Normal file
30
templates/challenge/start_group.html.twig
Normal file
@@ -0,0 +1,30 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<div class="mx-auto mt-5 max-w-7xl px-2 sm:px-6 lg:px-8 pb-10">
|
||||
{% for question in questions %}
|
||||
<div class="mx-4 mb-8">
|
||||
|
||||
<h2 class="mb-3 text-sm">{{ loop.index }}. {{ question.question }}</h2>
|
||||
{% for answer in question.answers %}
|
||||
<div class="mb-2">
|
||||
<label class="ms-4 mb-2 text-gray-800 text-sm">
|
||||
<input type="radio" class="rounded text-pink-500" name="{{ question.uuid }}">
|
||||
{{ answer.value }}
|
||||
</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<span class="sm:ml-3">
|
||||
<button type="button"
|
||||
class="inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
|
||||
<svg class="-ml-0.5 mr-1.5 h-5 w-5" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true" data-slot="icon">
|
||||
<path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 0 1 .143 1.052l-8 10.5a.75.75 0 0 1-1.127.075l-4.5-4.5a.75.75 0 0 1 1.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 0 1 1.05-.143Z"
|
||||
clip-rule="evenodd"/>
|
||||
</svg>
|
||||
Submit
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
34
templates/challenge/submit.html.twig
Normal file
34
templates/challenge/submit.html.twig
Normal file
@@ -0,0 +1,34 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block body %}
|
||||
<div class="mx-auto mt-5 max-w-7xl px-2 sm:px-6 lg:px-8 pb-10">
|
||||
<h1 class="mx-4 mb-4 font-semibold text-2xl">{{ challenge|replace({'.yaml': '', '_': ' '})|capitalize }}</h1>
|
||||
<div>
|
||||
{% for question in questions %}
|
||||
<div class="mx-4 mb-8">
|
||||
<h2 class="mb-3 text-sm">{{ loop.index }}. {{ question.question }}</h2>
|
||||
{% for questionanswer in question.answers %}
|
||||
<div class="mb-2">
|
||||
<div class="ms-4 mb-2 m-4 text-gray-800 text-sm">
|
||||
{% if answers[question.uuid] is defined %}
|
||||
{% if questionanswer.value in answers[question.uuid] and questionanswer.correct == true %}
|
||||
<span class="text-green-700 bg-green-200 p-2">{{ questionanswer.value }}</span>
|
||||
{% elseif questionanswer.value in answers[question.uuid] and questionanswer.correct == false %}
|
||||
<span class="text-red-700 bg-red-200 p-2">{{ questionanswer.value }}</span>
|
||||
{% else %}
|
||||
<span class="p-2">{{ questionanswer.value }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{{ questionanswer.value }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<div class="ms-4 mt-4 mb-2 ">
|
||||
<span class="text-gray-400 p-2 text-sm bg-gray-200">help: </span><a href="{{ question.help }}" target="_blank" class="text-gray-400 p-2 text-sm">{{ question.help }}</a>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user