""" Feedback forms - Forms for feedback management """ from django import forms from apps.organizations.models import Department, Hospital, Patient, Staff from apps.core.form_mixins import HospitalFieldMixin from .models import Feedback, FeedbackResponse, FeedbackStatus, FeedbackType, FeedbackCategory class FeedbackForm(HospitalFieldMixin, forms.ModelForm): """Form for creating and editing feedback""" class Meta: model = Feedback fields = [ "patient", "is_anonymous", "contact_name", "contact_email", "contact_phone", "hospital", "department", "staff", "feedback_type", "title", "message", "category", "subcategory", "rating", "priority", "encounter_id", ] widgets = { "patient": forms.Select(attrs={"class": "form-select", "id": "id_patient"}), "is_anonymous": forms.CheckboxInput(attrs={"class": "form-check-input", "id": "id_is_anonymous"}), "contact_name": forms.TextInput(attrs={"class": "form-control", "placeholder": "Enter contact name"}), "contact_email": forms.EmailInput(attrs={"class": "form-control", "placeholder": "Enter email address"}), "contact_phone": forms.TextInput(attrs={"class": "form-control", "placeholder": "Enter phone number"}), "hospital": forms.Select(attrs={"class": "form-select", "required": True}), "department": forms.Select(attrs={"class": "form-select"}), "staff": forms.Select(attrs={"class": "form-select"}), "feedback_type": forms.Select(attrs={"class": "form-select", "required": True}), "title": forms.TextInput( attrs={"class": "form-control", "placeholder": "Enter feedback title", "required": True} ), "message": forms.Textarea( attrs={ "class": "form-control", "rows": 5, "placeholder": "Enter your feedback message...", "required": True, } ), "category": forms.Select(attrs={"class": "form-select", "required": True}), "subcategory": forms.TextInput( attrs={"class": "form-control", "placeholder": "Enter subcategory (optional)"} ), "rating": forms.NumberInput( attrs={"class": "form-control", "min": 1, "max": 5, "placeholder": "Rate from 1 to 5"} ), "priority": forms.Select(attrs={"class": "form-select"}), "encounter_id": forms.TextInput( attrs={"class": "form-control", "placeholder": "Enter encounter ID (optional)"} ), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Hospital field is configured by HospitalFieldMixin (always hidden) # Filter departments and staff based on hospital hospital = None if self.instance.pk and hasattr(self.instance, "hospital") and self.instance.hospital_id: hospital = self.instance.hospital elif self.user and self.user.is_px_admin(): hospital = getattr(self.request, "tenant_hospital", None) elif self.user and self.user.hospital: hospital = self.user.hospital if hospital: self.fields["department"].queryset = Department.objects.filter(hospital=hospital, status="active") self.fields["staff"].queryset = Staff.objects.filter(hospital=hospital, status="active") else: self.fields["department"].queryset = Department.objects.none() self.fields["staff"].queryset = Staff.objects.none() # Make patient optional if anonymous if self.data.get("is_anonymous"): self.fields["patient"].required = False def clean(self): cleaned_data = super().clean() is_anonymous = cleaned_data.get("is_anonymous") patient = cleaned_data.get("patient") contact_name = cleaned_data.get("contact_name") # Validate anonymous feedback if is_anonymous: if not contact_name: raise forms.ValidationError("Contact name is required for anonymous feedback.") else: if not patient: raise forms.ValidationError("Please select a patient or mark as anonymous.") # Validate rating rating = cleaned_data.get("rating") if rating is not None and (rating < 1 or rating > 5): raise forms.ValidationError("Rating must be between 1 and 5.") return cleaned_data class FeedbackResponseForm(forms.ModelForm): """Form for adding responses to feedback""" class Meta: model = FeedbackResponse fields = ["response_type", "message", "is_internal"] widgets = { "response_type": forms.Select(attrs={"class": "form-select", "required": True}), "message": forms.Textarea( attrs={"class": "form-control", "rows": 4, "placeholder": "Enter your response...", "required": True} ), "is_internal": forms.CheckboxInput(attrs={"class": "form-check-input"}), } class FeedbackFilterForm(forms.Form): """Form for filtering feedback list""" search = forms.CharField( required=False, widget=forms.TextInput(attrs={"class": "form-control", "placeholder": "Search by title, message, patient..."}), ) feedback_type = forms.ChoiceField( required=False, choices=[("", "All Types")] + list(FeedbackType.choices), widget=forms.Select(attrs={"class": "form-select"}), ) status = forms.ChoiceField( required=False, choices=[("", "All Statuses")] + list(FeedbackStatus.choices), widget=forms.Select(attrs={"class": "form-select"}), ) category = forms.ChoiceField( required=False, choices=[("", "All Categories")] + list(FeedbackCategory.choices), widget=forms.Select(attrs={"class": "form-select"}), ) sentiment = forms.ChoiceField( required=False, choices=[ ("", "All Sentiments"), ("positive", "Positive"), ("neutral", "Neutral"), ("negative", "Negative"), ], widget=forms.Select(attrs={"class": "form-select"}), ) priority = forms.ChoiceField( required=False, choices=[ ("", "All Priorities"), ("low", "Low"), ("medium", "Medium"), ("high", "High"), ("urgent", "Urgent"), ], widget=forms.Select(attrs={"class": "form-select"}), ) hospital = forms.ModelChoiceField( required=False, queryset=Hospital.objects.filter(status="active"), widget=forms.Select(attrs={"class": "form-select"}), empty_label="All Hospitals", ) department = forms.ModelChoiceField( required=False, queryset=Department.objects.filter(status="active"), widget=forms.Select(attrs={"class": "form-select"}), empty_label="All Departments", ) rating_min = forms.IntegerField( required=False, min_value=1, max_value=5, widget=forms.NumberInput(attrs={"class": "form-control", "placeholder": "Min rating"}), ) rating_max = forms.IntegerField( required=False, min_value=1, max_value=5, widget=forms.NumberInput(attrs={"class": "form-control", "placeholder": "Max rating"}), ) date_from = forms.DateField(required=False, widget=forms.DateInput(attrs={"class": "form-control", "type": "date"})) date_to = forms.DateField(required=False, widget=forms.DateInput(attrs={"class": "form-control", "type": "date"})) is_featured = forms.BooleanField(required=False, widget=forms.CheckboxInput(attrs={"class": "form-check-input"})) requires_follow_up = forms.BooleanField( required=False, widget=forms.CheckboxInput(attrs={"class": "form-check-input"}) ) class FeedbackStatusChangeForm(forms.Form): """Form for changing feedback status""" status = forms.ChoiceField( choices=FeedbackStatus.choices, widget=forms.Select(attrs={"class": "form-select", "required": True}) ) note = forms.CharField( required=False, widget=forms.Textarea( attrs={ "class": "form-control", "rows": 3, "placeholder": "Add a note about this status change (optional)...", } ), ) class FeedbackAssignForm(forms.Form): """Form for assigning feedback to a user""" user_id = forms.UUIDField(widget=forms.Select(attrs={"class": "form-select", "required": True})) note = forms.CharField( required=False, widget=forms.Textarea( attrs={"class": "form-control", "rows": 2, "placeholder": "Add a note about this assignment (optional)..."} ), )