from datetime import datetime from typing import Optional from pydantic import BaseModel, ConfigDict, EmailStr, field_validator from app.models import ProjectStatus # ---------- Auth ---------- class Token(BaseModel): access_token: str token_type: str = "bearer" class LoginRequest(BaseModel): username: str password: str # ---------- Brand ---------- class BrandBase(BaseModel): name: str = "" logo: str = "" hero: str = "" contact_bg: str = "" phone: str = "" phone_href: str = "" email: str = "" address: str = "" class BrandOut(BrandBase): model_config = ConfigDict(from_attributes=True) id: int class BrandUpdate(BrandBase): pass # ---------- Service ---------- class ServiceBase(BaseModel): title: str desc: str icon: str order: int = 0 class ServiceCreate(ServiceBase): pass class ServiceUpdate(BaseModel): title: Optional[str] = None desc: Optional[str] = None icon: Optional[str] = None order: Optional[int] = None class ServiceOut(ServiceBase): model_config = ConfigDict(from_attributes=True) id: int # ---------- Project ---------- class ProjectBase(BaseModel): slug: str title: str location: str year: str status: ProjectStatus image: str gallery: list[str] = [] area: str floors: str units: str client: str summary: str body: list[str] = [] order: int = 0 class ProjectCreate(ProjectBase): pass class ProjectUpdate(BaseModel): slug: Optional[str] = None title: Optional[str] = None location: Optional[str] = None year: Optional[str] = None status: Optional[ProjectStatus] = None image: Optional[str] = None gallery: Optional[list[str]] = None area: Optional[str] = None floors: Optional[str] = None units: Optional[str] = None client: Optional[str] = None summary: Optional[str] = None body: Optional[list[str]] = None order: Optional[int] = None class ProjectOut(ProjectBase): model_config = ConfigDict(from_attributes=True) id: int # ---------- Stat ---------- class StatBase(BaseModel): value: int suffix: str = "" label: str order: int = 0 class StatCreate(StatBase): pass class StatUpdate(BaseModel): value: Optional[int] = None suffix: Optional[str] = None label: Optional[str] = None order: Optional[int] = None class StatOut(StatBase): model_config = ConfigDict(from_attributes=True) id: int # ---------- Timeline ---------- class TimelineBase(BaseModel): year: str title: str desc: str image: str order: int = 0 class TimelineCreate(TimelineBase): pass class TimelineUpdate(BaseModel): year: Optional[str] = None title: Optional[str] = None desc: Optional[str] = None image: Optional[str] = None order: Optional[int] = None class TimelineOut(TimelineBase): model_config = ConfigDict(from_attributes=True) id: int # ---------- WhyUs ---------- class WhyUsBase(BaseModel): title: str desc: str order: int = 0 class WhyUsCreate(WhyUsBase): pass class WhyUsUpdate(BaseModel): title: Optional[str] = None desc: Optional[str] = None order: Optional[int] = None class WhyUsOut(WhyUsBase): model_config = ConfigDict(from_attributes=True) id: int # ---------- Testimonial ---------- class TestimonialBase(BaseModel): name: str role: str quote: str order: int = 0 class TestimonialCreate(TestimonialBase): pass class TestimonialUpdate(BaseModel): name: Optional[str] = None role: Optional[str] = None quote: Optional[str] = None order: Optional[int] = None class TestimonialOut(TestimonialBase): model_config = ConfigDict(from_attributes=True) id: int # ---------- Team ---------- class TeamMemberBase(BaseModel): name: str role: str bio: str photo: str = "" order: int = 0 class TeamMemberCreate(TeamMemberBase): pass class TeamMemberUpdate(BaseModel): name: Optional[str] = None role: Optional[str] = None bio: Optional[str] = None photo: Optional[str] = None order: Optional[int] = None class TeamMemberOut(TeamMemberBase): model_config = ConfigDict(from_attributes=True) id: int # ---------- Article ---------- class ArticleBase(BaseModel): slug: str title: str date: str category: str image: str read: str excerpt: str body: list[str] = [] order: int = 0 class ArticleCreate(ArticleBase): pass class ArticleUpdate(BaseModel): slug: Optional[str] = None title: Optional[str] = None date: Optional[str] = None category: Optional[str] = None image: Optional[str] = None read: Optional[str] = None excerpt: Optional[str] = None body: Optional[list[str]] = None order: Optional[int] = None class ArticleOut(ArticleBase): model_config = ConfigDict(from_attributes=True) id: int # ---------- FAQ ---------- class FaqBase(BaseModel): q: str a: str order: int = 0 class FaqCreate(FaqBase): pass class FaqUpdate(BaseModel): q: Optional[str] = None a: Optional[str] = None order: Optional[int] = None class FaqOut(FaqBase): model_config = ConfigDict(from_attributes=True) id: int # ---------- Contact ---------- class ContactCreate(BaseModel): name: str = "" phone: str note: str = "" @field_validator("phone") @classmethod def phone_min_length(cls, v: str) -> str: if len(v.strip()) < 8: raise ValueError("شماره تلفن معتبر نیست") return v.strip() class ContactOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: int name: str phone: str note: str is_read: bool created_at: datetime class ContactUpdate(BaseModel): is_read: Optional[bool] = None # ---------- Newsletter ---------- class NewsletterCreate(BaseModel): email: EmailStr class NewsletterOut(BaseModel): model_config = ConfigDict(from_attributes=True) id: int email: str created_at: datetime