.
This commit is contained in:
+137
-2
@@ -4,6 +4,10 @@ from django.urls import reverse
|
||||
from .models import RotaSchedule, Worker
|
||||
from .forms import WorkerForm, LeaveForm, RotaScheduleForm
|
||||
from .services import run_rota_async
|
||||
from .forms import ShiftForm
|
||||
from django.views.decorators.http import require_http_methods
|
||||
from django.template.loader import render_to_string
|
||||
from django.http import HttpResponse, HttpResponseBadRequest
|
||||
|
||||
|
||||
def index(request):
|
||||
@@ -16,11 +20,23 @@ def rota_detail(request, rota_id):
|
||||
if request.method == "POST":
|
||||
# trigger a background run
|
||||
run = run_rota_async(rota.id)
|
||||
return redirect(reverse("rota_run_detail", args=(run.id,)))
|
||||
return redirect(reverse("rota:rota_run_detail", args=(run.id,)))
|
||||
|
||||
return render(request, "rota/rota_detail.html", {"rota": rota})
|
||||
|
||||
|
||||
def rota_create(request):
|
||||
if request.method == "POST":
|
||||
form = RotaScheduleForm(request.POST)
|
||||
if form.is_valid():
|
||||
rota = form.save()
|
||||
return redirect("rota:rota_detail", rota_id=rota.id)
|
||||
else:
|
||||
form = RotaScheduleForm()
|
||||
|
||||
return render(request, "rota/rota_form.html", {"form": form})
|
||||
|
||||
|
||||
def worker_create(request):
|
||||
if request.method == "POST":
|
||||
form = WorkerForm(request.POST)
|
||||
@@ -41,7 +57,7 @@ def worker_detail(request, worker_id):
|
||||
leave = form.save(commit=False)
|
||||
leave.worker = worker
|
||||
leave.save()
|
||||
return redirect("worker_detail", worker_id=worker.id)
|
||||
return redirect("rota:worker_detail", worker_id=worker.id)
|
||||
else:
|
||||
form = LeaveForm()
|
||||
|
||||
@@ -54,3 +70,122 @@ def rota_run_detail(request, run_id):
|
||||
run = get_object_or_404(RotaRun, pk=run_id)
|
||||
return render(request, "rota/rota_run_detail.html", {"run": run})
|
||||
|
||||
|
||||
@require_http_methods(["GET", "POST"])
|
||||
def shift_add(request, rota_id):
|
||||
"""HTMX endpoint to render a shift form or accept submission to append a shift to the rota."""
|
||||
rota = get_object_or_404(RotaSchedule, pk=rota_id)
|
||||
|
||||
if request.method == "POST":
|
||||
form = ShiftForm(request.POST)
|
||||
if form.is_valid():
|
||||
data = form.cleaned_data
|
||||
shift_dict = {
|
||||
"sites": data["sites"],
|
||||
"name": data["name"],
|
||||
"length": float(data["length"]),
|
||||
"days": data["days"],
|
||||
"workers_required": int(data["workers_required"]),
|
||||
"assign_as_block": bool(data["assign_as_block"]),
|
||||
}
|
||||
|
||||
current = rota.shifts or []
|
||||
current.append(shift_dict)
|
||||
rota.shifts = current
|
||||
rota.save()
|
||||
|
||||
# Return out-of-band swap: update shift-list and clear modal
|
||||
shift_list_html = render_to_string("rota/partials/shift_list.html", {"rota": rota}, request=request)
|
||||
# wrap shift list for OOB swap
|
||||
resp = (
|
||||
f'<div id="shift-list" hx-swap-oob="true">{shift_list_html}</div>'
|
||||
+ '<div id="modal" hx-swap-oob="true"></div>'
|
||||
)
|
||||
return HttpResponse(resp)
|
||||
|
||||
# invalid: return modal with form and errors
|
||||
modal_html = render_to_string("rota/partials/shift_form_modal.html", {"form": form, "rota": rota, "form_action": request.path}, request=request)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
else:
|
||||
form = ShiftForm()
|
||||
modal_html = render_to_string("rota/partials/shift_form_modal.html", {"form": form, "rota": rota, "form_action": request.path}, request=request)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
|
||||
@require_http_methods(["GET", "POST"])
|
||||
def shift_edit(request, rota_id, idx):
|
||||
rota = get_object_or_404(RotaSchedule, pk=rota_id)
|
||||
try:
|
||||
shift = rota.shifts[idx]
|
||||
except Exception:
|
||||
return HttpResponseBadRequest("Shift not found")
|
||||
|
||||
if request.method == "POST":
|
||||
form = ShiftForm(request.POST)
|
||||
if form.is_valid():
|
||||
data = form.cleaned_data
|
||||
shift_dict = {
|
||||
"sites": data["sites"],
|
||||
"name": data["name"],
|
||||
"length": float(data["length"]),
|
||||
"days": data["days"],
|
||||
"workers_required": int(data["workers_required"]),
|
||||
"assign_as_block": bool(data["assign_as_block"]),
|
||||
}
|
||||
current = rota.shifts or []
|
||||
current[idx] = shift_dict
|
||||
rota.shifts = current
|
||||
rota.save()
|
||||
|
||||
shift_list_html = render_to_string("rota/partials/shift_list.html", {"rota": rota}, request=request)
|
||||
resp = (
|
||||
f'<div id="shift-list" hx-swap-oob="true">{shift_list_html}</div>'
|
||||
+ '<div id="modal" hx-swap-oob="true"></div>'
|
||||
)
|
||||
return HttpResponse(resp)
|
||||
|
||||
modal_html = render_to_string("rota/partials/shift_form_modal.html", {"form": form, "rota": rota, "form_action": request.path}, request=request)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
# GET: populate form with existing shift
|
||||
initial = {
|
||||
"name": shift.get("name"),
|
||||
"sites": ",".join(shift.get("sites") or []),
|
||||
"length": shift.get("length"),
|
||||
"days": shift.get("days"),
|
||||
"workers_required": shift.get("workers_required"),
|
||||
"assign_as_block": shift.get("assign_as_block", False),
|
||||
}
|
||||
form = ShiftForm(initial=initial)
|
||||
modal_html = render_to_string("rota/partials/shift_form_modal.html", {"form": form, "rota": rota, "form_action": request.path}, request=request)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
|
||||
@require_http_methods(["GET", "POST"])
|
||||
def shift_delete(request, rota_id, idx):
|
||||
rota = get_object_or_404(RotaSchedule, pk=rota_id)
|
||||
try:
|
||||
shift = rota.shifts[idx]
|
||||
except Exception:
|
||||
return HttpResponseBadRequest("Shift not found")
|
||||
|
||||
if request.method == "POST":
|
||||
current = rota.shifts or []
|
||||
try:
|
||||
current.pop(idx)
|
||||
except Exception:
|
||||
return HttpResponseBadRequest("Invalid index")
|
||||
rota.shifts = current
|
||||
rota.save()
|
||||
shift_list_html = render_to_string("rota/partials/shift_list.html", {"rota": rota}, request=request)
|
||||
resp = (
|
||||
f'<div id="shift-list" hx-swap-oob="true">{shift_list_html}</div>'
|
||||
+ '<div id="modal" hx-swap-oob="true"></div>'
|
||||
)
|
||||
return HttpResponse(resp)
|
||||
|
||||
# GET: confirmation modal
|
||||
modal_html = render_to_string("rota/partials/shift_confirm_delete.html", {"rota": rota, "idx": idx, "shift": shift}, request=request)
|
||||
return HttpResponse(modal_html)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user