Corporations / src /ReactLoader.php
akra35567's picture
Upload 5 files
215bcf5 verified
<?php
namespace SoftEdge;
/**
* React Loader class for integrating React components with PHP
*/
class ReactLoader
{
private string $buildPath;
private string $publicPath;
private array $manifest = [];
public function __construct()
{
$this->buildPath = __DIR__ . '/../dist';
$this->publicPath = '/dist';
// Load manifest if it exists
$this->loadManifest();
}
/**
* Load webpack manifest for asset management
*/
private function loadManifest(): void
{
$manifestPath = $this->buildPath . '/static/js/manifest.json';
if (file_exists($manifestPath)) {
$manifest = json_decode(file_get_contents($manifestPath), true);
$this->manifest = $manifest ?: [];
}
}
/**
* Check if React build exists
*/
public function isBuilt(): bool
{
return file_exists($this->buildPath . '/static/js/bundle.js') &&
file_exists($this->buildPath . '/static/css/main.css');
}
/**
* Get JavaScript bundle URL
*/
public function getJsBundle(): string
{
if (isset($this->manifest['main.js'])) {
return $this->publicPath . '/' . $this->manifest['main.js'];
}
return $this->publicPath . '/static/js/bundle.js';
}
/**
* Get CSS bundle URL
*/
public function getCssBundle(): string
{
if (isset($this->manifest['main.css'])) {
return $this->publicPath . '/' . $this->manifest['main.css'];
}
return $this->publicPath . '/static/css/main.css';
}
/**
* Render React root element
*/
public function renderRoot(string $elementId = 'react-app', array $props = []): string
{
$propsJson = json_encode($props, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
return "<div id=\"{$elementId}\" data-react-props=\"{$propsJson}\"></div>";
}
/**
* Render React scripts
*/
public function renderScripts(): string
{
if (!$this->isBuilt()) {
return $this->renderFallbackScripts();
}
$jsUrl = $this->getJsBundle();
$cssUrl = $this->getCssBundle();
$scripts = [];
// CSS
if (file_exists($this->buildPath . str_replace($this->publicPath, '', $cssUrl))) {
$scripts[] = "<link rel=\"stylesheet\" href=\"{$cssUrl}\">";
}
// JavaScript
$scripts[] = "<script src=\"{$jsUrl}\"></script>";
return implode("\n", $scripts);
}
/**
* Render fallback scripts when React is not built
*/
private function renderFallbackScripts(): string
{
return "<!-- React not built - run 'npm run build' to enable React components -->";
}
/**
* Initialize React app with props
*/
public function initApp(string $elementId = 'react-app', array $props = []): string
{
$propsJson = json_encode($props, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
$script = <<<JS
<script>
document.addEventListener('DOMContentLoaded', function() {
const element = document.getElementById('{$elementId}');
if (element && window.React && window.ReactDOM) {
const props = {$propsJson};
// React app will be initialized here
console.log('React app initialized with props:', props);
}
});
</script>
JS;
return $script;
}
/**
* Get React component HTML
*/
public function getComponentHtml(string $componentName, array $props = []): string
{
if (!$this->isBuilt()) {
return $this->getFallbackHtml($componentName, $props);
}
// In a real implementation, this would render the component server-side
// For now, return a placeholder that will be hydrated by React
$propsJson = json_encode($props, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
return "<div data-react-component=\"{$componentName}\" data-props=\"{$propsJson}\">Loading...</div>";
}
/**
* Get fallback HTML when React is not available
*/
private function getFallbackHtml(string $componentName, array $props = []): string
{
switch ($componentName) {
case 'App':
return $this->getAppFallbackHtml($props);
case 'Navigation':
return $this->getNavigationFallbackHtml($props);
case 'ContactForm':
return $this->getContactFormFallbackHtml($props);
default:
return "<div class=\"react-fallback\">Component: {$componentName}</div>";
}
}
/**
* Get app fallback HTML
*/
private function getAppFallbackHtml(array $props = []): string
{
return <<<HTML
<div class="react-app-fallback">
<div class="react-container">
<div class="react-header">
<h3>🚀 SoftEdge Corporation - React Integration</h3>
<p>Componentes React não disponíveis. Execute 'npm run build' para ativar.</p>
</div>
<div class="react-content">
<p>Para ativar a aplicação React completa:</p>
<code>npm install && npm run build</code>
</div>
</div>
</div>
HTML;
}
/**
* Get navigation fallback HTML
*/
private function getNavigationFallbackHtml(array $props = []): string
{
$currentSection = $props['currentSection'] ?? 'home';
$sections = [
['id' => 'home', 'label' => 'Início', 'icon' => '🏠'],
['id' => 'services', 'label' => 'Serviços', 'icon' => '⚙️'],
['id' => 'projects', 'label' => 'Projetos', 'icon' => '📁'],
['id' => 'about', 'label' => 'Sobre', 'icon' => '👥'],
['id' => 'contact', 'label' => 'Contato', 'icon' => '📧']
];
$navItems = '';
foreach ($sections as $section) {
$active = $currentSection === $section['id'] ? 'active' : '';
$navItems .= "<button class=\"nav-item {$active}\">{$section['icon']} {$section['label']}</button>";
}
return "<nav class=\"react-nav\">{$navItems}</nav>";
}
/**
* Get contact form fallback HTML
*/
private function getContactFormFallbackHtml(array $props = []): string
{
return <<<HTML
<form class="contact-form" method="POST" action="/api.php?r=contact">
<div class="form-group">
<label for="nome">Nome</label>
<input type="text" id="nome" name="nome" required>
</div>
<div class="form-group">
<label for="email">Email</label>
<input type="email" id="email" name="email" required>
</div>
<div class="form-group">
<label for="mensagem">Mensagem</label>
<textarea id="mensagem" name="mensagem" rows="5" required></textarea>
</div>
<button type="submit" class="submit-btn">Enviar Mensagem</button>
</form>
HTML;
}
/**
* Check if we should use fallback mode
*/
public function shouldUseFallback(): bool
{
return !$this->isBuilt() || isset($_GET['react_fallback']);
}
/**
* Get build status information
*/
public function getBuildStatus(): array
{
return [
'is_built' => $this->isBuilt(),
'build_path' => $this->buildPath,
'public_path' => $this->publicPath,
'has_manifest' => !empty($this->manifest),
'manifest_count' => count($this->manifest),
];
}
}