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