106 lines
4.5 KiB
Python
106 lines
4.5 KiB
Python
from datetime import timedelta
|
|
|
|
from django import forms
|
|
|
|
from .models import Event
|
|
|
|
|
|
WEEKDAY_CHOICES = [
|
|
('0', 'Monday'),
|
|
('1', 'Tuesday'),
|
|
('2', 'Wednesday'),
|
|
('3', 'Thursday'),
|
|
('4', 'Friday'),
|
|
('5', 'Saturday'),
|
|
('6', 'Sunday'),
|
|
]
|
|
|
|
|
|
class EventForm(forms.ModelForm):
|
|
start = forms.DateTimeField(
|
|
input_formats=['%Y-%m-%dT%H:%M'],
|
|
widget=forms.DateTimeInput(
|
|
attrs={'type': 'datetime-local', 'class': 'form-control'},
|
|
format='%Y-%m-%dT%H:%M',
|
|
),
|
|
)
|
|
end = forms.DateTimeField(
|
|
input_formats=['%Y-%m-%dT%H:%M'],
|
|
widget=forms.DateTimeInput(
|
|
attrs={'type': 'datetime-local', 'class': 'form-control'},
|
|
format='%Y-%m-%dT%H:%M',
|
|
),
|
|
)
|
|
recurrence_start_date = forms.DateField(
|
|
required=False,
|
|
label='Repeat from',
|
|
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
|
|
help_text='Optional: first date in the weekly recurrence window.',
|
|
)
|
|
recurrence_end_date = forms.DateField(
|
|
required=False,
|
|
label='Repeat until',
|
|
widget=forms.DateInput(attrs={'type': 'date', 'class': 'form-control'}),
|
|
help_text='Optional: last date in the weekly recurrence window.',
|
|
)
|
|
recurrence_weekday = forms.ChoiceField(
|
|
required=False,
|
|
label='Weekday',
|
|
choices=[('', 'Select a weekday')] + WEEKDAY_CHOICES,
|
|
widget=forms.Select(attrs={'class': 'form-select'}),
|
|
help_text='Optional: create one event each week on this weekday.',
|
|
)
|
|
|
|
class Meta:
|
|
model = Event
|
|
fields = ['name', 'location', 'start', 'end', 'event_url', 'summary', 'is_published']
|
|
widgets = {
|
|
'name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Downtown Spring Market'}),
|
|
'location': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Riverfront Pavilion'}),
|
|
'event_url': forms.URLInput(attrs={'class': 'form-control', 'placeholder': 'https://event-page.example.com'}),
|
|
'summary': forms.Textarea(attrs={'class': 'form-control', 'rows': 4, 'placeholder': 'Anything visitors should know before attending.'}),
|
|
'is_published': forms.CheckboxInput(attrs={'class': 'form-check-input'}),
|
|
}
|
|
help_texts = {
|
|
'is_published': 'Only published events appear in the public calendar and embed widget.',
|
|
}
|
|
|
|
def __init__(self, *args, **kwargs):
|
|
super().__init__(*args, **kwargs)
|
|
for field_name in ['start', 'end']:
|
|
value = self.initial.get(field_name) or getattr(self.instance, field_name, None)
|
|
if value:
|
|
self.initial[field_name] = value.strftime('%Y-%m-%dT%H:%M')
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
start = cleaned_data.get('start')
|
|
end = cleaned_data.get('end')
|
|
if start and end and end <= start:
|
|
self.add_error('end', 'End time must be after the start time.')
|
|
|
|
recurrence_start_date = cleaned_data.get('recurrence_start_date')
|
|
recurrence_end_date = cleaned_data.get('recurrence_end_date')
|
|
recurrence_weekday = cleaned_data.get('recurrence_weekday')
|
|
recurrence_requested = any([recurrence_start_date, recurrence_end_date, recurrence_weekday])
|
|
|
|
if recurrence_requested:
|
|
if not recurrence_start_date:
|
|
self.add_error('recurrence_start_date', 'Enter the first date for the recurring series.')
|
|
if not recurrence_end_date:
|
|
self.add_error('recurrence_end_date', 'Enter the last date for the recurring series.')
|
|
if not recurrence_weekday:
|
|
self.add_error('recurrence_weekday', 'Choose which weekday should repeat each week.')
|
|
|
|
if recurrence_start_date and recurrence_end_date and recurrence_end_date < recurrence_start_date:
|
|
self.add_error('recurrence_end_date', 'The recurring series must end on or after the start date.')
|
|
|
|
if recurrence_start_date and recurrence_end_date and recurrence_weekday:
|
|
weekday_index = int(recurrence_weekday)
|
|
days_until_first = (weekday_index - recurrence_start_date.weekday()) % 7
|
|
first_occurrence = recurrence_start_date + timedelta(days=days_until_first)
|
|
if first_occurrence > recurrence_end_date:
|
|
self.add_error('recurrence_weekday', 'No selected weekday falls inside that recurrence date range.')
|
|
|
|
return cleaned_data
|