feat: features 025-032 - favoritos, contatos, trabalhe-conosco, area-cliente, navbar, hero-light-dark, performance-homepage
Some checks failed
CI/CD → Deploy via SSH / Build & Push Docker Images (push) Successful in 1m0s
CI/CD → Deploy via SSH / Deploy via SSH (push) Successful in 4m35s
CI/CD → Deploy via SSH / Validate HTTPS & Endpoints (push) Failing after 46s

- feat(025): favoritos locais com FavoritesContext, HeartButton, PublicFavoritesPage
- feat(026): central de contatos admin (leads/contatos unificados)
- feat(027): configuração da página de contato via admin
- feat(028): trabalhe conosco - candidaturas com upload e admin
- feat(029): UX área do cliente - visitas, comparação, perfil
- feat(030): navbar UX - menu mobile, ThemeToggle, useFavorites
- feat(031): hero light/dark - imagens separadas por tema, upload, preview, seed
- feat(032): performance homepage - Promise.all parallel fetches, sessionStorage cache,
  preload hero image, loading=lazy nos cards, useInView hook, will-change carrossel,
  keyframes em index.css, AgentsCarousel e HomeScrollScene via props
- fix: light mode HomeScrollScene - gradiente, cores de texto, scroll hint

migrations: g1h2i3j4k5l6 (source em leads), h1i2j3k4l5m6 (contact_config),
            i1j2k3l4m5n6 (job_applications), j2k3l4m5n6o7 (hero theme images)
This commit is contained in:
MatheusAlves96 2026-04-22 22:35:17 -03:00
parent 6ef5a7a17e
commit cf5603243c
106 changed files with 11927 additions and 1367 deletions

View file

@ -83,7 +83,9 @@ def list_properties():
neighborhood_ids_raw = args.get("neighborhood_ids", "")
if neighborhood_ids_raw:
try:
neighborhood_ids_list = [int(x) for x in neighborhood_ids_raw.split(",") if x.strip()]
neighborhood_ids_list = [
int(x) for x in neighborhood_ids_raw.split(",") if x.strip()
]
except ValueError:
neighborhood_ids_list = []
if neighborhood_ids_list:
@ -171,16 +173,14 @@ def list_properties():
if q_raw:
pattern = f"%{q_raw}%"
NeighborhoodAlias = aliased(Neighborhood)
query = (
query
.outerjoin(NeighborhoodAlias, Property.neighborhood_id == NeighborhoodAlias.id)
.filter(
or_(
Property.title.ilike(pattern),
Property.address.ilike(pattern),
Property.code.ilike(pattern),
NeighborhoodAlias.name.ilike(pattern),
)
query = query.outerjoin(
NeighborhoodAlias, Property.neighborhood_id == NeighborhoodAlias.id
).filter(
or_(
Property.title.ilike(pattern),
Property.address.ilike(pattern),
Property.code.ilike(pattern),
NeighborhoodAlias.name.ilike(pattern),
)
)
@ -203,10 +203,7 @@ def list_properties():
pages = math.ceil(total / per_page) if total > 0 else 1
props = (
query.order_by(sort_order)
.offset((page - 1) * per_page)
.limit(per_page)
.all()
query.order_by(sort_order).offset((page - 1) * per_page).limit(per_page).all()
)
result = PaginatedPropertiesOut(
@ -248,6 +245,46 @@ def contact_property(slug: str):
email=lead_in.email,
phone=lead_in.phone,
message=lead_in.message,
source=lead_in.source or "imovel",
source_detail=lead_in.source_detail or prop.title,
)
db.session.add(lead)
db.session.commit()
return (
jsonify(
ContactLeadCreatedOut(
id=lead.id, message="Mensagem enviada com sucesso!"
).model_dump()
),
201,
)
@properties_bp.post("/contact")
def contact_general():
"""Contato geral (página /contato e /cadastro-residencia)."""
from app.models.lead import ContactLead
from app.schemas.lead import ContactLeadIn, ContactLeadCreatedOut
data = request.get_json(silent=True) or {}
try:
lead_in = ContactLeadIn.model_validate(data)
except ValidationError as exc:
import json as _json
return jsonify({"error": "Dados inválidos", "details": _json.loads(exc.json())}), 422
valid_sources = {"contato", "imovel", "cadastro_residencia"}
source = lead_in.source if lead_in.source in valid_sources else "contato"
lead = ContactLead(
property_id=None,
name=lead_in.name,
email=lead_in.email,
phone=lead_in.phone,
message=lead_in.message,
source=source,
source_detail=lead_in.source_detail,
)
db.session.add(lead)
db.session.commit()