feat: allow to remove users

This commit is contained in:
2026-10-06 11:03:25 +01:00
parent 0637ff80cb
commit c3d4a325a0
10 changed files with 557 additions and 9 deletions
+33
View File
@@ -97,5 +97,38 @@
</form>
</section>
{% endif %}
<section class="panel" id="swap-requests">
<h3>Pedidos de troca</h3>
<p class="muted">Um administrador pode atribuir o turno a outra pessoa, mesmo que essa pessoa não entre na aplicação. Só se aplica se quem pediu a troca continuar a ser o titular do turno.</p>
<ul class="link-list">
{% for item in swap_requests %}
<li>
<div>
<strong>{{ item.assignment.date|dia }}</strong> · {{ item.assignment.schedule.name }}
— pedido por {{ item.requester.name }}
{% if item.target_user %}para {{ item.target_user.name }}{% endif %}
{% if item.accepted_by %}, aceite por {{ item.accepted_by.name }}{% endif %}
{% if item.message %}<br><span class="muted">“{{ item.message }}”</span>{% endif %}
</div>
<form method="post" action="/admin/schedules/{{ schedule.id }}/swaps/{{ item.id }}/assign" class="inline-form">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="year" value="{{ year }}"><input type="hidden" name="month" value="{{ month }}">
<select name="user_id" required>
<option value="">Atribuir a…</option>
{% for person in users %}
{% if person.id != item.requester_id %}
<option value="{{ person.id }}" {% if person.id == (item.accepted_by_id or item.target_user_id) %}selected{% endif %}>{{ person.name }}</option>
{% endif %}
{% endfor %}
</select>
<button class="secondary small" type="submit">Atribuir turno</button>
</form>
</li>
{% else %}
<li class="muted">Não há pedidos de troca nesta escala.</li>
{% endfor %}
</ul>
</section>
</div>
{% endblock %}
+1 -1
View File
@@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block content %}
<div class="page-head"><div><h1>Escalas</h1><p class="muted">Uma página por tipo de escala. A escala da noite é fixa e repete todos os meses; o almoço de sábado e o de domingo são rotações independentes. Os turnos já gerados não são reescritos quando uma rotação muda.</p></div></div>
<div class="page-head"><div><h1>Escalas</h1></div></div>
<div class="stack gap">
{% for card in cards %}
{% set schedule = card.schedule %}
+31
View File
@@ -0,0 +1,31 @@
{% extends "base.html" %}
{% block title %}Remover {{ person.name }} · {{ settings.app_name }}{% endblock %}
{% block content %}
<div class="page-head">
<div>
<p class="eyebrow"><a href="/admin/users">Pessoas</a></p>
<h1>Remover pessoa</h1>
<p class="muted">Isto é definitivo e não pode ser desfeito.</p>
</div>
</div>
<section class="panel">
<h2>{{ person.name }}</h2>
<p>{% if person.can_login %}@{{ person.username }}{% else %}Sem login, apenas aparece na escala.{% endif %}</p>
<p class="muted">Só é possível remover quem ainda não tem turnos atribuídos. Primeiro transfira os turnos desta pessoa para outras; assim o registo de quem trabalhou cada data mantém-se.</p>
<p class="muted">Ao remover, acontece o seguinte:</p>
<ul class="link-list">
<li>{{ impact.rotation }} posição(ões) saem das rotações.</li>
{% if impact.pattern_days %}<li>{{ impact.pattern_days }} dia(s) do padrão de noites ficam por definir.</li>{% endif %}
{% if impact.requests %}<li>{{ impact.requests }} pedido(s) de troca em aberto são encerrados.</li>{% endif %}
<li>O histórico de e-mails é mantido, sem ligação a esta pessoa.</li>
</ul>
<p class="muted">Se só quiser que esta pessoa deixe de receber turnos, desative-a em vez de a remover.</p>
<div class="actions">
<form method="post" action="/admin/users/{{ person.id }}/delete">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<button class="danger" type="submit">Remover definitivamente</button>
</form>
<a class="button secondary" href="/admin/users">Cancelar</a>
</div>
</section>
{% endblock %}
+1
View File
@@ -41,6 +41,7 @@
<label class="check"><input type="checkbox" name="is_active" {% if person.is_active %}checked{% endif %}> Ativa</label>
<label class="check"><input type="checkbox" name="is_admin" {% if person.is_admin %}checked{% endif %}> Administrador</label>
<div><button class="primary" type="submit">Guardar</button></div>
{% if person.id in removable_ids %}<div><a class="button danger" href="/admin/users/{{ person.id }}/delete">Remover</a></div>{% endif %}
</form>
</details>
{% endfor %}
+1 -1
View File
@@ -1,7 +1,7 @@
{% extends "base.html" %}
{% block content %}
<div class="page-head">
<div><h1>Pedidos de troca</h1><p class="muted">Qualquer pessoa pode assumir um turno aberto ou aceitar um pedido enviado diretamente para si.</p></div>
<div><h1>Pedidos de troca</h1></div>
</div>
<div class="stack gap-lg">