from __future__ import annotations from flask_wtf import FlaskForm from flask_wtf.file import FileAllowed, FileField from wtforms import ( BooleanField, DateField, IntegerField, PasswordField, StringField, SelectField, SubmitField, TextAreaField, ) from wtforms.validators import DataRequired, EqualTo, Length, NumberRange, Optional, Regexp, ValidationError from .models import User EMAIL_LIKE = Regexp(r"^[^@\s]+@[^@\s]+\.[^@\s]+$", message="Bitte gib eine gültige E-Mail-Adresse ein.") class LoginForm(FlaskForm): email = StringField("E-Mail", validators=[DataRequired(), EMAIL_LIKE, Length(max=255)]) password = PasswordField("Passwort", validators=[DataRequired(), Length(min=6, max=128)]) remember_me = BooleanField("Angemeldet bleiben") submit = SubmitField("Einloggen") class RegisterForm(FlaskForm): name = StringField("Name", validators=[DataRequired(), Length(min=2, max=120)]) email = StringField("E-Mail", validators=[DataRequired(), EMAIL_LIKE, Length(max=255)]) password = PasswordField("Passwort", validators=[DataRequired(), Length(min=6, max=128)]) password_confirm = PasswordField( "Passwort wiederholen", validators=[DataRequired(), EqualTo("password", message="Die Passwörter stimmen nicht überein.")], ) submit = SubmitField("Konto erstellen") def validate_email(self, field) -> None: if User.query.filter_by(email=field.data.lower().strip()).first(): raise ValidationError("Diese E-Mail-Adresse ist bereits vergeben.") class TaskForm(FlaskForm): title = StringField("Titel", validators=[DataRequired(), Length(min=2, max=160)]) description = TextAreaField("Beschreibung", validators=[Optional(), Length(max=2000)]) default_points = IntegerField("Punkte", validators=[DataRequired(), NumberRange(min=1, max=500)], default=10) assigned_user_id = SelectField("Zugewiesen an", coerce=int, validators=[DataRequired()]) due_date = DateField("Fälligkeitsdatum", format="%Y-%m-%d", validators=[DataRequired()]) recurrence_interval_value = IntegerField( "Intervallwert", validators=[Optional(), NumberRange(min=1, max=365)], default=1, ) recurrence_interval_unit = SelectField( "Wiederholung", choices=[ ("none", "Einmalig"), ("days", "Alle X Tage"), ("weeks", "Alle X Wochen"), ("months", "Alle X Monate"), ], validators=[DataRequired()], ) active = BooleanField("Vorlage aktiv", default=True) submit = SubmitField("Speichern") def validate(self, extra_validators=None): valid = super().validate(extra_validators=extra_validators) if not valid: return False if self.recurrence_interval_unit.data != "none" and not self.recurrence_interval_value.data: self.recurrence_interval_value.errors.append("Bitte gib einen Intervallwert an.") return False return True class SettingsProfileForm(FlaskForm): name = StringField("Name", validators=[DataRequired(), Length(min=2, max=120)]) email = StringField("E-Mail", validators=[DataRequired(), EMAIL_LIKE, Length(max=255)]) password = PasswordField("Neues Passwort", validators=[Optional(), Length(min=6, max=128)]) avatar = FileField( "Avatar", validators=[Optional(), FileAllowed(["png", "jpg", "jpeg", "gif", "webp", "svg"], "Bitte ein Bild hochladen.")], ) notification_task_due_enabled = BooleanField("Push bei bald fälligen Aufgaben") notification_monthly_winner_enabled = BooleanField("Push zum Monatssieger") submit = SubmitField("Einstellungen speichern") def __init__(self, original_email: str | None = None, *args, **kwargs): super().__init__(*args, **kwargs) self.original_email = original_email def validate_email(self, field) -> None: value = field.data.lower().strip() if value == (self.original_email or "").lower().strip(): return if User.query.filter_by(email=value).first(): raise ValidationError("Diese E-Mail-Adresse wird bereits verwendet.")