Doctorrick's picture
Update app.py from anycoder
56b2b0b verified
import gradio as gr
import json
import base64
from datetime import datetime
import os
# --- Utility Functions ---
def generate_theme_preview(primary_color, secondary_color, accent_color, background_color,
header_style, animation_type, layout_type, enable_woocommerce,
gallery_columns, show_videos, contact_form_fields):
"""Generate a live HTML/CSS preview of the WordPress theme"""
# Determine font based on layout
font_family = "'Inter', sans-serif"
if layout_type == "modern":
font_family = "'Outfit', sans-serif" # Modern geometric font for 3D printing
elif layout_type == "clean":
font_family = "'Roboto', sans-serif"
# CSS Generation
css = f"""
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;600;800&family=Outfit:wght@300;500;700&family=Roboto:wght@400;500&display=swap');
:root {{
--primary: {primary_color};
--secondary: {secondary_color};
--accent: {accent_color};
--bg: {background_color};
}}
.wp-theme-preview {{
font-family: {font_family};
background-color: var(--bg);
color: #333;
overflow: hidden;
border-radius: 12px;
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
position: relative;
}}
/* Header Styles */
.theme-header {{
padding: 2rem;
color: white;
position: relative;
overflow: hidden;
transition: all 0.3s ease;
}}
.header-gradient {{ background: linear-gradient(135deg, var(--primary), var(--secondary)); }}
.header-solid {{ background: var(--primary); }}
.header-glass {{
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
border-bottom: 1px solid rgba(255,255,255,0.2);
color: var(--primary);
}}
.logo {{
font-size: 1.8rem;
font-weight: 800;
letter-spacing: -0.5px;
display: flex;
align-items: center;
gap: 10px;
}}
.nav-menu {{
display: flex;
gap: 20px;
margin-top: 1rem;
font-weight: 500;
}}
.nav-menu a {{
color: inherit;
text-decoration: none;
opacity: 0.9;
transition: 0.2s;
}}
.nav-menu a:hover {{ opacity: 1; transform: translateY(-2px); }}
/* Hero Section */
.hero {{
padding: 4rem 2rem;
text-align: center;
animation: {animation_type} 0.8s ease-out;
}}
.hero h2 {{
font-size: 2.5rem;
margin-bottom: 1rem;
background: -webkit-linear-gradient(45deg, var(--primary), var(--accent));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
}}
/* Product Grid */
.products-grid {{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 2rem;
padding: 2rem;
}}
.product-card {{
background: white;
border-radius: 16px;
padding: 1rem;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
transition: transform 0.3s ease, box-shadow 0.3s ease;
animation: {animation_type} 0.6s ease-out backwards;
}}
.product-card:hover {{
transform: translateY(-10px);
box-shadow: 0 15px 30px rgba(0,0,0,0.1);
border: 2px solid var(--accent);
}}
.product-img {{
width: 100%;
height: 150px;
background: #f0f0f0;
border-radius: 8px;
margin-bottom: 1rem;
object-fit: cover;
}}
.price-tag {{
color: var(--accent);
font-weight: 800;
font-size: 1.2rem;
}}
.btn {{
background: var(--primary);
color: white;
border: none;
padding: 8px 16px;
border-radius: 6px;
cursor: pointer;
width: 100%;
margin-top: 10px;
font-weight: 600;
transition: 0.2s;
}}
.btn:hover {{ background: var(--accent); }}
/* Gallery */
.gallery {{
display: grid;
grid-template-columns: repeat({gallery_columns}, 1fr);
gap: 10px;
padding: 2rem;
}}
.gallery-item {{
aspect-ratio: 1;
background: #ddd;
border-radius: 8px;
overflow: hidden;
}}
/* Contact Form */
.contact-section {{
background: white;
margin: 2rem;
padding: 2rem;
border-radius: 16px;
border-left: 5px solid var(--accent);
}}
.form-input {{
width: 100%;
padding: 10px;
margin-bottom: 10px;
border: 1px solid #eee;
border-radius: 6px;
}}
/* Animations */
@keyframes fadeInUp {{ from {{ opacity: 0; transform: translateY(20px); }} to {{ opacity: 1; transform: translateY(0); }} }}
@keyframes slideInLeft {{ from {{ opacity: 0; transform: translateX(-50px); }} to {{ opacity: 1; transform: translateX(0); }} }}
@keyframes bounceIn {{ 0% {{ transform: scale(0.3); opacity: 0; }} 50% {{ transform: scale(1.05); }} 70% {{ transform: scale(0.9); }} 100% {{ transform: scale(1); opacity: 1; }} }}
@keyframes pulse {{ 0% {{ transform: scale(1); }} 50% {{ transform: scale(1.02); }} 100% {{ transform: scale(1); }} }}
</style>
"""
# HTML Structure
html = f"""
<div class="wp-theme-preview">
<header class="theme-header header-{header_style}">
<div class="logo">
<span style="font-size: 1.5em">🧊</span> 3D PRINT <span style="color: {accent_color}">PRO</span>
</div>
<nav class="nav-menu">
<a href="#">Tienda</a>
<a href="#">Filamentos</a>
<a href="#">Servicios 3D</a>
<a href="#">Contacto</a>
{'<a href="#" style="background:rgba(255,255,255,0.2); padding:2px 10px; border-radius:20px;">🛒 2</a>' if enable_woocommerce else ''}
</nav>
</header>
<div class="hero">
<h2>Impresión 3D de Alta Precisión</h2>
<p style="margin-bottom: 2rem; color: #666;">Diseños personalizados, prototipos rápidos y arte en PLA/Resina.</p>
<button class="btn" style="width: auto; padding: 12px 30px; border-radius: 30px; background: {accent_color}">
Ver Catálogo
</button>
</div>
<div class="products-grid">
<div class="product-card" style="animation-delay: 0.1s">
<img src="https://placehold.co/400x300/333/FFF?text=Estatua+PLA" class="product-img" alt="Product">
<h3>Figura Coleccionable</h3>
<div class="price-tag">$45.00</div>
<button class="btn">Añadir al Carrito</button>
</div>
<div class="product-card" style="animation-delay: 0.2s">
<img src="https://placehold.co/400x300/666/FFF?text=Pieza+Mecánica" class="product-img" alt="Product">
<h3>Engranaje Nylon</h3>
<div class="price-tag">$12.50</div>
<button class="btn">Añadir al Carrito</button>
</div>
<div class="product-card" style="animation-delay: 0.3s">
<img src="https://placehold.co/400x300/444/FFF?text=Jarrón+Voronoi" class="product-img" alt="Product">
<h3>Jarrón Voronoi</h3>
<div class="price-tag">$28.99</div>
<button class="btn">Añadir al Carrito</button>
</div>
</div>
{'<div class="gallery">' + ''.join([f'<div class="gallery-item"><img src="https://placehold.co/200/eee/ccc?text=Print+{i+1}" style="width:100%;height:100%;object-fit:cover;"></div>' for i in range(gallery_columns)]) + '</div>' if gallery_columns > 0 else ''}
{f'<div style="padding: 2rem;"><h3 style="text-align:center; margin-bottom:1rem;">Proceso de Impresión</h3><div style="background:#000; height:200px; border-radius:12px; display:flex; align-items:center; justify-content:center; color:white;">▶ Video Embed Placeholder</div></div>' if show_videos else ''}
<div class="contact-section">
<h3 style="color: {primary_color}">Solicita tu Presupuesto</h3>
{'<input type="text" placeholder="Nombre" class="form-input">' if "name" in contact_form_fields else ''}
{'<input type="email" placeholder="Email" class="form-input">' if "email" in contact_form_fields else ''}
{'<input type="text" placeholder="Teléfono" class="form-input">' if "phone" in contact_form_fields else ''}
{'<textarea placeholder="Describe tu proyecto 3D..." class="form-input" rows="3"></textarea>' if "message" in contact_form_fields else ''}
<button class="btn">Enviar Solicitud</button>
</div>
<footer style="background: #222; color: white; padding: 2rem; text-align: center; margin-top: 2rem;">
<p>© 2024 3D Print Store. Theme generated by Anycoder.</p>
</footer>
</div>
"""
# Configuration Object
config_data = {
"theme_name": "3D Print Store Theme",
"version": "1.0.0",
"colors": {
"primary": primary_color,
"secondary": secondary_color,
"accent": accent_color,
"background": background_color
},
"layout": {
"header": header_style,
"animation": animation_type,
"font": layout_type
},
"modules": {
"woocommerce": enable_woocommerce,
"gallery_cols": gallery_columns,
"video_enabled": show_videos,
"contact_fields": contact_form_fields
}
}
return css + html, config_data
def generate_woo_php():
return """<?php
// Add to your theme's functions.php
function theme_add_woocommerce_support() {
add_theme_support('woocommerce');
add_theme_support('wc-product-gallery-zoom');
add_theme_support('wc-product-gallery-lightbox');
add_theme_support('wc-product-gallery-slider');
}
add_action('after_setup_theme', 'theme_add_woocommerce_support');
// Custom 3D Print Badge
add_action('woocommerce_before_shop_loop_item_title', 'add_3d_badge', 10);
function add_3d_badge() {
echo '<span class="badge-3d">3D PRINTED</span>';
}
?>"""
def export_theme_config(config_data):
# For Gradio 6, we can write to a temp file and return the path
filename = "theme_config.json"
with open(filename, "w") as f:
json.dump(config_data, f, indent=4)
return filename
# --- Gradio Application ---
with gr.Blocks() as demo:
gr.Markdown(
"""
# 🎨 WordPress Theme Builder: 3D Print Store Edition
<a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank" style="text-decoration: none;">
<span style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 8px 16px;
border-radius: 20px; font-weight: 600; font-size: 0.9em; box-shadow: 0 4px 15px rgba(0,0,0,0.2);">
Built with anycoder
</span>
</a>
Diseña un tema **vibrante, moderno y optimizado** para vender productos impresos en 3D.
"""
)
with gr.Row():
with gr.Column(scale=1):
with gr.Tabs():
with gr.TabItem("🎨 Colores & Estilo"):
gr.Markdown("### Paleta de Colores 'Llamativa'")
primary_col = gr.ColorPicker(label="Primario (Marca)", value="#6366f1")
secondary_col = gr.ColorPicker(label="Secundario (Gradientes)", value="#ec4899")
accent_col = gr.ColorPicker(label="Acento (Botones/Precios)", value="#f43f5e")
bg_col = gr.ColorPicker(label="Fondo (Cuerpo)", value="#f8fafc")
gr.Markdown("### Estructura Visual")
header_style = gr.Dropdown(
choices=["gradient", "solid", "glass"],
value="gradient",
label="Estilo del Header"
)
layout_type = gr.Radio(
choices=["modern", "clean"],
value="modern",
label="Tipografía y Layout"
)
with gr.TabItem("⚡ Animaciones & Módulos"):
animation_type = gr.Dropdown(
choices=["fadeInUp", "slideInLeft", "bounceIn", "pulse"],
value="fadeInUp",
label="Animación de Entrada"
)
enable_woo = gr.Checkbox(label="Activar WooCommerce", value=True)
show_videos = gr.Checkbox(label="Sección de Video (Proceso de Impresión)", value=True)
gallery_cols = gr.Slider(minimum=2, maximum=6, step=1, value=4, label="Columnas Galería")
with gr.TabItem("📧 Contacto"):
contact_fields = gr.CheckboxGroup(
choices=["name", "email", "phone", "message"],
value=["name", "email", "message"],
label="Campos del Formulario"
)
with gr.Accordion("💻 Código PHP (WooCommerce)", open=False):
gr.Code(value=generate_woo_php(), language="php", interactive=False)
btn_generate = gr.Button("🔄 Actualizar Diseño", variant="primary")
btn_export = gr.Button("💾 Exportar Configuración JSON")
file_output = gr.File(label="Descargar Tema Config")
with gr.Column(scale=2):
gr.Markdown("### 👁️ Vista Previa en Vivo (HTML/CSS)")
preview_html = gr.HTML(label="Theme Preview")
json_output = gr.JSON(label="JSON Data", visible=False)
# Event Listeners
inputs = [
primary_col, secondary_col, accent_col, bg_col,
header_style, animation_type, layout_type, enable_woo,
gallery_cols, show_videos, contact_fields
]
# Initial Load
demo.load(
fn=generate_theme_preview,
inputs=inputs,
outputs=[preview_html, json_output],
api_visibility="private"
)
# Update on Change
for inp in inputs:
inp.change(
fn=generate_theme_preview,
inputs=inputs,
outputs=[preview_html, json_output],
api_visibility="private"
)
# Button Click
btn_generate.click(
fn=generate_theme_preview,
inputs=inputs,
outputs=[preview_html, json_output],
api_visibility="public"
)
# Export
btn_export.click(
fn=export_theme_config,
inputs=[json_output],
outputs=[file_output],
api_visibility="public"
)
# Launch App
demo.launch(
theme=gr.themes.Soft(
primary_hue="indigo",
secondary_hue="pink",
neutral_hue="slate",
font=gr.themes.GoogleFont("Inter")
).set(
button_primary_background_fill="*primary_600",
button_primary_background_fill_hover="*primary_700",
block_shadow="*shadow_drop_lg"
),
footer_links=[
{"label": "Built with anycoder", "url": "https://huggingface.co/spaces/akhaliq/anycoder"},
{"label": "WordPress.org", "url": "https://wordpress.org"},
{"label": "WooCommerce", "url": "https://woocommerce.com"}
]
)