76 lines
3.0 KiB
Python
76 lines
3.0 KiB
Python
from django import forms
|
|
from django.utils import timezone
|
|
|
|
from .models import ConsultationRequest, ConsultationSlot
|
|
|
|
|
|
class AvailableSlotChoiceField(forms.ModelChoiceField):
|
|
def label_from_instance(self, slot):
|
|
local_start = timezone.localtime(slot.start_at)
|
|
return (
|
|
f"{local_start:%d.%m.%Y} в {local_start:%H:%M} "
|
|
f"· {slot.duration_minutes} минут · {slot.get_format_display()}"
|
|
)
|
|
|
|
|
|
class ConsultationRequestForm(forms.ModelForm):
|
|
slot = AvailableSlotChoiceField(
|
|
queryset=ConsultationSlot.objects.none(),
|
|
empty_label="Выберите свободное время",
|
|
label="Удобное время",
|
|
)
|
|
|
|
class Meta:
|
|
model = ConsultationRequest
|
|
fields = (
|
|
"name",
|
|
"phone",
|
|
"contact",
|
|
"student_grade",
|
|
"subject",
|
|
"exam",
|
|
"format",
|
|
"slot",
|
|
"comment",
|
|
"consent_given",
|
|
)
|
|
widgets = {
|
|
"name": forms.TextInput(attrs={"placeholder": "Как к вам обращаться"}),
|
|
"phone": forms.TelInput(attrs={"placeholder": "+7 (999) 123-45-67"}),
|
|
"contact": forms.TextInput(attrs={"placeholder": "@username, WhatsApp и т. п."}),
|
|
"comment": forms.Textarea(
|
|
attrs={
|
|
"placeholder": "Класс, темы и вопросы, которые хотите разобрать",
|
|
"rows": 4,
|
|
}
|
|
),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
self.fields["slot"].queryset = ConsultationSlot.objects.available()
|
|
for name, field in self.fields.items():
|
|
if name != "consent_given":
|
|
field.widget.attrs["class"] = "form-control"
|
|
self.fields["consent_given"].widget.attrs["class"] = "consent-control"
|
|
self.fields["contact"].required = False
|
|
self.fields["student_grade"].required = False
|
|
self.fields["comment"].required = False
|
|
|
|
def clean_slot(self):
|
|
slot = self.cleaned_data["slot"]
|
|
if not slot.is_available:
|
|
raise forms.ValidationError("Это время уже занято. Выберите другой свободный слот.")
|
|
return slot
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
slot = cleaned_data.get("slot")
|
|
subject = cleaned_data.get("subject")
|
|
requested_format = cleaned_data.get("format")
|
|
if slot and subject and slot.subject not in (ConsultationSlot.Subject.ANY, subject):
|
|
self.add_error("slot", "Это время доступно только для другого предмета.")
|
|
if slot and requested_format not in (ConsultationRequest.Format.ANY, slot.format):
|
|
self.add_error("format", f"Для выбранного времени доступен формат: {slot.get_format_display()}.")
|
|
return cleaned_data
|