WIP: Implement menu/navigation

This commit is contained in:
Björn Fromme
2023-09-25 18:02:27 +02:00
parent c3c2e1ae2d
commit 3e0353c79b
24 changed files with 475 additions and 92 deletions
+21 -3
View File
@@ -1,7 +1,15 @@
.menu {
.menu--header {
@apply flex items-center space-x-4 h-8;
}
.menu--main {
@apply flex flex-col divide-y divide-gray-200;
}
.menu--main > li {
@apply py-4 first:pt-0 last:pb-0;
}
.menu--mobile {
@apply flex-col space-x-0 h-auto divide-y divide-gray-200;
}
@@ -10,7 +18,8 @@
@apply py-4 w-full;
}
.menu a {
.menu a,
.menu div {
@apply uppercase hover:text-slate-700 text-slate-900 text-sm lg:text-base;
}
@@ -18,11 +27,20 @@
@apply text-lg;
}
.menu ul {
@apply pl-7 pt-1;
}
.menu ul a {
@apply text-sm;
}
.menu .current > a,
.menu .active > a {
@apply text-slate-900 font-bold;
}
.menu .icon-link {
.menu .icon-link,
.menu .icon-section {
@apply flex items-center space-x-2;
}
+36 -2
View File
@@ -56,13 +56,47 @@ services:
$intlExtension: '@twig.extension.intl'
$environment: '%kernel.environment%'
App\Menu\MenuBuilder:
App\Menu\AdminMenuBuilder:
arguments:
$factory: '@knp_menu.factory'
tags:
- name: knp_menu.menu_builder
method: createHeaderMenu
alias: admin_header
- name: knp_menu.menu_builder
method: createMainMenu
alias: main
alias: admin_main
- name: knp_menu.menu_builder
method: createMobileMenu
alias: admin_mobile
App\Menu\ManagerMenuBuilder:
arguments:
$factory: '@knp_menu.factory'
tags:
- name: knp_menu.menu_builder
method: createHeaderMenu
alias: manager_header
- name: knp_menu.menu_builder
method: createMainMenu
alias: manager_main
- name: knp_menu.menu_builder
method: createMobileMenu
alias: manager_mobile
App\Menu\TeamerMenuBuilder:
arguments:
$factory: '@knp_menu.factory'
tags:
- name: knp_menu.menu_builder
method: createHeaderMenu
alias: teamer_header
- name: knp_menu.menu_builder
method: createMainMenu
alias: teamer_main
- name: knp_menu.menu_builder
method: createMobileMenu
alias: teamer_mobile
App\Service\Upload\UploadHandler:
arguments:
+1 -1
View File
@@ -1,5 +1,5 @@
{
"name": "myep-team",
"name": "html",
"lockfileVersion": 2,
"requires": true,
"packages": {
@@ -0,0 +1,18 @@
<?php
namespace App\Controller\Teamer\Disposition;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class IndexController extends AbstractController
{
#[Route('/teamer/disposition', name: 'app_teamer_disposition_index')]
#[IsGranted('ROLE_TEAMER')]
public function index(): Response
{
return $this->render('');
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Controller\Teamer\Disposition;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class WatchlistController extends AbstractController
{
#[Route('/teamer/disposition/watchlist', name: 'app_teamer_disposition_watchlist')]
#[IsGranted('ROLE_TEAMER')]
public function index(): Response
{
return $this->render('');
}
}
@@ -0,0 +1,18 @@
<?php
namespace App\Controller\Teamer\Profile;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class AvailabilitiesController extends AbstractController
{
#[Route('/teamer/profile/availabilities', name: 'app_teamer_profile_availabilities')]
#[IsGranted('ROLE_TEAMER')]
public function index(): Response
{
return $this->render('');
}
}
@@ -1,6 +1,6 @@
<?php
namespace App\Controller\Teamer;
namespace App\Controller\Teamer\Profile;
use App\BusProNet\ApiClient;
use App\BusProNet\ApiClientException;
@@ -19,7 +19,7 @@ use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
use Symfony\Component\Validator\Validator\ValidatorInterface;
class ProfileController extends AbstractController
class IndexController extends AbstractController
{
public function __construct(
private readonly ValidatorInterface $validator,
@@ -30,7 +30,7 @@ class ProfileController extends AbstractController
) {
}
#[Route('/teamer/profile', name: 'app_teamer_profile')]
#[Route('/teamer/profile', name: 'app_teamer_profile_index')]
#[IsGranted('ROLE_TEAMER')]
public function index(Request $request): Response
{
@@ -0,0 +1,18 @@
<?php
namespace App\Controller\Teamer\Profile;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
class SkillsController extends AbstractController
{
#[Route('/teamer/profile/skills', name: 'app_teamer_profile_skills')]
#[IsGranted('ROLE_TEAMER')]
public function index(): Response
{
return $this->render('');
}
}
@@ -10,7 +10,7 @@ use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Security\Core\Authentication\Token\SwitchUserToken;
use Symfony\Contracts\Translation\TranslatorInterface;
class MenuBuilder
abstract class AbstractMenuBuilder
{
public function __construct(
protected FactoryInterface $factory,
@@ -20,42 +20,26 @@ class MenuBuilder
) {
}
private function assertMobile(array $options): bool
protected function assertMobile(array $options): bool
{
return isset($options['mobile']) && true === (bool) $options['mobile'];
}
private function createRootElement(bool $isMobile): ItemInterface
protected function createRootElement(string $class): ItemInterface
{
return $this
->factory->createItem('root')
->setChildrenAttribute('class', 'menu'.($isMobile ? ' menu--mobile' : ''))
->setChildrenAttribute('class', $class)
;
}
private function getDefaultRouteParameters(string $parameter = 'id', string $default = '0'): array
protected function getDefaultRouteParameters(string $parameter = 'id', string $default = '0'): array
{
return [$parameter => $this->requestStack->getMainRequest()->get($parameter, $default)];
}
public function createMainMenu(array $options): ItemInterface
protected function addLogoutItem(ItemInterface $menu, bool $isMobile = false): void
{
/** @var User $user */
$user = $this->security->getUser();
$userLabel = $user->getUserIdentifier();
$isMobile = $this->assertMobile($options);
$menu = $this->createRootElement($isMobile);
if ($this->security->isGranted('ROLE_TEAMER')) {
$menu
->addChild('Profil', ['route' => 'app_teamer_profile'])
->setLinkAttribute('title', 'Benutzer: '.$userLabel)
->setExtra('icon', 'user')
->setExtra('icon_only', false === $isMobile)
;
}
$token = $this->security->getToken();
if ($token instanceof SwitchUserToken) {
@@ -85,6 +69,5 @@ class MenuBuilder
;
}
return $menu;
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace App\Menu;
use Knp\Menu\ItemInterface;
class AdminMenuBuilder extends AbstractMenuBuilder
{
public function createHeaderMenu(array $options): ItemInterface
{
$menu = $this->createRootElement();
$this->addLogoutItem($menu);
return $menu;
}
public function createMainMenu(array $options): ItemInterface
{
$menu = $this->createRootElement();
return $menu;
}
public function createMobileMenu(array $options): ItemInterface
{
$menu = $this->createRootElement(true);
$this->addLogoutItem($menu, true);
return $menu;
}
}
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace App\Menu;
use Knp\Menu\ItemInterface;
class ManagerMenuBuilder extends AbstractMenuBuilder
{
public function createHeaderMenu(array $options): ItemInterface
{
$menu = $this->createRootElement();
$this->addLogoutItem($menu);
return $menu;
}
public function createMainMenu(array $options): ItemInterface
{
$menu = $this->createRootElement();
return $menu;
}
public function createMobileMenu(array $options): ItemInterface
{
$menu = $this->createRootElement(true);
$this->addLogoutItem($menu, true);
return $menu;
}
}
+92
View File
@@ -0,0 +1,92 @@
<?php
namespace App\Menu;
use Knp\Menu\ItemInterface;
class TeamerMenuBuilder extends AbstractMenuBuilder
{
public function createHeaderMenu(array $options): ItemInterface
{
$menu = $this->createRootElement('menu menu--header');
$this->addLogoutItem($menu);
return $menu;
}
public function createMainMenu(array $options): ItemInterface
{
$menu = $this->createRootElement('menu menu--main');
$menu
->addChild('Einsatzübersicht', ['route' => 'app_teamer_disposition_index'])
->setLinkAttributes([
'title' => 'Einsatzübersicht',
'class' => 'icon-link',
])
->setExtra('icon', 'calendar')
->setExtra('icon_only', false)
;
$profileMenu = $menu
->addChild('Mein Profil')
->setExtra('icon', 'user')
->setExtra('icon_only', false)
;
$profileMenu
->addChild('Stammdaten und Foto', ['route' => 'app_teamer_profile_index'])
->setLinkAttributes([
'title' => 'Mein Profil',
])
;
$profileMenu
->addChild('Jobprofile & Skills', ['route' => 'app_teamer_profile_skills'])
->setLinkAttributes([
'title' => 'Jobprofile & Skills',
])
;
$profileMenu
->addChild('Meine Verfügbarkeit', ['route' => 'app_teamer_profile_availabilities'])
->setLinkAttributes([
'title' => 'Meine Verfügbarkeit',
])
;
$dispositionMenu = $menu
->addChild('Meine Einsätze')
->setExtra('icon', 'calendar')
->setExtra('icon_only', false)
;
$dispositionMenu
->addChild('Merkliste', ['route' => 'app_teamer_disposition_watchlist'])
->setLinkAttributes([
'title' => 'Merkliste',
])
;
return $menu;
}
public function createMobileMenu(array $options): ItemInterface
{
$menu = $this->createRootElement('menu menu--mobile');
$menu
->addChild('Profil', ['route' => 'app_teamer_profile_index'])
->setLinkAttributes([
'title' => 'Mein Profil',
'class' => 'icon-link',
])
->setExtra('icon', 'user')
->setExtra('icon_only', false)
;
$this->addLogoutItem($menu, true);
return $menu;
}
}
+13
View File
@@ -12,3 +12,16 @@
{% endif %}
{% endapply %}
{% endblock %}
{% block spanElement %}
<div class="icon-section" role="button">
{% if item.extras.icon is defined %}
{{ icon(item.extras.icon, 'w-5 h-5') }}
{% if item.extras.icon_only is defined and false == item.extras.icon_only %}
<span class="flex-1">{{ item.label|raw }}</span>
{% endif %}
{% else %}
{{ item.label|raw }}
{% endif %}
</div>
{% endblock %}
@@ -1,18 +0,0 @@
<div id="mobilenav"
class="fixed z-50 top-0 left-0 inset-0 pr-16 bg-black/70 -translate-x-full"
{{ stimulus_controller('mobilenav', [], { 'closed': '-translate-x-full' }, { 'mobilenav': '#mobilenav' }) }}
>
<div class="h-screen w-full bg-white">
<div class="flex justify-between px-8 pt-4">
<img src="{{ asset('build/images/logo.svg') }}" alt="" class="block w-auto h-8">
<button type="button"
{{ stimulus_action('mobilenav', 'trigger', null, { 'mode': 'close' }) }}>
{{ icon('close', 'w-8 h-8') }}
</button>
</div>
<div class="w-full h-full p-8 pt-4 overflow-y-scroll">
{% set mobileMenu = knp_menu_get('main', [], { 'mobile': true }) %}
{{ knp_menu_render(mobileMenu, { 'firstClass': null, 'lastClass': null, 'ancestorClass': 'active', 'compressed': true }) }}
</div>
</div>
</div>
+1 -2
View File
@@ -6,8 +6,7 @@
</div>
</a>
<nav class="hidden md:block font-medium">
{% set menu = knp_menu_get('main') %}
{{ knp_menu_render(menu, { 'firstClass': null, 'lastClass': null, 'ancestorClass': 'active', 'compressed': true }) }}
{% block header_menu %}{% endblock %}
</nav>
<button type="button"
class="md:hidden"
@@ -0,0 +1,68 @@
<div class="flex grow flex-col gap-y-5 overflow-y-scroll md:border-r border-gray-200 bg-white px-6">
<nav class="flex flex-1 flex-col">
<ul role="list" class="-mx-2 space-y-1">
<li>
<!-- Current: "bg-gray-50", Default: "hover:bg-gray-50" -->
<a href="#" class="bg-gray-50 block rounded-md py-2 pr-2 pl-10 text-sm leading-6 font-semibold text-gray-700">Dashboard</a>
</li>
<li>
<div>
<button type="button" class="hover:bg-gray-50 flex items-center w-full text-left rounded-md p-2 gap-x-3 text-sm leading-6 font-semibold text-gray-700" aria-controls="sub-menu-1" aria-expanded="false">
<!-- Expanded: "rotate-90 text-gray-500", Collapsed: "text-gray-400" -->
<svg class="text-gray-400 h-5 w-5 shrink-0" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />
</svg>
Teams
</button>
<!-- Expandable link section, show/hide based on state. -->
<ul class="mt-1 px-2" id="sub-menu-1">
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700">Engineering</a>
</li>
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700">Human Resources</a>
</li>
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700">Customer Success</a>
</li>
</ul>
</div>
</li>
<li>
<div>
<button type="button" class="hover:bg-gray-50 flex items-center w-full text-left rounded-md p-2 gap-x-3 text-sm leading-6 font-semibold text-gray-700" aria-controls="sub-menu-2" aria-expanded="false">
<!-- Expanded: "rotate-90 text-gray-500", Collapsed: "text-gray-400" -->
<svg class="text-gray-400 h-5 w-5 shrink-0" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z" clip-rule="evenodd" />
</svg>
Projects
</button>
<!-- Expandable link section, show/hide based on state. -->
<ul class="mt-1 px-2" id="sub-menu-2">
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700">GraphQL API</a>
</li>
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700">iOS App</a>
</li>
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700">Android App</a>
</li>
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-9 text-sm leading-6 text-gray-700">New Customer Portal</a>
</li>
</ul>
</div>
</li>
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-10 text-sm leading-6 font-semibold text-gray-700">Calendar</a>
</li>
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-10 text-sm leading-6 font-semibold text-gray-700">Documents</a>
</li>
<li>
<a href="#" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-10 text-sm leading-6 font-semibold text-gray-700">Reports</a>
</li>
</ul>
</nav>
</div>
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends 'layout.html.twig' %}
{% extends 'admin/layout.html.twig' %}
{% block content %}
{% endblock %}
+9
View File
@@ -0,0 +1,9 @@
{% extends 'layout.html.twig' %}
{% block header_menu %}
{{ knp_menu_render(knp_menu_get('admin_header'), { 'firstClass': null, 'lastClass': null, 'ancestorClass': 'active', 'compressed': true }) }}
{% endblock %}
{% block mobile_menu %}
{{ knp_menu_render(knp_menu_get('admin_mobile'), { 'firstClass': null, 'lastClass': null, 'ancestorClass': 'active', 'compressed': true }) }}
{% endblock %}
+7 -7
View File
@@ -35,11 +35,11 @@
{%- block form_widget_simple -%}
{%- set type = type|default('text') -%}
{%- if type != 'hidden' -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' mt-2 appearance-none text-slate-900 bg-white rounded-md block w-full px-3 h-10 shadow-sm sm:text-sm focus:outline-none ring-0 focus:ring-0')|trim }) -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' mt-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6')|trim }) -%}
{%- if errors|length -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' border-red-500 placeholder-red-500 focus:border-red-500' }) -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' ring-red-500 placeholder-red-500 focus:ring-red-500' }) -%}
{% else %}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' placeholder:text-slate-400 focus:border-primary' }) -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' placeholder:text-slate-400 focus:ring-primary' }) -%}
{%- endif -%}
{%- if disabled is defined and disabled == true -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' cursor-not-allowed' }) -%}
@@ -52,9 +52,9 @@
{%- endblock form_widget_simple -%}
{%- block textarea_widget -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' mt-2 appearance-none text-slate-900 bg-white rounded-md block w-full px-3 shadow-sm sm:text-sm focus:outline-none ring-0 focus:ring-0')|trim }) -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' mt-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6')|trim }) -%}
{%- if errors|length -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' border-red-500 placeholder-red-500 focus:border-red-500' }) -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' ring-red-500 placeholder-red-500 focus:ring-red-500' }) -%}
{% else %}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' placeholder:text-slate-400 focus:ring-1 focus:ring-primary' }) -%}
{%- endif -%}
@@ -68,9 +68,9 @@
{%- endblock textarea_widget -%}
{%- block choice_widget_collapsed -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' mt-2 appearance-none text-slate-900 bg-white rounded-md block w-full px-3 shadow-sm sm:text-sm focus:outline-none ring-0 focus:ring-0')|trim }) -%}
{%- set attr = attr|merge({'class': (attr.class|default('') ~ ' mt-2 block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 focus:ring-2 focus:ring-inset focus:ring-primary sm:text-sm sm:leading-6')|trim }) -%}
{%- if errors|length -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' border-red-500 placeholder-red-500 focus:border-red-500' }) -%}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' ring-red-500 placeholder-red-500 focus:ring-red-500' }) -%}
{% else %}
{%- set attr = attr|merge({'class': attr.class|default('') ~ ' placeholder:text-slate-400 focus:ring-1 focus:ring-primary' }) -%}
{%- endif -%}
+25 -4
View File
@@ -1,11 +1,32 @@
{% extends 'base.html.twig' %}
{% block body %}
{% block page_header %}{% include '_partials/_page_header.html.twig' %}{% endblock %}
<div class="container py-24">
{% block content %}{% endblock %}
<div class="container grid md:grid-cols-4 gap-8 py-8">
<div class="md:col-span-4">
<img class="h-8 w-auto" src="{{ asset('build/images/logo.svg') }}" alt="My E&amp;P Team">
</div>
{% include '_partials/_sidebar_menu.html.twig' %}
<div class="md:col-span-3">
{% block content %}{% endblock %}
</div>
</div>
{% include '_partials/_ajax_modal.html.twig' %}
{% include '_partials/_confirmation_modal.html.twig' %}
{% include '_partials/_mobile_menu.html.twig' %}
<div id="mobilenav"
class="fixed z-50 top-0 left-0 inset-0 pr-16 bg-black/70 -translate-x-full"
{{ stimulus_controller('mobilenav', [], { 'closed': '-translate-x-full' }, { 'mobilenav': '#mobilenav' }) }}
>
<div class="h-screen w-full bg-white">
<div class="flex justify-between px-8 pt-4">
<img src="{{ asset('build/images/logo.svg') }}" alt="" class="block w-auto h-8">
<button type="button"
{{ stimulus_action('mobilenav', 'trigger', null, { 'mode': 'close' }) }}>
{{ icon('close', 'w-8 h-8') }}
</button>
</div>
<div class="w-full h-full p-8 pt-4 overflow-y-scroll">
{% block mobile_menu %}{% endblock %}
</div>
</div>
</div>
{% endblock %}
+9
View File
@@ -0,0 +1,9 @@
{% extends 'layout.html.twig' %}
{% block header_menu %}
{{ knp_menu_render(knp_menu_get('manager_header'), { 'firstClass': null, 'lastClass': null, 'ancestorClass': 'active', 'compressed': true }) }}
{% endblock %}
{% block mobile_menu %}
{{ knp_menu_render(knp_menu_get('manager_mobile'), { 'firstClass': null, 'lastClass': null, 'ancestorClass': 'active', 'compressed': true }) }}
{% endblock %}
+1 -1
View File
@@ -1,4 +1,4 @@
{% extends 'layout.html.twig' %}
{% extends 'teamer/layout.html.twig' %}
{% block title %}Mein Dashboard{% endblock %}
+13
View File
@@ -0,0 +1,13 @@
{% extends 'layout.html.twig' %}
{% block header_menu %}
{{ knp_menu_render(knp_menu_get('teamer_header'), { 'firstClass': null, 'lastClass': null, 'ancestorClass': 'active', 'compressed': true }) }}
{% endblock %}
{% block main_menu %}
{{ knp_menu_render(knp_menu_get('teamer_main'), { 'firstClass': null, 'lastClass': null, 'ancestorClass': 'active', 'compressed': true }) }}
{% endblock %}
{% block mobile_menu %}
{{ knp_menu_render(knp_menu_get('teamer_mobile'), { 'firstClass': null, 'lastClass': null, 'ancestorClass': 'active', 'compressed': true }) }}
{% endblock %}
+33 -27
View File
@@ -1,4 +1,4 @@
{% extends 'layout.html.twig' %}
{% extends 'teamer/layout.html.twig' %}
{% block title %}Mein Profil{% endblock %}
@@ -17,33 +17,41 @@
{% block content %}
{{ form_start(form) }}
<div {{ stimulus_controller('tabs', {}, { 'buttonActive': 'btn--secondary btn--active' }) }}>
<div {{ stimulus_controller('tabs', {}, { 'buttonActive': 'bg-gray-50' }) }}>
<div class="grid lg:grid-cols-3 gap-y-8 lg:gap-y-0 lg:gap-x-16">
<div class="flex flex-col space-y-2">
<button type="button" class="btn" {{ stimulus_target('tabs', 'button') }} {{ stimulus_action('tabs', 'select', null, { 'tab': 0 }) }}>
Persönliche Daten
</button>
<button type="button" class="btn" {{ stimulus_target('tabs', 'button') }} {{ stimulus_action('tabs', 'select', null, { 'tab': 1 }) }}>
Anschrift/Kontakt
</button>
<button type="button" class="btn" {{ stimulus_target('tabs', 'button') }} {{ stimulus_action('tabs', 'select', null, { 'tab': 2 }) }}>
Bankverbindung
</button>
<button type="button" class="btn" {{ stimulus_target('tabs', 'button') }} {{ stimulus_action('tabs', 'select', null, { 'tab': 3 }) }}>
Sonstiges/Foto
</button>
</div>
<ul role="list" class="-mx-2 space-y-1">
<li>
<button type="button" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-10 w-full text-left text-sm leading-6 font-semibold text-gray-700" {{ stimulus_target('tabs', 'button') }} {{ stimulus_action('tabs', 'select', null, { 'tab': 0 }) }}>
Persönliche Daten
</button>
</li>
<li>
<button type="button" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-10 w-full text-left text-sm leading-6 font-semibold text-gray-700" {{ stimulus_target('tabs', 'button') }} {{ stimulus_action('tabs', 'select', null, { 'tab': 1 }) }}>
Anschrift/Kontakt
</button>
</li>
<li>
<button type="button" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-10 w-full text-left text-sm leading-6 font-semibold text-gray-700" {{ stimulus_target('tabs', 'button') }} {{ stimulus_action('tabs', 'select', null, { 'tab': 2 }) }}>
Bankverbindung
</button>
</li>
<li>
<button type="button" class="hover:bg-gray-50 block rounded-md py-2 pr-2 pl-10 w-full text-left text-sm leading-6 font-semibold text-gray-700" {{ stimulus_target('tabs', 'button') }} {{ stimulus_action('tabs', 'select', null, { 'tab': 3 }) }}>
Sonstiges/Foto
</button>
</li>
</ul>
<div class="lg:col-span-2">
{% if not form.vars.valid %}
<div class="max-w-screen-md mx-auto border border-red-500 rounded-md p-4 text-red-500 mb-8">
<div class="border border-red-500 rounded-md p-4 text-red-500 mb-8">
{{ _self.formErrors(form) }}
{{ _self.formErrors(form.address) }}
{{ _self.formErrors(form.communication) }}
{{ _self.formErrors(form.bankAccount) }}
</div>
{% elseif errors|length > 0 %}
<div class="max-w-screen-md mx-auto border border-red-500 rounded-md p-4 text-red-500 mb-8">
<div class="border border-red-500 rounded-md p-4 text-red-500 mb-8">
<ul>
{% for error in errors %}
<li>
@@ -53,7 +61,7 @@
</ul>
</div>
{% endif %}
<div class="pb-8 max-w-screen-md mx-auto" {{ stimulus_target('tabs', 'tab') }}>
<div class="pb-8" {{ stimulus_target('tabs', 'tab') }}>
<h3 class="text-xl font-bold pb-2">
Persönliche Daten
</h3>
@@ -68,7 +76,7 @@
</div>
</div>
<div class="pb-8 max-w-screen-md mx-auto" {{ stimulus_target('tabs', 'tab') }}>
<div class="pb-8" {{ stimulus_target('tabs', 'tab') }}>
<h3 class="text-xl font-bold pb-2">
Anschrift
</h3>
@@ -88,7 +96,7 @@
</div>
</div>
<div class="pb-8 max-w-screen-md mx-auto" {{ stimulus_target('tabs', 'tab') }}>
<div class="pb-8" {{ stimulus_target('tabs', 'tab') }}>
<h3 class="text-xl font-bold pb-2">
Bankverbindung
</h3>
@@ -100,7 +108,7 @@
</div>
</div>
<div class="pb-8 max-w-screen-md mx-auto" {{ stimulus_target('tabs', 'tab') }}>
<div class="pb-8" {{ stimulus_target('tabs', 'tab') }}>
<h3 class="text-xl font-bold pb-2">
Sonstiges
</h3>
@@ -133,11 +141,9 @@
</div>
</div>
<div class="max-w-screen-md mx-auto">
<button type="submit" class="btn">
Aktualisieren
</button>
</div>
<button type="submit" class="btn">
Aktualisieren
</button>
</div>
</div>