115 lines
3.8 KiB
Python
115 lines
3.8 KiB
Python
from django import forms
|
|
from django.core.exceptions import ValidationError
|
|
|
|
from apps.pages.contact_uploads import validate_contact_attachments
|
|
|
|
from .models import ProjectBrief
|
|
|
|
WIZARD_STEPS = [
|
|
{
|
|
"id": "basics",
|
|
"title": "Project basics",
|
|
"subtitle": "Give your project a name and category.",
|
|
"fields": ["title", "category"],
|
|
},
|
|
{
|
|
"id": "scope",
|
|
"title": "Description & goals",
|
|
"subtitle": "Describe the project scope, context, and the outcomes you expect.",
|
|
"fields": ["description"],
|
|
},
|
|
{
|
|
"id": "timeline",
|
|
"title": "Budget & timeline",
|
|
"subtitle": "Share your budget range and target deadline.",
|
|
"fields": ["budget_range", "desired_deadline"],
|
|
},
|
|
{
|
|
"id": "references",
|
|
"title": "References & files",
|
|
"subtitle": "Add links and supporting files, then review your brief.",
|
|
"fields": ["reference_links", "attachments"],
|
|
},
|
|
]
|
|
|
|
REQUIRED_FIELDS = ("title",)
|
|
|
|
|
|
class ProjectBriefForm(forms.ModelForm):
|
|
attachments = forms.Field(required=False)
|
|
|
|
class Meta:
|
|
model = ProjectBrief
|
|
fields = [
|
|
"title",
|
|
"category",
|
|
"description",
|
|
"budget_range",
|
|
"desired_deadline",
|
|
"reference_links",
|
|
]
|
|
widgets = {
|
|
"title": forms.TextInput(attrs={"placeholder": "Project title"}),
|
|
"category": forms.Select(),
|
|
"description": forms.Textarea(
|
|
attrs={
|
|
"placeholder": "Describe the project scope, context, and goals",
|
|
"rows": 7,
|
|
}
|
|
),
|
|
"budget_range": forms.Select(),
|
|
"desired_deadline": forms.DateInput(attrs={"type": "date"}),
|
|
"reference_links": forms.Textarea(
|
|
attrs={
|
|
"placeholder": "Links to docs, mockups, repos (one per line)",
|
|
"rows": 3,
|
|
}
|
|
),
|
|
}
|
|
|
|
def __init__(self, *args, file_list=None, **kwargs):
|
|
self.file_list = file_list
|
|
super().__init__(*args, **kwargs)
|
|
optional_choice_fields = {
|
|
"category": "Select a category (optional)",
|
|
"budget_range": "Select a budget range (optional)",
|
|
}
|
|
for field_name, empty_label in optional_choice_fields.items():
|
|
field = self.fields[field_name]
|
|
field.required = False
|
|
field.choices = [("", empty_label)] + list(field.choices)
|
|
for field_name in self.fields:
|
|
self.fields[field_name].required = field_name in REQUIRED_FIELDS
|
|
for field in self.fields.values():
|
|
if isinstance(
|
|
field.widget,
|
|
(forms.TextInput, forms.Textarea, forms.Select, forms.DateInput),
|
|
):
|
|
field.widget.attrs.setdefault("class", "form-control")
|
|
if self.instance and self.instance.pk:
|
|
for field_name in self.fields:
|
|
if self.instance.is_field_locked(field_name):
|
|
self.fields[field_name].disabled = True
|
|
|
|
def clean(self):
|
|
cleaned_data = super().clean()
|
|
try:
|
|
cleaned_data["attachments"] = validate_contact_attachments(self.file_list)
|
|
except ValidationError as exc:
|
|
self.add_error("attachments", exc)
|
|
cleaned_data["attachments"] = []
|
|
return cleaned_data
|
|
|
|
def first_error_step(self):
|
|
for index, step in enumerate(WIZARD_STEPS, start=1):
|
|
for field_name in step["fields"]:
|
|
if field_name in self.errors:
|
|
return index
|
|
return 1
|
|
|
|
def step_for_field(self, field_name):
|
|
for index, step in enumerate(WIZARD_STEPS, start=1):
|
|
if field_name in step["fields"]:
|
|
return index
|
|
return 1
|