""" Surveys admin """ from django.contrib import admin from django.utils.html import format_html from django.db.models import Count from .models import ( SurveyInstance, SurveyQuestion, SurveyResponse, SurveyTemplate, SurveyTracking, ) class SurveyQuestionInline(admin.TabularInline): """Inline admin for survey questions""" model = SurveyQuestion extra = 1 fields = ["order", "text", "question_type", "is_required", "is_base", "event_type"] ordering = ["order"] @admin.register(SurveyTemplate) class SurveyTemplateAdmin(admin.ModelAdmin): """Survey template admin""" list_display = [ "name", "survey_type", "hospital", "scoring_method", "negative_threshold", "get_question_count", "is_active", ] list_filter = ["survey_type", "scoring_method", "is_active", "hospital"] search_fields = ["name", "name_ar"] ordering = ["hospital", "name"] inlines = [SurveyQuestionInline] fieldsets = ( (None, {"fields": ("name", "name_ar")}), ("Configuration", {"fields": ("hospital", "survey_type")}), ("Scoring", {"fields": ("scoring_method", "negative_threshold")}), ("Status", {"fields": ("is_active",)}), ("Metadata", {"fields": ("created_at", "updated_at")}), ) readonly_fields = ["created_at", "updated_at"] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related("hospital").prefetch_related("questions") @admin.register(SurveyQuestion) class SurveyQuestionAdmin(admin.ModelAdmin): """Survey question admin""" list_display = ["survey_template", "order", "text_preview", "question_type", "is_base", "is_required"] list_filter = ["survey_template", "question_type", "is_required", "is_base"] search_fields = ["text", "text_ar"] ordering = ["survey_template", "order"] fieldsets = ( (None, {"fields": ("survey_template", "order")}), ("Question Text", {"fields": ("text", "text_ar")}), ("Configuration", {"fields": ("question_type", "is_required", "is_base", "event_type")}), ("Choices (for multiple choice)", {"fields": ("choices_json",), "classes": ("collapse",)}), ("Metadata", {"fields": ("created_at", "updated_at")}), ) readonly_fields = ["created_at", "updated_at"] def text_preview(self, obj): """Show preview of question text""" return obj.text[:100] + "..." if len(obj.text) > 100 else obj.text text_preview.short_description = "Question" def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related("survey_template") class SurveyResponseInline(admin.TabularInline): """Inline admin for survey responses""" model = SurveyResponse extra = 0 fields = ["question", "numeric_value", "text_value", "choice_value"] readonly_fields = ["question"] ordering = ["question__order"] def has_add_permission(self, request, obj=None): return False class SurveyTrackingInline(admin.TabularInline): """Inline admin for survey tracking events""" model = SurveyTracking extra = 0 fields = ["event_type", "device_type", "browser", "total_time_spent", "created_at"] readonly_fields = ["event_type", "device_type", "browser", "total_time_spent", "created_at"] ordering = ["-created_at"] can_delete = False def has_add_permission(self, request, obj=None): return False @admin.register(SurveyInstance) class SurveyInstanceAdmin(admin.ModelAdmin): """Survey instance admin""" list_display = [ "survey_label", "patient", "encounter_id", "status_badge", "delivery_channel", "open_count", "time_spent_display", "total_score", "is_negative", "sent_at", "completed_at", ] list_filter = [ "status", "delivery_channel", "is_negative", "survey_template__survey_type", "sent_at", "completed_at", ] search_fields = ["patient__mrn", "patient__first_name", "patient__last_name", "encounter_id", "access_token"] ordering = ["-created_at"] inlines = [SurveyResponseInline, SurveyTrackingInline] fieldsets = ( (None, {"fields": ("survey_template", "patient", "encounter_id")}), ("Journey Linkage", {"fields": ("journey_instance",), "classes": ("collapse",)}), ( "Delivery", {"fields": ("delivery_channel", "recipient_phone", "recipient_email", "access_token", "token_expires_at")}, ), ("Status & Timestamps", {"fields": ("status", "sent_at", "opened_at", "completed_at")}), ("Tracking", {"fields": ("open_count", "last_opened_at", "time_spent_seconds")}), ("Scoring", {"fields": ("total_score", "is_negative")}), ("Patient Comment", {"fields": ("comment", "comment_analyzed")}), ("Comment Analysis", {"fields": ("comment_analysis",), "classes": ("collapse",)}), ("Metadata", {"fields": ("metadata", "created_at", "updated_at"), "classes": ("collapse",)}), ) readonly_fields = [ "access_token", "token_expires_at", "sent_at", "opened_at", "completed_at", "open_count", "last_opened_at", "time_spent_seconds", "total_score", "is_negative", "comment_analyzed", "comment_analysis", "created_at", "updated_at", ] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related("survey_template", "patient", "journey_instance").prefetch_related( "responses", "tracking_events" ) def status_badge(self, obj): """Display status with color badge""" colors = { "sent": "secondary", "viewed": "info", "in_progress": "warning", "completed": "success", "abandoned": "danger", "expired": "secondary", "cancelled": "dark", } color = colors.get(obj.status, "secondary") return format_html('{}', color, obj.get_status_display()) status_badge.short_description = "Status" def survey_label(self, obj): if obj.survey_template: return obj.survey_template.name return obj.metadata.get("patient_type", "Event-based Survey") survey_label.short_description = "Survey" def time_spent_display(self, obj): """Display time spent in human-readable format""" if obj.time_spent_seconds: minutes = obj.time_spent_seconds // 60 seconds = obj.time_spent_seconds % 60 return f"{minutes}m {seconds}s" return "-" time_spent_display.short_description = "Time Spent" @admin.register(SurveyTracking) class SurveyTrackingAdmin(admin.ModelAdmin): """Survey tracking admin""" list_display = [ "survey_instance_link", "event_type_badge", "device_type", "browser", "ip_address", "total_time_spent_display", "created_at", ] list_filter = ["event_type", "device_type", "browser", "survey_instance__survey_template", "created_at"] search_fields = [ "survey_instance__patient__mrn", "survey_instance__patient__first_name", "survey_instance__patient__last_name", "ip_address", "user_agent", ] ordering = ["-created_at"] fieldsets = ( (None, {"fields": ("survey_instance", "event_type")}), ("Timing", {"fields": ("time_on_page", "total_time_spent")}), ("Context", {"fields": ("current_question",)}), ("Device Info", {"fields": ("user_agent", "ip_address", "device_type", "browser")}), ("Location", {"fields": ("country", "city"), "classes": ("collapse",)}), ("Metadata", {"fields": ("metadata", "created_at"), "classes": ("collapse",)}), ) readonly_fields = ["created_at"] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related("survey_instance", "survey_instance__patient") def survey_instance_link(self, obj): """Link to survey instance""" url = f"/admin/surveys/surveyinstance/{obj.survey_instance.id}/change/" label = ( obj.survey_instance.survey_template.name if obj.survey_instance.survey_template else obj.survey_instance.metadata.get("patient_type", "Survey") ) return format_html( '{} - {}', url, label, obj.survey_instance.patient.get_full_name(), ) survey_instance_link.short_description = "Survey" def event_type_badge(self, obj): """Display event type with color badge""" colors = { "page_view": "info", "survey_started": "primary", "question_answered": "secondary", "survey_completed": "success", "survey_abandoned": "danger", "reminder_sent": "warning", } color = colors.get(obj.event_type, "secondary") return format_html('{}', color, obj.get_event_type_display()) event_type_badge.short_description = "Event Type" def total_time_spent_display(self, obj): """Display time spent in human-readable format""" if obj.total_time_spent: minutes = obj.total_time_spent // 60 seconds = obj.total_time_spent % 60 return f"{minutes}m {seconds}s" return "-" total_time_spent_display.short_description = "Time Spent" @admin.register(SurveyResponse) class SurveyResponseAdmin(admin.ModelAdmin): """Survey response admin""" list_display = ["survey_instance", "question_preview", "numeric_value", "text_value_preview", "created_at"] list_filter = ["survey_instance__survey_template", "question__question_type", "created_at"] search_fields = ["survey_instance__patient__mrn", "question__text", "text_value"] ordering = ["survey_instance", "question__order"] fieldsets = ( (None, {"fields": ("survey_instance", "question")}), ("Response", {"fields": ("numeric_value", "text_value", "choice_value")}), ("Metadata", {"fields": ("created_at", "updated_at")}), ) readonly_fields = ["created_at", "updated_at"] def get_queryset(self, request): qs = super().get_queryset(request) return qs.select_related("survey_instance", "question") def question_preview(self, obj): """Show preview of question""" return obj.question.text[:50] + "..." if len(obj.question.text) > 50 else obj.question.text question_preview.short_description = "Question" def text_value_preview(self, obj): """Show preview of text response""" if obj.text_value: return obj.text_value[:50] + "..." if len(obj.text_value) > 50 else obj.text_value return "-" text_value_preview.short_description = "Text Response"