115 lines
5.5 KiB
Python
115 lines
5.5 KiB
Python
from django import forms
|
|
from django.utils import timezone
|
|
|
|
from .models import Event, Registration
|
|
|
|
|
|
class EventSearchForm(forms.Form):
|
|
q = forms.CharField(
|
|
required=False,
|
|
max_length=80,
|
|
label='Search',
|
|
widget=forms.TextInput(
|
|
attrs={
|
|
'placeholder': 'Search by title, venue, or keyword',
|
|
'class': 'form-control form-control-lg',
|
|
}
|
|
),
|
|
)
|
|
|
|
|
|
class RegistrationForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Registration
|
|
fields = ['full_name', 'email', 'company', 'notes']
|
|
widgets = {
|
|
'full_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Jordan Lee'}),
|
|
'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'you@example.com'}),
|
|
'company': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Studio North'}),
|
|
'notes': forms.Textarea(attrs={'class': 'form-control', 'rows': 4, 'placeholder': 'Accessibility needs, dietary notes, or questions'}),
|
|
}
|
|
|
|
def __init__(self, *args, event=None, **kwargs):
|
|
self.event = event
|
|
super().__init__(*args, **kwargs)
|
|
for field in self.fields.values():
|
|
css = field.widget.attrs.get('class', '')
|
|
if 'form-control' not in css:
|
|
field.widget.attrs['class'] = f'{css} form-control'.strip()
|
|
|
|
def clean_email(self):
|
|
email = self.cleaned_data['email'].strip().lower()
|
|
if self.event and Registration.objects.filter(event=self.event, email__iexact=email).exists():
|
|
raise forms.ValidationError('This email is already registered for this event.')
|
|
return email
|
|
|
|
|
|
class OrganizerEventForm(forms.ModelForm):
|
|
datetime_format = '%Y-%m-%dT%H:%M'
|
|
|
|
class Meta:
|
|
model = Event
|
|
fields = [
|
|
'title',
|
|
'summary',
|
|
'description',
|
|
'venue',
|
|
'start_at',
|
|
'end_at',
|
|
'capacity',
|
|
'is_published',
|
|
'registration_opens',
|
|
'registration_closes',
|
|
]
|
|
widgets = {
|
|
'title': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Spring Product Launch'}),
|
|
'summary': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'A short one-line overview for the catalog card.'}),
|
|
'description': forms.Textarea(attrs={'class': 'form-control', 'rows': 6, 'placeholder': 'Describe the agenda, audience, and what attendees should expect.'}),
|
|
'venue': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Northstar Studio, Austin'}),
|
|
'start_at': forms.DateTimeInput(format='%Y-%m-%dT%H:%M', attrs={'class': 'form-control', 'type': 'datetime-local'}),
|
|
'end_at': forms.DateTimeInput(format='%Y-%m-%dT%H:%M', attrs={'class': 'form-control', 'type': 'datetime-local'}),
|
|
'capacity': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'Optional'}),
|
|
'is_published': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
|
'registration_opens': forms.DateTimeInput(format='%Y-%m-%dT%H:%M', attrs={'class': 'form-control', 'type': 'datetime-local'}),
|
|
'registration_closes': forms.DateTimeInput(format='%Y-%m-%dT%H:%M', attrs={'class': 'form-control', 'type': 'datetime-local'}),
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
for field_name in ('start_at', 'end_at', 'registration_opens', 'registration_closes'):
|
|
self.fields[field_name].input_formats = [self.datetime_format]
|
|
value = self.initial.get(field_name)
|
|
if value:
|
|
self.initial[field_name] = timezone.localtime(value).strftime(self.datetime_format)
|
|
for field in self.fields.values():
|
|
css = field.widget.attrs.get('class', '')
|
|
if isinstance(field.widget, forms.CheckboxInput):
|
|
field.widget.attrs['class'] = 'form-check-input'
|
|
elif 'form-control' not in css:
|
|
field.widget.attrs['class'] = f'{css} form-control'.strip()
|
|
self.fields['capacity'].required = False
|
|
self.fields['registration_opens'].required = False
|
|
self.fields['registration_closes'].required = False
|
|
self.fields['is_published'].required = False
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
start_at = cleaned_data.get('start_at')
|
|
end_at = cleaned_data.get('end_at')
|
|
registration_opens = cleaned_data.get('registration_opens')
|
|
registration_closes = cleaned_data.get('registration_closes')
|
|
capacity = cleaned_data.get('capacity')
|
|
|
|
if start_at and end_at and end_at <= start_at:
|
|
self.add_error('end_at', 'End time must be after the event start time.')
|
|
if registration_opens and start_at and registration_opens > start_at:
|
|
self.add_error('registration_opens', 'Registration should open before the event begins.')
|
|
if registration_closes and start_at and registration_closes > start_at:
|
|
self.add_error('registration_closes', 'Registration should close before the event begins.')
|
|
if registration_opens and registration_closes and registration_closes <= registration_opens:
|
|
self.add_error('registration_closes', 'Registration close must be after registration open.')
|
|
if capacity is not None and capacity < 1:
|
|
self.add_error('capacity', 'Capacity must be at least 1 when provided.')
|
|
|
|
return cleaned_data
|