From ef4e510814b10b989ecebcc78ff086e5c70367fa Mon Sep 17 00:00:00 2001 From: Colin Powell Date: Tue, 28 Apr 2026 15:44:48 -0400 Subject: [PATCH] [moods] Add a nice form for checking in --- vrobbler/apps/moods/models.py | 20 +++++ .../moods/templates/moods/checkin_mood.html | 28 +++++++ .../templates/moods/checkin_quality.html | 24 ++++++ .../templates/moods/checkin_success.html | 15 ++++ vrobbler/apps/moods/urls.py | 2 + vrobbler/apps/moods/views.py | 81 ++++++++++++++++++- vrobbler/apps/scrobbles/constants.py | 1 + vrobbler/templates/base.html | 3 + 8 files changed, 173 insertions(+), 1 deletion(-) create mode 100644 vrobbler/apps/moods/templates/moods/checkin_mood.html create mode 100644 vrobbler/apps/moods/templates/moods/checkin_quality.html create mode 100644 vrobbler/apps/moods/templates/moods/checkin_success.html diff --git a/vrobbler/apps/moods/models.py b/vrobbler/apps/moods/models.py index 9f4181d..f36bc2b 100644 --- a/vrobbler/apps/moods/models.py +++ b/vrobbler/apps/moods/models.py @@ -1,5 +1,6 @@ import logging from dataclasses import dataclass +from enum import IntEnum from typing import Optional from uuid import uuid4 @@ -21,10 +22,21 @@ class MoodType(models.TextChoices): NEGATIVE = "negative", "Negative" +class MoodQuality(IntEnum): + VERY_UNPLEASANT = 1 + UNPLEASANT = 2 + SLIGHTLY_UNPLEASANT = 3 + NEUTRAL = 4 + SLIGHTLY_PLEASANT = 5 + PLEASANT = 6 + VERY_PLEASANT = 7 + + @dataclass class MoodLogData(BaseLogData): mood_type: Optional[str] = None mood_reason_ids: Optional[list[int]] = None + mood_quality: Optional[int] = None @classmethod def override_fields(cls) -> dict: @@ -42,6 +54,14 @@ class MoodLogData(BaseLogData): required=False, widget=forms.SelectMultiple(attrs={"size": 10}), ), + "mood_quality": forms.ChoiceField( + choices=[ + (mq.value, mq.name.replace("_", " ").title()) + for mq in MoodQuality + ], + required=False, + widget=forms.Select(attrs={"class": "form-control"}), + ), } diff --git a/vrobbler/apps/moods/templates/moods/checkin_mood.html b/vrobbler/apps/moods/templates/moods/checkin_mood.html new file mode 100644 index 0000000..67d9464 --- /dev/null +++ b/vrobbler/apps/moods/templates/moods/checkin_mood.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} + +{% block page_title %}Check-in - Select your mood{% endblock %} + +{% block content %} +
+
+
+

Select your mood

+
+ {% csrf_token %} +
+ {% for mood in moods %} + + {% endfor %} +
+
+ +
+
+
+{% endblock %} diff --git a/vrobbler/apps/moods/templates/moods/checkin_quality.html b/vrobbler/apps/moods/templates/moods/checkin_quality.html new file mode 100644 index 0000000..120936f --- /dev/null +++ b/vrobbler/apps/moods/templates/moods/checkin_quality.html @@ -0,0 +1,24 @@ +{% extends "base.html" %} + +{% block page_title %}Check-in - How are you feeling?{% endblock %} + +{% block content %} +
+
+
+

How are you feeling?

+
+ {% csrf_token %} +
+ {% for quality in qualities %} + + {% endfor %} +
+
+
+
+
+{% endblock %} diff --git a/vrobbler/apps/moods/templates/moods/checkin_success.html b/vrobbler/apps/moods/templates/moods/checkin_success.html new file mode 100644 index 0000000..03990c2 --- /dev/null +++ b/vrobbler/apps/moods/templates/moods/checkin_success.html @@ -0,0 +1,15 @@ +{% extends "base.html" %} + +{% block page_title %}Check-in Complete{% endblock %} + +{% block content %} +
+
+
+

Check-in Complete!

+

Your mood has been recorded.

+ Back to Home +
+
+
+{% endblock %} diff --git a/vrobbler/apps/moods/urls.py b/vrobbler/apps/moods/urls.py index ad02987..bcccdc9 100644 --- a/vrobbler/apps/moods/urls.py +++ b/vrobbler/apps/moods/urls.py @@ -11,4 +11,6 @@ urlpatterns = [ views.MoodDetailView.as_view(), name="mood_detail", ), + path("checkin/", views.checkin, name="checkin"), + path("checkin/success/", views.checkin_success, name="checkin_success"), ] diff --git a/vrobbler/apps/moods/views.py b/vrobbler/apps/moods/views.py index a807963..9935e80 100644 --- a/vrobbler/apps/moods/views.py +++ b/vrobbler/apps/moods/views.py @@ -1,4 +1,83 @@ -from moods.models import Mood +import logging +from django.contrib.auth.decorators import login_required +from django.shortcuts import redirect, render +from django.urls import reverse +from django.utils import timezone +from moods.models import Mood, MoodLogData, MoodQuality +from scrobbles.models import Scrobble + +logger = logging.getLogger(__name__) + + +@login_required +def checkin(request): + """Two-step mood check-in wizard""" + step = request.session.get("checkin_step", 1) + + if request.method == "POST": + if step == 1: + quality = request.POST.get("mood_quality") + if quality: + request.session["checkin_quality"] = int(quality) + request.session["checkin_step"] = 2 + return redirect("moods:checkin") + qualities = [ + {"value": q.value, "name": q.name.replace("_", " ").title()} + for q in MoodQuality + ] + return render( + request, "moods/checkin_quality.html", {"qualities": qualities} + ) + + elif step == 2: + mood_id = request.POST.get("mood") + quality = request.session.get("checkin_quality") + + if mood_id and quality: + try: + mood = Mood.objects.get(id=mood_id) + log_data = MoodLogData( + mood_quality=quality, + mood_type=mood.mood_type, + ) + + scrobble = Scrobble.objects.create( + user=request.user, + mood=mood, + media_type=Scrobble.MediaType.MOOD, + timestamp=timezone.now(), + source="web_checkin", + log=log_data.asdict, + ) + + # Clear session data + request.session.pop("checkin_step", None) + request.session.pop("checkin_quality", None) + + return redirect("moods:checkin_success") + except Mood.DoesNotExist: + logger.error(f"Mood with id {mood_id} not found") + + return redirect("moods:checkin") + + if step == 1: + qualities = [ + {"value": q.value, "name": q.name.replace("_", " ").title()} + for q in MoodQuality + ] + return render( + request, "moods/checkin_quality.html", {"qualities": qualities} + ) + else: + moods = Mood.objects.all() + return render(request, "moods/checkin_mood.html", {"moods": moods}) + + +@login_required +def checkin_success(request): + return render(request, "moods/checkin_success.html") + + from scrobbles.views import ScrobbleableListView, ScrobbleableDetailView diff --git a/vrobbler/apps/scrobbles/constants.py b/vrobbler/apps/scrobbles/constants.py index d9c08fe..592c2fd 100644 --- a/vrobbler/apps/scrobbles/constants.py +++ b/vrobbler/apps/scrobbles/constants.py @@ -15,6 +15,7 @@ AUTO_FINISH_MEDIA = { "webpages": "WebPage", "tracks": "Track", "videos": "Video", + "moods": "Mood", } PLAY_AGAIN_MEDIA = { diff --git a/vrobbler/templates/base.html b/vrobbler/templates/base.html index d1cbc05..b0326f4 100644 --- a/vrobbler/templates/base.html +++ b/vrobbler/templates/base.html @@ -218,6 +218,9 @@ {% endif %} {% if user.is_authenticated %}