{# templates/team/index.html.twig #} {% extends 'base.html.twig' %} {% block title %}Team{% endblock %} {% block body %} <div class="crud-page"> <div class="crud-page__header"> <h1 class="crud-page__title">Team</h1> <button class="btn btn-primary" id="team-invite-btn">Neuer Benutzer</button> </div> <div class="crud-tabs"> <button class="crud-tab crud-tab--active" data-tab="active"> Aktiv ({{ activeUsers|length + pendingInvites|length }}) </button> <button class="crud-tab" data-tab="archived"> Archiviert ({{ archivedUsers|length }}) </button> </div> {# ── Aktive User ──────────────────────────────────────────────────── #} <div class="crud-list" id="team-list" data-tab-panel="active"> {% for au in activeUsers %} <div class="crud-row" id="au-{{ au.id }}" data-id="{{ au.id }}" data-first-name="{{ au.user.firstName|e('html_attr') }}" data-last-name="{{ au.user.lastName|e('html_attr') }}" data-email="{{ au.user.email|e('html_attr') }}" data-note="{{ au.user.note|default('')|e('html_attr') }}" data-role="{{ au.role }}" data-is-self="{{ au.user.id == currentUserId ? '1' : '0' }}"> <div class="crud-row__display"> <div class="crud-row__info"> <span class="crud-row__name">{{ au.user.fullName }}</span> <span class="crud-row__meta">({{ au.roleLabel }})</span> {% if au.user.password is null %} <span class="team-badge team-badge--pending">Einladung ausstehend</span> {% endif %} </div> <div class="crud-row__actions"> <button class="crud-row__btn crud-row__btn--edit" data-action="edit" title="Bearbeiten"> <svg viewBox="0 0 16 16" fill="none"><path d="M11 2l3 3L5 14H2v-3L11 2z" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg> </button> {% if au.user.id != currentUserId %} <button class="crud-row__btn crud-row__btn--delete" data-action="delete" title="Entfernen"> <svg viewBox="0 0 16 16" fill="none"><path d="M3 4h10M6 4V2h4v2M5 4l.5 9h5l.5-9" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg> </button> {% endif %} </div> </div> <div class="crud-row__edit" hidden> <div class="entry-form__grid entry-form__grid--inline"> <label class="entry-form__label">Vorname</label> <div class="entry-form__field"> <input type="text" class="input edit-first-name" value="{{ au.user.firstName }}" /> </div> <label class="entry-form__label">Nachname</label> <div class="entry-form__field"> <input type="text" class="input edit-last-name" value="{{ au.user.lastName }}" /> </div> <label class="entry-form__label">E-Mail</label> <div class="entry-form__field"> <input type="email" class="input edit-email" value="{{ au.user.email }}" /> </div> <label class="entry-form__label">Bemerkung</label> <div class="entry-form__field"> <textarea class="textarea edit-note" rows="2">{{ au.user.note|default('') }}</textarea> </div> <label class="entry-form__label">Rolle</label> <div class="entry-form__field"> <div class="team-role-selector{% if au.user.id == currentUserId and au.isAdmin() %} team-role-selector--disabled{% endif %}"> {% set roleDisabled = (au.user.id == currentUserId and au.isAdmin()) ? 'disabled' : '' %} <label class="team-role-option"> <input type="radio" class="edit-role" name="role-{{ au.id }}" value="tracker" {{ au.role == 'tracker' ? 'checked' : '' }} {{ roleDisabled }} /> <span class="team-role-option__label">Zeiterfasser</span> </label> <label class="team-role-option"> <input type="radio" class="edit-role" name="role-{{ au.id }}" value="member" {{ au.role == 'member' ? 'checked' : '' }} {{ roleDisabled }} /> <span class="team-role-option__label">Standard-Nutzer</span> </label> <label class="team-role-option"> <input type="radio" class="edit-role" name="role-{{ au.id }}" value="admin" {{ au.role == 'admin' ? 'checked' : '' }} {{ roleDisabled }} /> <span class="team-role-option__label">Administrator</span> </label> </div> {% if au.user.id == currentUserId and au.isAdmin() %} <p class="team-role-hint">Eigene Administrator-Rolle kann nicht geändert werden.</p> {% endif %} </div> <div class="entry-form__actions"> <button type="button" class="btn btn-primary" data-action="save">Sichern</button> <button type="button" class="btn btn-secondary" data-action="cancel">Abbrechen</button> </div> </div> </div> </div> {% endfor %} {# ── Ausstehende Einladungen ──────────────────────────────────── #} {% for invite in pendingInvites %} <div class="crud-row" id="invite-{{ invite.id }}"> <div class="crud-row__display"> <div class="crud-row__info"> <span class="crud-row__name">{{ invite.firstName }} {{ invite.lastName }}</span> <span class="crud-row__meta">({{ invite.email }})</span> <span class="team-badge team-badge--pending">Einladung ausstehend</span> </div> <div class="crud-row__actions"> <button class="crud-row__btn crud-row__btn--delete" data-action="delete-invite" data-id="{{ invite.id }}" title="Einladung zurückziehen"> <svg viewBox="0 0 16 16" fill="none"><path d="M3 4h10M6 4V2h4v2M5 4l.5 9h5l.5-9" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg> </button> </div> </div> </div> {% endfor %} {% if activeUsers is empty and pendingInvites is empty %} <div class="crud-list__empty">Noch keine aktiven Teammitglieder.</div> {% endif %} </div> {# ── Archivierte User ─────────────────────────────────────────────── #} <div class="crud-list" id="team-list-archived" data-tab-panel="archived" hidden> {% for au in archivedUsers %} <div class="crud-row crud-row--archived" id="au-{{ au.id }}"> <div class="crud-row__display"> <div class="crud-row__info"> <span class="crud-row__name">{{ au.user.fullName }}</span> <span class="crud-row__meta">({{ au.roleLabel }})</span> </div> <div class="crud-row__actions"> <button class="crud-row__btn crud-row__btn--restore" data-action="unarchive" title="Wiederherstellen"> <svg viewBox="0 0 16 16" fill="none"><path d="M2 8a6 6 0 1 1 1.5 3.5" stroke="currentColor" stroke-width="1.3" stroke-linecap="round"/><path d="M2 13V9h4" stroke="currentColor" stroke-width="1.3" stroke-linecap="round" stroke-linejoin="round"/></svg> </button> </div> </div> </div> {% else %} <div class="crud-list__empty">Keine archivierten Teammitglieder.</div> {% endfor %} </div> </div> {# ── Einlade-Modal ────────────────────────────────────────────────────────────── #} <div class="modal-overlay" id="team-modal" hidden> <div class="modal-card"> <div class="modal-card__header"> <h2 class="modal-card__title">Neuen Benutzer einladen</h2> <button class="modal-card__close" id="team-modal-close" type="button"> <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"> <line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/> </svg> </button> </div> <div id="team-modal-errors" class="form-errors" hidden></div> <div class="modal-card__body"> <div class="form-row"> <div class="form-field"> <label class="form-field__label" for="inv-firstName">Vorname</label> <input class="input" type="text" id="inv-firstName" autocomplete="off" /> </div> <div class="form-field"> <label class="form-field__label" for="inv-lastName">Nachname</label> <input class="input" type="text" id="inv-lastName" autocomplete="off" /> </div> </div> <div class="form-field"> <label class="form-field__label" for="inv-email">E-Mail</label> <input class="input" type="email" id="inv-email" autocomplete="off" /> </div> <div class="form-field"> <label class="form-field__label">Rolle</label> <div class="team-role-selector"> <label class="team-role-option"> <input type="radio" name="inv-role" value="tracker" /> <span class="team-role-option__label">Zeiterfasser</span> </label> <label class="team-role-option"> <input type="radio" name="inv-role" value="member" checked /> <span class="team-role-option__label">Standard-Nutzer</span> </label> <label class="team-role-option"> <input type="radio" name="inv-role" value="admin" /> <span class="team-role-option__label">Administrator</span> </label> </div> </div> </div> <div class="modal-card__footer"> <button class="btn btn-secondary" id="team-modal-cancel" type="button">Abbrechen</button> <button class="btn btn-cta" id="team-modal-submit" type="button">Einladung senden</button> </div> </div> </div> {% endblock %} {% block javascripts %} {{ parent() }} {{ encore_entry_script_tags('team') }} {% endblock %}