feat: submission confirmation and payment locking
This commit is contained in:
@@ -34,8 +34,8 @@
|
||||
<div class="space-y-6">
|
||||
{% for claim in claims %}
|
||||
<article class="rounded-3xl bg-white shadow-sm ring-1 ring-gray-100">
|
||||
<div class="flex flex-col gap-4 border-b border-gray-100 px-6 py-5 md:flex-row md:items-center md:justify-between">
|
||||
<div class="space-y-2">
|
||||
<div class="flex flex-col gap-4 border-b border-gray-100 px-6 py-5 lg:flex-row lg:justify-between">
|
||||
<div class="space-y-3">
|
||||
<div class="flex flex-wrap items-center gap-3 text-sm text-gray-500">
|
||||
<span class="rounded-full bg-slate-100 px-3 py-1 font-semibold text-gray-700">
|
||||
{{ claim.amount }} {{ claim.currency }}
|
||||
@@ -47,25 +47,67 @@
|
||||
{% endif %}
|
||||
<span class="text-xs text-gray-400">Skapad {{ claim.created_at|date:"Y-m-d H:i" }}</span>
|
||||
</div>
|
||||
<h2 class="text-xl font-semibold text-gray-900">{{ claim.full_name }}</h2>
|
||||
<p class="text-sm text-gray-600">
|
||||
{{ claim.email }} · Konto: {{ claim.account_number }}<br>
|
||||
{% if claim.submitted_by %}
|
||||
<span class="text-xs uppercase tracking-wide text-green-600">Inloggad användare: {{ claim.submitted_by.get_username }}</span>
|
||||
{% else %}
|
||||
<span class="text-xs uppercase tracking-wide text-gray-500">Inskickad av gäst</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
<div class="space-y-1">
|
||||
<p class="text-sm font-semibold uppercase tracking-wide text-gray-500">Person</p>
|
||||
<h2 class="text-2xl font-semibold text-gray-900">{{ claim.full_name }}</h2>
|
||||
<p class="text-sm text-gray-600">
|
||||
{{ claim.email }} · Konto: <span class="font-mono text-gray-900">{{ claim.account_number }}</span><br>
|
||||
{% if claim.submitted_by %}
|
||||
<span class="text-xs uppercase tracking-wide text-green-600">Inloggad användare: {{ claim.submitted_by.get_username }}</span>
|
||||
{% else %}
|
||||
<span class="text-xs uppercase tracking-wide text-gray-500">Inskickad av gäst</span>
|
||||
{% endif %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col items-start gap-2 text-sm md:items-end">
|
||||
<div class="flex flex-col items-start gap-2 text-sm lg:items-end">
|
||||
<span class="rounded-full px-4 py-2 text-sm font-semibold {% if claim.status == 'approved' %}bg-green-50 text-green-700 border border-green-200{% elif claim.status == 'rejected' %}bg-rose-50 text-rose-700 border border-rose-200{% else %}bg-amber-50 text-amber-800 border border-amber-200{% endif %}">
|
||||
{{ claim.get_status_display }}
|
||||
</span>
|
||||
{% if claim.decision_note %}
|
||||
<p class="text-xs text-gray-500">Kommentar: {{ claim.decision_note }}</p>
|
||||
{% endif %}
|
||||
{% if payments_enabled and claim.status == 'approved' %}
|
||||
{% if claim.is_paid %}
|
||||
<span class="rounded-full bg-emerald-100 px-3 py-1 text-xs font-semibold text-emerald-800">
|
||||
Betald {{ claim.paid_at|date:"Y-m-d H:i" }}
|
||||
{% if claim.paid_by %}av {{ claim.paid_by.get_username }}{% endif %}
|
||||
</span>
|
||||
{% else %}
|
||||
<span class="text-xs text-gray-500">Ej markerad som betald</span>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if claim.status == 'approved' %}
|
||||
<div class="mx-6 mt-4 rounded-2xl border border-green-100 bg-green-50 px-6 py-4 text-sm text-green-900">
|
||||
<div class="flex flex-col gap-3 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
<p class="text-xs font-semibold uppercase tracking-wide text-green-600">Sammanfattning</p>
|
||||
<p class="text-lg font-semibold text-green-900">{{ claim.full_name }}</p>
|
||||
<p class="text-sm text-green-800">Belopp: <strong>{{ claim.amount }} {{ claim.currency }}</strong> · Konto: <span class="font-mono">{{ claim.account_number }}</span></p>
|
||||
</div>
|
||||
{% if payments_enabled %}
|
||||
{% if claim.is_paid %}
|
||||
<p class="text-xs uppercase tracking-wide text-emerald-600">Markerad som betald</p>
|
||||
{% else %}
|
||||
<form method="post" onsubmit="return confirm('Är du säker på att du har lagt upp betalningen? Markera endast som betald om beloppet skickas till banken.');">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action_type" value="payment">
|
||||
<input type="hidden" name="payment_claim_id" value="{{ claim.id }}">
|
||||
<button type="submit" class="inline-flex items-center gap-2 rounded-full bg-emerald-600 px-4 py-2 text-xs font-semibold uppercase tracking-wide text-white transition hover:bg-emerald-700">
|
||||
Betala
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p class="text-xs text-green-700">Intern betalningshantering är av – markera betalning i ekonomisystemet.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<div class="grid gap-6 px-6 py-6 lg:grid-cols-3">
|
||||
<div class="lg:col-span-2">
|
||||
<p class="text-sm font-semibold text-gray-500">Beskrivning</p>
|
||||
@@ -110,24 +152,31 @@
|
||||
</details>
|
||||
|
||||
{% if can_change %}
|
||||
<form method="post" class="space-y-3">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="claim_id" value="{{ claim.id }}">
|
||||
{% if claim.is_paid %}
|
||||
<p class="rounded-lg bg-slate-100 px-3 py-2 text-xs text-slate-600">
|
||||
Utlägget är markerat som betalt. Ändringar av beslut/kommentar är låsta.
|
||||
</p>
|
||||
{% else %}
|
||||
<form method="post" class="space-y-3">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="claim_id" value="{{ claim.id }}">
|
||||
|
||||
<label class="block text-sm font-medium text-gray-700">Åtgärd</label>
|
||||
<select name="action" class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-gray-900 focus:border-brand-600 focus:outline-none focus:ring-2 focus:ring-brand-600">
|
||||
{% for value, label in decision_choices %}
|
||||
<option value="{{ value }}">{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<label class="block text-sm font-medium text-gray-700">Åtgärd</label>
|
||||
<select name="action" class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-gray-900 focus:border-brand-600">
|
||||
{% for value, label in decision_choices %}
|
||||
<option value="{{ value }}">{{ label }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<label class="block text-sm font-medium text-gray-700">Kommentar</label>
|
||||
<textarea name="decision_note" rows="3" class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-gray-900 focus:border-brand-600 focus:outline-none focus:ring-2 focus:ring-brand-600">{{ claim.decision_note }}</textarea>
|
||||
<label class="block text-sm font-medium text-gray-700">Kommentar</label>
|
||||
<textarea name="decision_note" rows="3" class="w-full rounded-lg border border-gray-300 px-3 py-2 text-sm text-gray-900 focus:border-brand-600">{{ claim.decision_note }}</textarea>
|
||||
|
||||
<button type="submit" class="w-full rounded-full bg-brand-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-brand-700">
|
||||
Uppdatera beslut
|
||||
</button>
|
||||
</form>
|
||||
<input type="hidden" name="action_type" value="decision">
|
||||
<button type="submit" class="w-full rounded-full bg-brand-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-brand-700">
|
||||
Uppdatera beslut
|
||||
</button>
|
||||
</form>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,21 +24,27 @@
|
||||
<body class="min-h-screen bg-slate-50 text-gray-900">
|
||||
<header class="bg-white shadow-sm">
|
||||
<div class="mx-auto flex max-w-6xl items-center justify-between px-4 py-4">
|
||||
<div class="text-lg font-semibold text-gray-900">
|
||||
claims-system
|
||||
</div>
|
||||
<nav class="flex flex-wrap items-center gap-4 text-sm font-medium text-gray-600">
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:submit' %}">Skicka utlägg</a>
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:admin-list' %}">Admin</a>
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:export' %}">Export</a>
|
||||
<a href="{% url 'claims:submit' %}" class="text-lg font-semibold text-gray-900 hover:text-brand-700">claims-system</a>
|
||||
<nav class="flex flex-wrap items-center gap-3 text-sm font-medium text-gray-600">
|
||||
<div class="flex items-center gap-2">
|
||||
<span class="rounded-full border border-gray-200 bg-gray-50 px-3 py-1 text-xs uppercase tracking-wide text-gray-500">Offentlig</span>
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:submit' %}">Skicka utlägg</a>
|
||||
</div>
|
||||
{% if user.is_authenticated %}
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
<span class="rounded-full border border-gray-200 bg-gray-50 px-3 py-1 text-xs uppercase tracking-wide text-gray-500">Intern</span>
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:admin-list' %}">Utläggslista</a>
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:my-claims' %}">Mina utlägg</a>
|
||||
{% if perms.auth.view_user %}
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:user-manage' %}">Användare</a>
|
||||
{% endif %}
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:export' %}">Export</a>
|
||||
{% if user.is_staff %}
|
||||
<a class="hover:text-gray-900" href="{% url 'admin:index' %}">Django admin</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% if user.is_authenticated %}
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:my-claims' %}">Mina utlägg</a>
|
||||
{% if perms.auth.view_user %}
|
||||
<a class="hover:text-gray-900" href="{% url 'claims:user-manage' %}">Användare</a>
|
||||
{% endif %}
|
||||
{% if user.is_staff %}
|
||||
<a class="hover:text-gray-900" href="{% url 'admin:index' %}">Kontohantering</a>
|
||||
{% endif %}
|
||||
<span class="hidden text-xs text-gray-400 sm:inline">|</span>
|
||||
<span class="text-xs text-gray-500">Inloggad som {{ user.get_username }}</span>
|
||||
<form action="{% url 'logout' %}" method="post" class="inline">
|
||||
|
||||
@@ -3,61 +3,80 @@
|
||||
{% block title %}Mina utlägg{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Mina utlägg</h1>
|
||||
<p>Här ser du status för de utlägg du skickat in när du varit inloggad.</p>
|
||||
<section class="space-y-6 py-6">
|
||||
<header class="max-w-3xl">
|
||||
<p class="text-sm font-semibold uppercase tracking-wide text-brand-600">Översikt</p>
|
||||
<h1 class="text-3xl font-semibold text-gray-900">Mina utlägg</h1>
|
||||
<p class="mt-2 text-sm text-gray-600">Här ser du alla utlägg du skickat in när du varit inloggad, inklusive status, kvitton och loggar.</p>
|
||||
</header>
|
||||
|
||||
{% if claims %}
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Skickad</th>
|
||||
<th>Beskrivning</th>
|
||||
<th>Belopp</th>
|
||||
<th>Projekt</th>
|
||||
<th>Status</th>
|
||||
<th>Kvitto</th>
|
||||
<th>Logg</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<div class="grid gap-6">
|
||||
{% for claim in claims %}
|
||||
<tr>
|
||||
<td>{{ claim.created_at|date:"Y-m-d H:i" }}</td>
|
||||
<td>{{ claim.description|linebreaksbr }}</td>
|
||||
<td>{{ claim.amount }} {{ claim.currency }}</td>
|
||||
<td>{{ claim.project|default:"-" }}</td>
|
||||
<td>{{ claim.get_status_display }}</td>
|
||||
<td>
|
||||
{% if claim.receipt %}
|
||||
<a href="{{ claim.receipt.url }}" target="_blank" rel="noopener">Visa fil</a>
|
||||
{% else %}
|
||||
–
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>
|
||||
<details>
|
||||
<summary>Visa logg</summary>
|
||||
<ul>
|
||||
{% for log in claim.logs.all %}
|
||||
<li>
|
||||
{{ log.created_at|date:"Y-m-d H:i" }} –
|
||||
{{ log.get_action_display }}
|
||||
{% if log.from_status %} ({{ log.get_from_status_display }} → {{ log.get_to_status_display }}){% endif %}
|
||||
{% if log.note %}
|
||||
– "{{ log.note }}"
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li>Ingen logg än.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</details>
|
||||
</td>
|
||||
</tr>
|
||||
<article class="rounded-3xl bg-white px-6 py-6 shadow-sm ring-1 ring-gray-100">
|
||||
<div class="flex flex-col gap-4 border-b border-gray-100 pb-4 lg:flex-row lg:items-center lg:justify-between">
|
||||
<div>
|
||||
<p class="text-xs uppercase tracking-wide text-gray-500">Skickad {{ claim.created_at|date:"Y-m-d H:i" }}</p>
|
||||
<h2 class="mt-1 text-2xl font-semibold text-gray-900">{{ claim.description|default:"Utlägg" }}</h2>
|
||||
<p class="mt-2 text-sm text-gray-600">
|
||||
Belopp: <strong>{{ claim.amount }} {{ claim.currency }}</strong><br>
|
||||
Projekt: {{ claim.project|default:"-" }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-start gap-2 text-sm lg:items-end">
|
||||
<span class="rounded-full px-4 py-2 text-sm font-semibold {% if claim.status == 'approved' %}bg-green-50 text-green-700 border border-green-200{% elif claim.status == 'rejected' %}bg-rose-50 text-rose-700 border border-rose-200{% else %}bg-amber-50 text-amber-800 border border-amber-200{% endif %}">
|
||||
{{ claim.get_status_display }}
|
||||
</span>
|
||||
{% if claim.paid_at %}
|
||||
<span class="rounded-full bg-emerald-50 px-3 py-1 text-xs font-semibold text-emerald-800">
|
||||
Betald {{ claim.paid_at|date:"Y-m-d" }}
|
||||
</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-4 grid gap-4 lg:grid-cols-[2fr,1fr]">
|
||||
<div>
|
||||
<p class="text-sm font-semibold text-gray-500">Detaljer</p>
|
||||
<p class="mt-2 whitespace-pre-wrap text-gray-800">{{ claim.description }}</p>
|
||||
</div>
|
||||
<div class="rounded-2xl bg-slate-50 p-4 text-sm text-gray-600">
|
||||
<p class="font-semibold text-gray-800">Kvitto</p>
|
||||
{% if claim.receipt %}
|
||||
<a class="mt-2 inline-flex items-center gap-2 text-brand-600 hover:text-brand-700" href="{{ claim.receipt.url }}" target="_blank" rel="noopener">
|
||||
Visa fil
|
||||
</a>
|
||||
{% else %}
|
||||
<p class="mt-2 text-xs text-gray-400">Inget kvitto bifogat.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
<details class="mt-4 rounded-2xl border border-dashed border-gray-200 bg-gray-50 p-4 text-sm text-gray-700">
|
||||
<summary class="cursor-pointer select-none text-sm font-semibold text-gray-800">Visa logg</summary>
|
||||
<ul class="mt-3 space-y-2 text-sm text-gray-600">
|
||||
{% for log in claim.logs.all %}
|
||||
<li class="rounded-lg bg-white px-3 py-2 shadow-sm">
|
||||
<p class="font-semibold text-gray-900">{{ log.get_action_display }}</p>
|
||||
<p class="text-xs text-gray-500">{{ log.created_at|date:"Y-m-d H:i" }}</p>
|
||||
{% if log.from_status %}
|
||||
<p class="text-xs text-gray-500">Status: {{ log.get_from_status_display }} → {{ log.get_to_status_display }}</p>
|
||||
{% endif %}
|
||||
{% if log.note %}
|
||||
<p class="mt-1 text-xs text-gray-600">"{{ log.note }}"</p>
|
||||
{% endif %}
|
||||
</li>
|
||||
{% empty %}
|
||||
<li class="text-xs text-gray-400">Ingen logg än.</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</details>
|
||||
</article>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% else %}
|
||||
<p>Du har inte skickat in några utlägg ännu eller så gjordes de utan inloggning.</p>
|
||||
<div class="rounded-3xl border border-dashed border-gray-200 bg-white px-6 py-10 text-center text-gray-500">
|
||||
<p class="text-lg font-semibold text-gray-900">Inga utlägg ännu</p>
|
||||
<p class="mt-2 text-sm">När du skickar in utlägg medan du är inloggad dyker de upp här.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
26
claims/templates/claims/submit_success.html
Normal file
26
claims/templates/claims/submit_success.html
Normal file
@@ -0,0 +1,26 @@
|
||||
{% extends "claims/base.html" %}
|
||||
|
||||
{% block title %}Tack för ditt utlägg{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="flex min-h-[60vh] items-center justify-center py-10">
|
||||
<div class="w-full max-w-lg rounded-3xl bg-white px-8 py-10 text-center shadow-lg ring-1 ring-gray-100">
|
||||
<p class="text-sm font-semibold uppercase tracking-wide text-brand-600">Tack!</p>
|
||||
<h1 class="mt-2 text-3xl font-semibold text-gray-900">Utlägget är skickat</h1>
|
||||
<p class="mt-3 text-sm text-gray-600">
|
||||
Vi har tagit emot underlaget. Om du har fler kvitton kan du fylla i ett nytt formulär direkt,
|
||||
annars kan du logga in för att följa statusen.
|
||||
</p>
|
||||
<div class="mt-6 flex flex-col gap-3 sm:flex-row sm:justify-center">
|
||||
<a href="{% url 'claims:submit' %}"
|
||||
class="inline-flex items-center justify-center rounded-full bg-brand-600 px-5 py-3 text-sm font-semibold text-white transition hover:bg-brand-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-600 focus-visible:ring-offset-2">
|
||||
Skicka nytt utlägg
|
||||
</a>
|
||||
<a href="{% url 'login' %}"
|
||||
class="inline-flex items-center justify-center rounded-full border border-gray-200 px-5 py-3 text-sm font-semibold text-gray-700 transition hover:bg-gray-50 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-600 focus-visible:ring-offset-2">
|
||||
Logga in
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
@@ -3,76 +3,175 @@
|
||||
{% block title %}Användarhantering{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<h1>Användare & behörigheter</h1>
|
||||
<p>Skapa nya konton, underhåll behörigheter och ta bort användare kopplat till utläggssystemet.</p>
|
||||
<section class="space-y-10 py-8">
|
||||
<header class="max-w-3xl">
|
||||
<p class="text-sm font-semibold uppercase tracking-wide text-brand-600">Konton & behörigheter</p>
|
||||
<h1 class="mt-2 text-3xl font-semibold text-gray-900">Hantera användare</h1>
|
||||
<p class="mt-3 text-sm text-gray-600">
|
||||
Skapa nya konton, justera rättigheter för claim-flödet och ta bort användare som inte längre ska ha åtkomst.
|
||||
</p>
|
||||
<div class="mt-4 rounded-2xl border border-dashed border-amber-200 bg-amber-50 px-4 py-3 text-xs text-amber-800">
|
||||
Notis: denna sida styr direkta behörigheter. Rättigheter via grupper eller superuser-status gäller även om kryssrutorna avmarkeras.
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<p><small>Notis: sidan hanterar direkta behörigheter. Behörigheter via grupper eller superuser-status gäller även om kryssrutorna avmarkeras.</small></p>
|
||||
|
||||
<section>
|
||||
<h2>Skapa ny användare</h2>
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="create">
|
||||
{{ create_form.as_p }}
|
||||
<button type="submit">Skapa användare</button>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<hr>
|
||||
|
||||
<section>
|
||||
<h2>Befintliga användare</h2>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Användare</th>
|
||||
<th>Namn</th>
|
||||
<th>E-post</th>
|
||||
<th>Behörigheter</th>
|
||||
<th>Ta bort</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for row in user_rows %}
|
||||
{% with user=row.user %}
|
||||
<tr>
|
||||
<td>
|
||||
{{ user.username }}
|
||||
{% if user.is_superuser %}<span title="Superuser">⭐</span>{% endif %}
|
||||
</td>
|
||||
<td>{{ user.get_full_name|default:"-" }}</td>
|
||||
<td>{{ user.email|default:"-" }}</td>
|
||||
<td>
|
||||
{% with form=row.permission_form %}
|
||||
<form method="post">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="update">
|
||||
{{ form.user_id }}
|
||||
<label>{{ form.is_staff }} {{ form.is_staff.label }}</label><br>
|
||||
<label>{{ form.grant_view }} {{ form.grant_view.label }}</label><br>
|
||||
<label>{{ form.grant_change }} {{ form.grant_change.label }}</label><br>
|
||||
<button type="submit">Spara</button>
|
||||
</form>
|
||||
{% endwith %}
|
||||
</td>
|
||||
<td>
|
||||
{% if row.delete_form %}
|
||||
<form method="post" onsubmit="return confirm('Ta bort {{ user.username }}?');">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="delete">
|
||||
{{ row.delete_form.user_id }}
|
||||
<button type="submit">Ta bort</button>
|
||||
</form>
|
||||
<div class="grid gap-8 lg:grid-cols-2">
|
||||
<div class="rounded-3xl bg-white px-6 py-8 shadow-sm ring-1 ring-gray-100">
|
||||
<div class="border-b border-gray-100 pb-4">
|
||||
<p class="text-sm font-semibold uppercase tracking-wide text-gray-500">Nytt konto</p>
|
||||
<h2 class="mt-1 text-2xl font-semibold text-gray-900">Skapa användare</h2>
|
||||
<p class="mt-1 text-sm text-gray-600">Lösenordet valideras mot Djangos standardregler.</p>
|
||||
</div>
|
||||
<form method="post" class="mt-6 space-y-4">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="create">
|
||||
{% for field in create_form %}
|
||||
<div>
|
||||
<label class="text-sm font-medium text-gray-700" for="{{ field.id_for_label }}">{{ field.label }}</label>
|
||||
{% if field.is_hidden %}
|
||||
{{ field }}
|
||||
{% else %}
|
||||
<em>—</em>
|
||||
<input
|
||||
type="{{ field.field.widget.input_type|default:'text' }}"
|
||||
name="{{ field.html_name }}"
|
||||
id="{{ field.id_for_label }}"
|
||||
value="{{ field.value|default_if_none:'' }}"
|
||||
class="mt-1 block w-full rounded-xl border border-gray-200 px-3 py-2 text-sm shadow-sm focus:border-brand-600 focus:outline-none focus:ring-2 focus:ring-brand-600"
|
||||
{% if field.field.required %}required{% endif %}
|
||||
{% if field.field.widget.attrs.autocomplete %}autocomplete="{{ field.field.widget.attrs.autocomplete }}"{% endif %}
|
||||
{% if field.field.widget.attrs.autofocus %}autofocus{% endif %}
|
||||
/>
|
||||
{% endif %}
|
||||
</td>
|
||||
</tr>
|
||||
{% if field.help_text %}
|
||||
<p class="mt-1 text-xs text-gray-500">{{ field.help_text }}</p>
|
||||
{% endif %}
|
||||
{% for error in field.errors %}
|
||||
<p class="mt-1 text-sm text-rose-600">{{ error }}</p>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endfor %}
|
||||
<button type="submit" class="w-full rounded-2xl bg-brand-600 px-4 py-3 text-sm font-semibold text-white transition hover:bg-brand-700 focus:outline-none focus-visible:ring-2 focus-visible:ring-brand-600 focus-visible:ring-offset-2">
|
||||
Skapa användare
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="rounded-3xl bg-slate-900 px-6 py-8 text-slate-100 shadow-sm ring-1 ring-slate-800">
|
||||
<h3 class="text-2xl font-semibold">Tips för kontohantering</h3>
|
||||
<ul class="mt-4 space-y-3 text-sm text-slate-300 break-words">
|
||||
<li class="flex items-start gap-3">
|
||||
<span class="mt-1 h-2 w-2 rounded-full bg-brand-400"></span>
|
||||
<span class="min-w-0">Lägg användare i grupper via Django admin om flera personer ska dela samma roll.</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<span class="mt-1 h-2 w-2 rounded-full bg-brand-400"></span>
|
||||
<span class="min-w-0">
|
||||
Behörigheterna <code class="break-normal rounded bg-slate-800 px-2 py-1 text-xs">claims.view_claim</code>
|
||||
och <code class="break-normal rounded bg-slate-800 px-2 py-1 text-xs">claims.change_claim</code>
|
||||
styr åtkomst till adminvyn respektive beslutsflödet.
|
||||
</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<span class="mt-1 h-2 w-2 rounded-full bg-brand-400"></span>
|
||||
<span class="min-w-0">En markerad <strong>Admin/staff</strong>-användare kan nå Django admin och skapa projekt, exportflöden m.m.</span>
|
||||
</li>
|
||||
<li class="flex items-start gap-3">
|
||||
<span class="mt-1 h-2 w-2 rounded-full bg-brand-400"></span>
|
||||
<span class="min-w-0">Ta bara bort konton du är säker på – historik försvinner inte, men personen tappar all åtkomst.</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class="space-y-6">
|
||||
<div>
|
||||
<p class="text-sm font-semibold uppercase tracking-wide text-gray-500">Befintliga användare</p>
|
||||
<h2 class="text-2xl font-semibold text-gray-900">Justera behörigheter</h2>
|
||||
</div>
|
||||
<div class="space-y-4">
|
||||
{% for row in user_rows %}
|
||||
{% with user=row.user form=row.permission_form delete_form=row.delete_form %}
|
||||
<article class="rounded-3xl bg-white px-6 py-6 shadow-sm ring-1 ring-gray-100">
|
||||
<div class="flex flex-col gap-4 border-b border-gray-100 pb-4 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
<div class="flex items-center gap-3">
|
||||
<h3 class="text-xl font-semibold text-gray-900">{{ user.username }}</h3>
|
||||
{% if user.is_superuser %}
|
||||
<span class="rounded-full bg-emerald-50 px-3 py-1 text-xs font-semibold uppercase tracking-wide text-emerald-700">Superuser</span>
|
||||
{% endif %}
|
||||
</div>
|
||||
<p class="text-sm text-gray-600">
|
||||
{{ user.get_full_name|default:"Saknar namn" }} · {{ user.email|default:"Ingen e-post" }}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-xs uppercase tracking-wide text-gray-400">
|
||||
ID: {{ user.id }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="mt-4 grid gap-6 lg:grid-cols-[2fr,1fr]">
|
||||
<form method="post" class="space-y-4 rounded-2xl bg-slate-50 p-4">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="update">
|
||||
{{ form.user_id }}
|
||||
<div class="space-y-3 text-sm text-gray-700">
|
||||
<label class="flex items-center gap-2" for="{{ form.is_staff.id_for_label }}">
|
||||
<input type="checkbox"
|
||||
id="{{ form.is_staff.id_for_label }}"
|
||||
name="{{ form.is_staff.html_name }}"
|
||||
value="on"
|
||||
{% if form.is_staff.value %}checked{% endif %}
|
||||
class="h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-600">
|
||||
<span>Admin/staff</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2" for="{{ form.grant_view.id_for_label }}">
|
||||
<input type="checkbox"
|
||||
id="{{ form.grant_view.id_for_label }}"
|
||||
name="{{ form.grant_view.html_name }}"
|
||||
value="on"
|
||||
{% if form.grant_view.value %}checked{% endif %}
|
||||
class="h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-600">
|
||||
<span>Får se utlägg</span>
|
||||
</label>
|
||||
<label class="flex items-center gap-2" for="{{ form.grant_change.id_for_label }}">
|
||||
<input type="checkbox"
|
||||
id="{{ form.grant_change.id_for_label }}"
|
||||
name="{{ form.grant_change.html_name }}"
|
||||
value="on"
|
||||
{% if form.grant_change.value %}checked{% endif %}
|
||||
class="h-4 w-4 rounded border-gray-300 text-brand-600 focus:ring-brand-600">
|
||||
<span>Får besluta utlägg</span>
|
||||
</label>
|
||||
</div>
|
||||
<button type="submit" class="w-full rounded-2xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white transition hover:bg-brand-700">
|
||||
Spara behörigheter
|
||||
</button>
|
||||
</form>
|
||||
<div class="rounded-2xl border border-red-100 bg-red-50 p-4 text-sm text-red-800">
|
||||
<p class="font-semibold">Ta bort konto</p>
|
||||
{% if delete_form %}
|
||||
<p class="mt-1 text-xs text-red-700">Åtgärden går inte att ångra. Användaren förlorar omedelbart åtkomst.</p>
|
||||
<form method="post" class="mt-4" onsubmit="return confirm('Ta bort {{ user.username }}?');">
|
||||
{% csrf_token %}
|
||||
<input type="hidden" name="action" value="delete">
|
||||
{{ delete_form.user_id }}
|
||||
<button type="submit" class="w-full rounded-full bg-red-600 px-4 py-2 text-xs font-semibold text-white transition hover:bg-red-700">
|
||||
Ta bort användare
|
||||
</button>
|
||||
</form>
|
||||
{% else %}
|
||||
<p class="mt-2 text-xs text-red-700">Kan inte tas bort (antingen du själv eller superuser).</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
{% endwith %}
|
||||
{% empty %}
|
||||
<tr><td colspan="5">Inga användare upplagda.</td></tr>
|
||||
<div class="rounded-3xl border border-dashed border-gray-200 bg-white px-6 py-10 text-center text-gray-500">
|
||||
<p class="text-lg font-semibold text-gray-900">Inga användare ännu</p>
|
||||
<p class="mt-2 text-sm">Skapa det första kontot via formuläret ovan.</p>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user