from django import forms from .models import PropertyEntry, PropertyFlag, PropertySuggestion class BootstrapFormMixin: def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) for field in self.fields.values(): widget = field.widget if widget.__class__.__name__ == "HiddenInput": continue current = widget.attrs.get("class", "") if widget.__class__.__name__ == "Select": widget.attrs["class"] = f"form-select {current}".strip() elif widget.__class__.__name__ == "Textarea": widget.attrs["class"] = f"form-control {current}".strip() else: widget.attrs["class"] = f"form-control {current}".strip() class PropertyLocationForm(BootstrapFormMixin, forms.ModelForm): latitude = forms.DecimalField(required=False, max_digits=9, decimal_places=6, widget=forms.HiddenInput()) longitude = forms.DecimalField(required=False, max_digits=9, decimal_places=6, widget=forms.HiddenInput()) class Meta: model = PropertyEntry fields = ["address", "latitude", "longitude", "phone", "email", "listing_type"] widgets = { "address": forms.TextInput(attrs={"placeholder": "Type or paste the full address", "autocomplete": "street-address", "data-manual-address": "true"}), "phone": forms.TextInput(attrs={"placeholder": "+34 600 000 000"}), "email": forms.EmailInput(attrs={"placeholder": "owner@example.com"}), "listing_type": forms.Select(), } def clean(self): cleaned = super().clean() address = cleaned.get("address") latitude = cleaned.get("latitude") longitude = cleaned.get("longitude") if not address and (latitude is None or longitude is None): raise forms.ValidationError("Type or paste an address, or allow location, so this property can be placed on the pinboard.") return cleaned class PropertyPhotoForm(BootstrapFormMixin, forms.ModelForm): class Meta: model = PropertyEntry fields = ["photo", "address", "phone", "email", "listing_type"] widgets = { "address": forms.TextInput(attrs={"placeholder": "Optional if the photo contains GPS or visible text"}), "phone": forms.TextInput(attrs={"placeholder": "Optional contact phone"}), "email": forms.EmailInput(attrs={"placeholder": "Optional contact email"}), "listing_type": forms.Select(), } def clean_photo(self): photo = self.cleaned_data.get("photo") if not photo: raise forms.ValidationError("Choose a property photo to upload.") if photo.size > 12 * 1024 * 1024: raise forms.ValidationError("Please upload an image under 12MB for this MVP.") return photo class PropertySuggestionForm(BootstrapFormMixin, forms.ModelForm): class Meta: model = PropertySuggestion fields = ["address", "phone", "email", "listing_type", "note"] widgets = { "address": forms.TextInput(attrs={"placeholder": "Correct or missing address"}), "phone": forms.TextInput(attrs={"placeholder": "Correct or missing phone"}), "email": forms.EmailInput(attrs={"placeholder": "Correct or missing email"}), "listing_type": forms.Select(), "note": forms.Textarea(attrs={"rows": 3, "placeholder": "What should be updated?"}), } def clean(self): cleaned = super().clean() if not any(cleaned.get(field) for field in self.fields): raise forms.ValidationError("Add at least one suggested detail.") return cleaned class PropertyFlagForm(BootstrapFormMixin, forms.ModelForm): class Meta: model = PropertyFlag fields = ["reason"] widgets = { "reason": forms.TextInput(attrs={"placeholder": "Duplicate, spam, private info, already removed..."}), }