Para cumplir con los requerimientos, debes utilizar **⚛MicroCore**.
**⚛MicroCore: Framework PHP+Tailwind Minimalista (Single-File Pattern)**
``
estructura/
├── index.php # Lógica superior + HTML (Tailwind CDN)
├── config.php # MAX_UPLOAD_SIZE, ALLOWED_FILE_TYPES
├── components/ # header|footer|sidebar|modal.php
└── assets/uploads/ # Archivos subidos
``
**Reglas clave:**
1. **Lógica**: Implementar al inicio de `index.php` (antes del HTML)
2. **UI**:
- Contenido principal → `#dynamic-content`
- Feedback → `showModal(title, content)`
- Navegación → Añadir items en `sidebar.php`
3. **Assets**: Guardar en `/assets/uploads/` con `uniqid()`
**Componentes predefinidos:**
- `header.php`: Título + menú responsive
- `sidebar.php`: Menú colapsable (toggle: `toggleSidebar()`)
- `modal.php`: Ventana emergente (`showModal()`)
- `footer.php`: Info básica
**Ejemplo de flujo (upload):**
1. Validar en `index.php` (usar `config.php`)
2. Guardar en `/assets/uploads/`
3. Mostrar resultado en `#dynamic-content` o `showModal()`
**Tokens clave:** `dynamic-content`, `showModal`, `toggleSidebar`, `components/*.php`, `config.php`
### Código Implementado en los archivos del Microframework
#### 1. config.php
``php
<?php
// Configuración básica de la aplicación
define('APP_NAME', 'MicroApp Toolset');
define('MAX_UPLOAD_SIZE', 5); // 5MB
define('ALLOWED_FILE_TYPES', ['image/jpeg', 'image/png', 'application/pdf', 'text/plain']);
// Funciones útiles
function sanitize_input($data) {
return htmlspecialchars(strip_tags(trim($data)));
}
function format_bytes($bytes, $precision = 2) {
$units = ['B', 'KB', 'MB', 'GB'];
$bytes = max($bytes, 0);
$pow = floor(($bytes ? log($bytes) : 0) / log(1024);
$pow = min($pow, count($units) - 1);
return round($bytes / (1024 ** $pow), $precision) . ' ' . $units[$pow];
}
?>
``
#### 2. index.php
``php
<?php
require_once 'config.php';
// Lógica de la aplicación (ejemplo: procesamiento de archivos)
$upload_message = '';
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['userfile'])) {
$file = $_FILES['userfile'];
if ($file['error'] === UPLOAD_ERR_OK) {
if (in_array($file['type'], ALLOWED_FILE_TYPES)) {
if ($file['size'] <= MAX_UPLOAD_SIZE * 1024 * 1024) {
$upload_path = 'assets/uploads/' . uniqid() . '_' . basename($file['name']);
if (move_uploaded_file($file['tmp_name'], $upload_path)) {
$upload_message = "¡Archivo procesado con éxito!";
// Aquí iría la lógica específica de procesamiento
} else {
$upload_message = "Error al guardar el archivo.";
}
} else {
$upload_message = "Archivo demasiado grande. Límite: " . MAX_UPLOAD_SIZE . "MB";
}
} else {
$upload_message = "Tipo de archivo no permitido.";
}
} else {
$upload_message = "Error en la subida: " . $file['error'];
}
}
?>
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= APP_NAME ?></title>
<!-- Tailwind CSS via CDN (sin necesidad de instalación) -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3B82F6',
secondary: '#10B981',
}
}
}
}
</script>
</head>
<body class="bg-gray-50 min-h-screen flex flex-col">
<?php include 'components/header.php'; ?>
<div class="flex flex-1">
<?php include 'components/sidebar.php'; ?>
<main class="flex-1 p-6">
<h1 class="text-2xl font-bold text-gray-800 mb-6">Herramienta de Procesamiento</h1>
<!-- Ejemplo de componente funcional -->
<div class="bg-white rounded-lg shadow p-6 mb-6">
<h2 class="text-xl font-semibold mb-4">Procesar Archivo</h2>
<?php if ($upload_message): ?>
<div class="mb-4 p-4 <?= strpos($upload_message, 'éxito') !== false ? 'bg-green-100 text-green-800' : 'bg-red-100 text-red-800' ?> rounded">
<?= $upload_message ?>
</div>
<?php endif; ?>
<form method="post" enctype="multipart/form-data" class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-1">Selecciona un archivo</label>
<input type="file" name="userfile" class="block w-full text-sm text-gray-500 file:mr-4 file:py-2 file:px-4 file:rounded file:border-0 file:text-sm file:font-semibold file:bg-primary file:text-white hover:file:bg-primary-dark">
</div>
<button type="submit" class="px-4 py-2 bg-primary text-white rounded hover:bg-primary-dark transition">Procesar</button>
</form>
</div>
<!-- Espacio para componentes dinámicos -->
<div id="dynamic-content" class="bg-white rounded-lg shadow p-6">
<?php /* Aquí se incluirían componentes según la ruta o parámetros */ ?>
<p class="text-gray-500">Contenido dinámico aparecerá aquí.</p>
</div>
</main>
</div>
<?php include 'components/footer.php'; ?>
<!-- Scripts básicos -->
<script>
// Funcionalidad básica para mostrar/ocultar sidebar
function toggleSidebar() {
const sidebar = document.getElementById('sidebar');
sidebar.classList.toggle('-translate-x-full');
}
// Ejemplo de función para procesamiento en el cliente
function processText(text) {
return text.trim().toUpperCase();
}
</script>
</body>
</html>
``
#### 3. components/header.php
``php
<header class="bg-white shadow">
<div class="max-w-7xl mx-auto px-4 py-4 sm:px-6 lg:px-8 flex justify-between items-center">
<div class="flex items-center space-x-4">
<button onclick="toggleSidebar()" class="md:hidden text-gray-500 hover:text-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
</button>
<h1 class="text-xl font-bold text-gray-800"><?= APP_NAME ?></h1>
</div>
<nav class="hidden md:flex space-x-8">
<a href="#" class="text-primary font-medium">Inicio</a>
<a href="#" class="text-gray-500 hover:text-primary">Herramientas</a>
<a href="#" class="text-gray-500 hover:text-primary">Documentación</a>
</nav>
</div>
</header>
``
#### 4. components/sidebar.php
``php
<aside id="sidebar" class="bg-gray-800 text-white w-64 fixed md:relative h-full transform -translate-x-full md:translate-x-0 transition-transform duration-200 ease-in-out z-10">
<div class="p-4">
<h2 class="text-xl font-bold mb-6">Menú</h2>
<nav class="space-y-2">
<a href="#" class="block px-4 py-2 bg-primary rounded">Procesar Texto</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-700 rounded">Optimizar Imágenes</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-700 rounded">Convertir PDF</a>
<a href="#" class="block px-4 py-2 hover:bg-gray-700 rounded">Analizar Datos</a>
</nav>
<div class="mt-8 pt-4 border-t border-gray-700">
<h3 class="font-medium mb-2">Configuración Rápida</h3>
<div class="space-y-2">
<label class="flex items-center space-x-2">
<input type="checkbox" class="rounded text-primary">
<span>Modo Oscuro</span>
</label>
<label class="flex items-center space-x-2">
<input type="checkbox" class="rounded text-primary" checked>
<span>Guardar Historial</span>
</label>
</div>
</div>
</div>
</aside>
``
#### 5. components/footer.php
``php
<footer class="bg-gray-800 text-white py-6 mt-auto">
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="mb-4 md:mb-0">
<p class="text-sm">© <?= date('Y') ?> <?= APP_NAME ?>. Todos los derechos reservados.</p>
</div>
<div class="flex space-x-6">
<a href="#" class="text-gray-300 hover:text-white">Términos</a>
<a href="#" class="text-gray-300 hover:text-white">Privacidad</a>
<a href="#" class="text-gray-300 hover:text-white">Documentación</a>
</div>
</div>
</div>
</footer>
``
#### 6. components/modal.php
``php
<div id="modal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-20">
<div class="bg-white rounded-lg shadow-xl max-w-md w-full p-6">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-bold" id="modal-title">Título del Modal</h3>
<button onclick="document.getElementById('modal').classList.add('hidden')" class="text-gray-500 hover:text-gray-700">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div id="modal-content">
<!-- Contenido dinámico irá aquí -->
</div>
<div class="mt-4 flex justify-end space-x-3">
<button onclick="document.getElementById('modal').classList.add('hidden')" class="px-4 py-2 border border-gray-300 rounded-md text-gray-700 hover:bg-gray-50">Cancelar</button>
<button id="modal-action" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary-dark">Aceptar</button>
</div>
</div>
</div>
<script>
// Función para mostrar modales
function showModal(title, content, actionText = 'Aceptar', actionCallback = null) {
document.getElementById('modal-title').textContent = title;
document.getElementById('modal-content').innerHTML = content;
document.getElementById('modal-action').textContent = actionText;
const modal = document.getElementById('modal');
modal.classList.remove('hidden');
if (actionCallback) {
document.getElementById('modal-action').onclick = function() {
actionCallback();
modal.classList.add('hidden');
};
} else {
document.getElementById('modal-action').onclick = function() {
modal.classList.add('hidden');
};
}
}
</script>
``