Files
stl-repo/static/index.html
Consultoria AS 5aa8d7512a feat: branding PrintForge + logo + dominio 3d.consultoria-as.com
- Nombre de app: PrintForge
- Logo generado: icono + version completa
- Integracion en navbar y favicon de todas las paginas
- QR code apunta a https://3d.consultoria-as.com
- README actualizado con URL de produccion
2026-04-28 04:45:32 +00:00

180 lines
10 KiB
HTML

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PrintForge</title>
<link rel="icon" type="image/png" href="/static/logo-icon.png">
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="/static/css/style.css">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
slate: { 850: '#172033', 950: '#020617' }
}
}
}
}
</script>
</head>
<body class="bg-slate-950 text-slate-100 min-h-screen">
<!-- Navbar -->
<nav class="glass sticky top-0 z-50 border-b border-white/5">
<div class="max-w-7xl mx-auto px-6 py-4 flex items-center justify-between">
<a href="/" class="flex items-center gap-3 group">
<img src="/static/logo-icon.png" alt="PrintForge" class="w-10 h-10 rounded-xl shadow-lg group-hover:scale-110 transition-transform">
<div>
<h1 class="text-xl font-bold bg-gradient-to-r from-cyan-400 to-blue-400 bg-clip-text text-transparent">PrintForge</h1>
<p class="text-xs text-slate-400 -mt-0.5">Forja tus ideas en 3D</p>
</div>
</a>
<button id="theme-toggle" class="p-2.5 rounded-xl bg-slate-800 hover:bg-slate-700 border border-white/10 text-slate-400 hover:text-yellow-400 transition-colors" title="Cambiar tema">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"></path></svg>
</button>
<a href="/upload" class="px-5 py-2.5 rounded-xl bg-gradient-to-r from-cyan-500 to-blue-600 hover:from-cyan-400 hover:to-blue-500 text-white font-semibold text-sm shadow-lg shadow-cyan-500/20 transition-all hover:scale-105 flex items-center gap-2">
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 4v16m8-8H4"></path></svg>
Subir Modelo
</a>
</div>
</nav>
<!-- Main -->
<main class="max-w-7xl mx-auto px-6 py-8 flex gap-8">
<!-- Sidebar -->
<aside class="hidden lg:block w-64 shrink-0">
<div class="glass rounded-2xl p-5 border border-white/5 sticky top-24">
<div class="flex items-center justify-between mb-4">
<h3 class="font-bold text-sm uppercase tracking-wider text-slate-400">Filtros</h3>
<button onclick="resetFilters()" class="text-xs text-cyan-400 hover:text-cyan-300 transition-colors">Limpiar</button>
</div>
<div class="space-y-4">
<div>
<label class="text-xs text-slate-500 mb-1.5 block">Ordenar por</label>
<select id="sort-by" class="w-full px-3 py-2 rounded-lg bg-slate-900/60 border border-white/10 focus:border-cyan-500 focus:outline-none text-sm cursor-pointer">
<option value="newest">Mas nuevos</option>
<option value="oldest">Mas antiguos</option>
<option value="most_downloaded">Mas descargados</option>
<option value="largest">Mas grandes</option>
<option value="most_faces">Mas caras</option>
<option value="highest_rated">Mejor valorados</option>
</select>
</div>
<div>
<label class="text-xs text-slate-500 mb-1.5 block">Caras</label>
<div class="flex gap-2">
<input type="number" id="min-faces" placeholder="Min" class="w-full px-3 py-2 rounded-lg bg-slate-900/60 border border-white/10 focus:border-cyan-500 focus:outline-none text-sm placeholder:text-slate-600">
<input type="number" id="max-faces" placeholder="Max" class="w-full px-3 py-2 rounded-lg bg-slate-900/60 border border-white/10 focus:border-cyan-500 focus:outline-none text-sm placeholder:text-slate-600">
</div>
</div>
<div>
<label class="text-xs text-slate-500 mb-1.5 block">Dimension max (mm)</label>
<div class="flex gap-2">
<input type="number" id="min-dim" placeholder="Min" class="w-full px-3 py-2 rounded-lg bg-slate-900/60 border border-white/10 focus:border-cyan-500 focus:outline-none text-sm placeholder:text-slate-600">
<input type="number" id="max-dim" placeholder="Max" class="w-full px-3 py-2 rounded-lg bg-slate-900/60 border border-white/10 focus:border-cyan-500 focus:outline-none text-sm placeholder:text-slate-600">
</div>
</div>
</div>
<div class="mt-6 pt-5 border-t border-white/5">
<h3 class="font-bold text-sm uppercase tracking-wider text-slate-400 mb-3">Tags</h3>
<div id="tag-cloud" class="flex flex-wrap gap-2">
<p class="text-xs text-slate-600">Cargando...</p>
</div>
</div>
</div>
</aside>
<!-- Content -->
<div class="flex-1 min-w-0">
<!-- Header -->
<div class="mb-6">
<h2 class="text-2xl font-bold mb-1">Galeria de Modelos</h2>
<p class="text-slate-400 text-sm">Explora, visualiza y descarga modelos 3D listos para imprimir.</p>
</div>
<!-- Filters bar -->
<div class="glass rounded-2xl p-4 mb-6 flex flex-wrap gap-3 items-center">
<div class="relative flex-1 min-w-[200px]">
<svg class="absolute left-3 top-1/2 -translate-y-1/2 w-5 h-5 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"></path></svg>
<input type="text" id="search" placeholder="Buscar modelos..." class="w-full pl-10 pr-4 py-2.5 rounded-xl bg-slate-900/60 border border-white/10 focus:border-cyan-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/20 text-sm transition-all placeholder:text-slate-500">
<div id="search-history" class="absolute left-0 right-0 top-full mt-1 z-20"></div>
</div>
<select id="category" class="px-4 py-2.5 rounded-xl bg-slate-900/60 border border-white/10 focus:border-cyan-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/20 text-sm cursor-pointer min-w-[150px]">
<option value="">Todas las categorias</option>
<option value="Arte">Arte</option>
<option value="Herramientas">Herramientas</option>
<option value="Juguetes">Juguetes</option>
<option value="Piezas">Piezas</option>
<option value="Decoracion">Decoracion</option>
<option value="Otros">Otros</option>
</select>
<div class="relative min-w-[160px]">
<svg class="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z"></path></svg>
<input type="text" id="tag" placeholder="Filtrar por tag..." class="w-full pl-9 pr-4 py-2.5 rounded-xl bg-slate-900/60 border border-white/10 focus:border-cyan-500 focus:outline-none focus:ring-2 focus:ring-cyan-500/20 text-sm transition-all placeholder:text-slate-500">
</div>
</div>
<!-- Stats & Actions -->
<div class="flex items-center justify-between mb-4">
<span class="text-sm text-slate-400"><span id="model-count" class="font-bold text-slate-200">0</span> modelos</span>
<button id="btn-select-mode" onclick="toggleSelectionMode()" class="px-3 py-1.5 rounded-lg bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors">
Seleccionar
</button>
</div>
<!-- Selection Bar -->
<div id="selection-bar" class="hidden mb-4 glass rounded-xl p-3 border border-cyan-500/20 flex items-center justify-between">
<span class="text-sm text-slate-300"><span id="selection-count" class="font-bold text-cyan-400">0</span> seleccionados</span>
<div class="flex gap-2">
<button onclick="batchDownload()" class="px-4 py-2 rounded-lg bg-gradient-to-r from-cyan-500 to-blue-600 text-white text-xs font-bold shadow-lg shadow-cyan-500/20 transition-all hover:scale-105">
Descargar ZIP
</button>
<button onclick="clearSelection()" class="px-4 py-2 rounded-lg bg-slate-800 hover:bg-slate-700 border border-white/10 text-xs font-medium transition-colors">
Cancelar
</button>
</div>
</div>
<!-- Grid -->
<div id="grid" class="grid grid-cols-1 sm:grid-cols-2 xl:grid-cols-3 gap-6">
<div class="col-span-full flex flex-col items-center justify-center py-20 text-slate-500">
<div class="w-12 h-12 border-4 border-slate-700 border-t-cyan-500 rounded-full animate-spin mb-4"></div>
<p>Cargando modelos...</p>
</div>
</div>
<!-- Load more -->
<div class="mt-8 flex justify-center">
<button id="load-more" onclick="loadMore()" class="hidden px-6 py-3 rounded-xl bg-slate-800 hover:bg-slate-700 border border-white/10 text-sm font-medium transition-colors">
Cargar mas
</button>
</div>
</div>
</main>
<!-- Estimator Modal -->
<div id="estimator-modal" class="hidden fixed inset-0 z-[100] flex items-center justify-center p-4 bg-black/60 backdrop-blur-sm">
<div class="glass rounded-2xl p-6 w-full max-w-sm border border-white/10 animate-fade-in">
<div class="flex items-center justify-between mb-4">
<h3 class="text-lg font-bold">Estimacion de impresion</h3>
<button onclick="closeEstimator()" class="p-2 rounded-lg hover:bg-slate-800 text-slate-400 hover:text-white transition-colors">
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path></svg>
</button>
</div>
<div id="estimator-content"></div>
</div>
</div>
<div id="toast-container"></div>
<script src="/static/js/theme.js"></script>
<script src="/static/js/api.js"></script>
<script src="/static/js/app.js"></script>
</body>
</html>