greentic-flow-builder 0.1.0

AI-powered Adaptive Card flow builder with visual graph editor and demo runner
Documentation
//! `POST /api/render` — render a single card.
//!
//! Supports two modes:
//!   - preset mode: `{ preset|template, theme?, data }` renders a named preset
//!   - compose mode: `{ sections, theme? }` renders a custom composition
//!
//! Compose mode takes precedence if `sections` is present in the body.

use crate::render;
use crate::template::ComposeSection;
use crate::ui::state::AppState;
use axum::Json;
use axum::extract::State;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use serde::Deserialize;
use serde_json::{Value, json};
use std::sync::Arc;

#[derive(Deserialize)]
pub struct RenderBody {
    #[serde(default, alias = "template")]
    pub preset: Option<String>,
    #[serde(default)]
    pub theme: Option<String>,
    #[serde(default)]
    pub data: Value,
    #[serde(default)]
    pub sections: Option<Vec<ComposeSection>>,
}

pub async fn post_render(
    State(state): State<Arc<AppState>>,
    Json(body): Json<RenderBody>,
) -> impl IntoResponse {
    let result = if let Some(sections) = body.sections {
        render::render_compose(&state.registry, &sections, body.theme.as_deref())
    } else if let Some(preset) = body.preset {
        render::render_preset(&state.registry, &preset, body.theme.as_deref(), &body.data)
    } else {
        return (
            StatusCode::BAD_REQUEST,
            Json(json!({
                "error": "request must include 'preset'/'template' or 'sections' for compose mode"
            })),
        )
            .into_response();
    };

    match result {
        Ok(response) => Json(json!({
            "card": response.card,
            "host_config": response.host_config,
            "preset": response.preset,
            "theme": response.theme,
        }))
        .into_response(),
        Err(e) => (
            StatusCode::BAD_REQUEST,
            Json(json!({"error": e.to_string()})),
        )
            .into_response(),
    }
}