Implementación inicial del sistema de automatización de redes sociales
- Estructura completa del proyecto con FastAPI - Modelos de base de datos (productos, servicios, posts, calendario, interacciones) - Publishers para X, Threads, Instagram, Facebook - Generador de contenido con DeepSeek API - Worker de Celery con tareas programadas - Dashboard básico con templates HTML - Docker Compose para despliegue - Documentación completa Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
118
app/api/routes/dashboard.py
Normal file
118
app/api/routes/dashboard.py
Normal file
@@ -0,0 +1,118 @@
|
||||
"""
|
||||
API Routes para el Dashboard.
|
||||
"""
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from fastapi import APIRouter, Depends, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
from fastapi.templating import Jinja2Templates
|
||||
from sqlalchemy.orm import Session
|
||||
from sqlalchemy import func
|
||||
|
||||
from app.core.database import get_db
|
||||
from app.models.post import Post
|
||||
from app.models.interaction import Interaction
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
templates = Jinja2Templates(directory="dashboard/templates")
|
||||
|
||||
|
||||
@router.get("/", response_class=HTMLResponse)
|
||||
async def dashboard_home(request: Request, db: Session = Depends(get_db)):
|
||||
"""Página principal del dashboard."""
|
||||
# Estadísticas
|
||||
now = datetime.utcnow()
|
||||
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
week_start = today_start - timedelta(days=now.weekday())
|
||||
|
||||
stats = {
|
||||
"posts_today": db.query(Post).filter(
|
||||
Post.published_at >= today_start
|
||||
).count(),
|
||||
"posts_week": db.query(Post).filter(
|
||||
Post.published_at >= week_start
|
||||
).count(),
|
||||
"pending_approval": db.query(Post).filter(
|
||||
Post.status == "pending_approval"
|
||||
).count(),
|
||||
"scheduled": db.query(Post).filter(
|
||||
Post.status == "scheduled"
|
||||
).count(),
|
||||
"interactions_pending": db.query(Interaction).filter(
|
||||
Interaction.responded == False,
|
||||
Interaction.is_archived == False
|
||||
).count()
|
||||
}
|
||||
|
||||
# Posts pendientes
|
||||
pending_posts = db.query(Post).filter(
|
||||
Post.status == "pending_approval"
|
||||
).order_by(Post.scheduled_at.asc()).limit(5).all()
|
||||
|
||||
# Próximas publicaciones
|
||||
scheduled_posts = db.query(Post).filter(
|
||||
Post.status == "scheduled",
|
||||
Post.scheduled_at >= now
|
||||
).order_by(Post.scheduled_at.asc()).limit(5).all()
|
||||
|
||||
# Interacciones recientes
|
||||
recent_interactions = db.query(Interaction).filter(
|
||||
Interaction.responded == False
|
||||
).order_by(Interaction.interaction_at.desc()).limit(5).all()
|
||||
|
||||
return templates.TemplateResponse("index.html", {
|
||||
"request": request,
|
||||
"stats": stats,
|
||||
"pending_posts": [p.to_dict() for p in pending_posts],
|
||||
"scheduled_posts": [p.to_dict() for p in scheduled_posts],
|
||||
"recent_interactions": [i.to_dict() for i in recent_interactions]
|
||||
})
|
||||
|
||||
|
||||
@router.get("/posts", response_class=HTMLResponse)
|
||||
async def dashboard_posts(request: Request, db: Session = Depends(get_db)):
|
||||
"""Página de gestión de posts."""
|
||||
posts = db.query(Post).order_by(Post.created_at.desc()).limit(50).all()
|
||||
|
||||
return templates.TemplateResponse("posts.html", {
|
||||
"request": request,
|
||||
"posts": [p.to_dict() for p in posts]
|
||||
})
|
||||
|
||||
|
||||
@router.get("/calendar", response_class=HTMLResponse)
|
||||
async def dashboard_calendar(request: Request):
|
||||
"""Página de calendario."""
|
||||
return templates.TemplateResponse("calendar.html", {
|
||||
"request": request
|
||||
})
|
||||
|
||||
|
||||
@router.get("/interactions", response_class=HTMLResponse)
|
||||
async def dashboard_interactions(request: Request, db: Session = Depends(get_db)):
|
||||
"""Página de interacciones."""
|
||||
interactions = db.query(Interaction).filter(
|
||||
Interaction.is_archived == False
|
||||
).order_by(Interaction.interaction_at.desc()).limit(50).all()
|
||||
|
||||
return templates.TemplateResponse("interactions.html", {
|
||||
"request": request,
|
||||
"interactions": [i.to_dict() for i in interactions]
|
||||
})
|
||||
|
||||
|
||||
@router.get("/products", response_class=HTMLResponse)
|
||||
async def dashboard_products(request: Request):
|
||||
"""Página de productos."""
|
||||
return templates.TemplateResponse("products.html", {
|
||||
"request": request
|
||||
})
|
||||
|
||||
|
||||
@router.get("/services", response_class=HTMLResponse)
|
||||
async def dashboard_services(request: Request):
|
||||
"""Página de servicios."""
|
||||
return templates.TemplateResponse("services.html", {
|
||||
"request": request
|
||||
})
|
||||
Reference in New Issue
Block a user