from django.conf import settings from django.contrib.admin.views.decorators import staff_member_required from django.contrib.staticfiles import finders from django.http import FileResponse, Http404 from django.middleware.csrf import get_token from django.shortcuts import render from tracker.models import ScheduledDose def service_worker(request): """The built worker (frontend/src/sw.ts), from the root so its scope covers /admin/. Served by a view rather than the staticfiles machinery because the URL must stay stable and unhashed — a renamed worker would be a brand-new worker. """ path = finders.find("sw.js") if path is None: raise Http404("Frontend not built yet — run: make frontend") response = FileResponse(open(path, "rb"), content_type="application/javascript") # Browsers cap service-worker caching anyway; make updates immediate. response["Cache-Control"] = "no-cache" return response @staff_member_required def app(request): """The single-page app shell: Vue routes between Today and Recap client-side. All data flows through the API; the shell only carries the per-page-load facts the frontend cannot fetch (CSRF token) or that feed the reminder diagnostics. """ active_doses = ScheduledDose.objects.filter( is_active=True, medication__is_active=True ) return render( request, "tracker/app.html", { "config": { "vapidPublicKey": settings.VAPID_PUBLIC_KEY, # get_token also sets the CSRF cookie for the session. "csrfToken": get_token(request), "activeDoses": active_doses.count(), "dosesWithReminders": active_doses.filter( reminder_time__isnull=False ).count(), "subscribedDevices": request.user.push_subscriptions.count(), } }, )