from django.contrib import messages from django.contrib.auth.decorators import login_required from django.core.files.storage import default_storage from django.db import IntegrityError from django.http import HttpResponse, JsonResponse from django.shortcuts import get_object_or_404, redirect, render from django.views.decorators.http import require_POST from django.views.generic import ListView from .forms import NoteUploadForm, SeatsForm from .models import Workshop from .services import SoldOut, cancel, reserve class WorkshopListView(ListView): template_name = "workshops/list.html" context_object_name = "workshops" paginate_by = 2 def get_queryset(self): return Workshop.objects.public().select_related("venue") def detail(request, slug): workshop = get_object_or_404(Workshop.objects.public().select_related("venue"), slug=slug) return render(request, "workshops/detail.html", {"workshop": workshop, "form": SeatsForm()}) @login_required @require_POST def book(request, slug): workshop = get_object_or_404(Workshop.objects.public(), slug=slug) form = SeatsForm(request.POST) if not form.is_valid(): return render(request, "workshops/detail.html", {"workshop": workshop, "form": form}, status=400) try: reserve(workshop_id=workshop.pk, user=request.user, seats=form.cleaned_data["seats"]) except (SoldOut, IntegrityError): form.add_error(None, "No reservation made. Check available seats or an existing reservation.") workshop.refresh_from_db() return render(request, "workshops/detail.html", {"workshop": workshop, "form": form}, status=409) messages.success(request, "Reservation saved in this local lab.") return redirect(workshop) @login_required @require_POST def cancel_booking(request, pk): if not cancel(reservation_id=pk, user=request.user): return HttpResponse("Reservation not found", status=404) return redirect("workshops:list") def api_list(request): rows = list(Workshop.objects.public().values("slug", "title", "remaining")) return JsonResponse({"workshops": rows}) async def health(request): return JsonResponse({"status": "local lab"}) @login_required def upload_note(request): form = NoteUploadForm(request.POST or None, request.FILES or None) if request.method == "POST" and form.is_valid(): name = default_storage.save("notes/access.txt", form.cleaned_data["note"]) return HttpResponse("Stored privately: " + name, content_type="text/plain") return render(request, "workshops/upload.html", {"form": form}, status=400 if request.method == "POST" else 200) def not_found(request, exception): return render(request, "404.html", status=404)