```markdown
YÊU CẦU:  
Tạo một module Laravel tên **`UiBuilder`** đặt tại `app/Modules/UiBuilder/` (Laravel 11, PHP 8.2+).  
Module này dùng để **quản lý và cấu hình giao diện động (footer, header, banner, landing...)** cho từng **tenant + domain**.  

Một tenant có thể có nhiều domain.  
Cấu hình (config) template được xác định bởi cặp `(tenant_id, domain_id, component)`.  

Module phải:
- Có **API cho frontend (Next.js)** để lấy template + config render động.  
- Có **CRUD giao diện quản trị (Blade)** dành cho admin.  
- **Không sử dụng style/layout của CMS hiện tại.**  
- Dùng **Tailwind riêng biệt**.  
- Cho phép **preview template trực quan với 3 chế độ responsive (Desktop / Tablet / Mobile).**  
- Có thể **tách riêng module này** ra thành app độc lập về sau.  

---

## 🎯 MỤC TIÊU CHÍNH

1️⃣ CRUD **UI Template** (HTML + CSS).  
2️⃣ CRUD **UI Config** (tenant + domain ↔ template + config JSON).  
3️⃣ API public để frontend lấy template/config động.  
4️⃣ View CRUD đẹp, dễ dùng, có preview responsive.  
5️⃣ Module hoạt động độc lập, không ảnh hưởng CMS chính.  

---

## 📁 Cấu trúc module

```

app/Modules/UiBuilder/
├── Http/
│   ├── Controllers/
│   │   ├── Api/
│   │   │   ├── TemplateApiController.php
│   │   │   └── ConfigApiController.php
│   │   └── Web/
│   │       └── UiBuilderController.php
│   ├── Requests/
│   │   ├── StoreTemplateRequest.php
│   │   └── StoreConfigRequest.php
├── Models/
│   ├── UiTemplate.php
│   └── UiConfig.php
├── Database/
│   ├── migrations/
│   │   ├── 2025_10_11_000001_create_ui_templates_table.php
│   │   └── 2025_10_11_000002_create_ui_configs_table.php
├── Providers/
│   └── UiBuilderServiceProvider.php
├── Resources/
│   ├── views/
│   │   ├── layouts/app.blade.php
│   │   ├── templates/
│   │   │   ├── index.blade.php
│   │   │   ├── form.blade.php
│   │   │   └── preview.blade.php
│   │   ├── configs/
│   │   │   ├── index.blade.php
│   │   │   └── form.blade.php
│   └── assets/
│       ├── css/uibuilder.css
│       └── js/uibuilder.js
├── routes/
│   ├── api.php
│   └── web.php
└── vite.config.js

````

---

## 🗃️ Migrations

### `ui_templates`
| Cột | Kiểu | Ghi chú |
|-----|------|----------|
| id | bigint | PK |
| component | varchar(50) | 'footer', 'header', 'landing', ... |
| name | varchar(100) | tên hiển thị |
| slug | varchar(120) | unique per component |
| html | longText | HTML template |
| css | text nullable | CSS riêng |
| is_active | boolean default true |
| timestamps |  |  |

### `ui_configs`
| Cột | Kiểu | Ghi chú |
|-----|------|----------|
| id | bigint | PK |
| tenant_id | bigint | FK -> hocmai_tenants.id |
| domain_id | bigint | FK -> hocmai_tenant_domains.id |
| component | varchar(50) |
| template_id | bigint | FK -> ui_templates.id |
| config | json nullable | Dữ liệu cấu hình (text, link, màu sắc, ...) |
| is_active | boolean default true |
| timestamps |  |  |
| unique index | (tenant_id, domain_id, component) |  |

---

## 🌐 Routes

### API — `routes/api.php`
```php
Route::prefix('api/admin/ui')->middleware(['auth:sanctum'])->group(function () {
    Route::apiResource('templates', \App\Modules\UiBuilder\Http\Controllers\Api\TemplateApiController::class);
    Route::apiResource('configs', \App\Modules\UiBuilder\Http\Controllers\Api\ConfigApiController::class);
});

Route::prefix('api/ui')->group(function () {
    Route::get('/{component}', [\App\Modules\UiBuilder\Http\Controllers\Api\TemplateApiController::class, 'render']);
});
````

### WEB — `routes/web.php`

```php
Route::prefix('admin/ui-builder')->middleware(['auth'])->group(function () {
    Route::get('/', [\App\Modules\UiBuilder\Http\Controllers\Web\UiBuilderController::class, 'dashboard'])->name('ui-builder.index');
    Route::get('/templates', [\App\Modules\UiBuilder\Http\Controllers\Web\UiBuilderController::class, 'templates'])->name('ui-builder.templates');
    Route::get('/configs', [\App\Modules\UiBuilder\Http\Controllers\Web\UiBuilderController::class, 'configs'])->name('ui-builder.configs');
    Route::get('/templates/{id}/preview', [\App\Modules\UiBuilder\Http\Controllers\Web\UiBuilderController::class, 'preview'])->name('ui-builder.templates.preview');
});
```

---

## 🧱 View CRUD (Blade – style riêng, có responsive preview)

### Layout riêng

`Resources/views/layouts/app.blade.php`

```blade
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>UiBuilder</title>
  <link rel="stylesheet" href="{{ asset('modules/uibuilder/css/uibuilder.css') }}">
  <script src="{{ asset('modules/uibuilder/js/uibuilder.js') }}" defer></script>
</head>
<body class="bg-gray-50 text-gray-800 font-sans">
  <div class="max-w-7xl mx-auto p-6">
    <header class="mb-6">
      <h1 class="text-3xl font-bold">UI Builder</h1>
      <nav class="mt-2 space-x-4">
        <a href="{{ route('ui-builder.templates') }}" class="text-blue-600 hover:underline">Templates</a>
        <a href="{{ route('ui-builder.configs') }}" class="text-blue-600 hover:underline">Configs</a>
      </nav>
    </header>

    @yield('content')
  </div>
</body>
</html>
```

---

### Template List View

`Resources/views/templates/index.blade.php`

```blade
@extends('uibuilder::layouts.app')

@section('content')
  <div class="flex justify-between items-center mb-4">
    <h2 class="text-2xl font-semibold">Templates</h2>
    <a href="#" class="bg-blue-600 text-white px-4 py-2 rounded">+ Add Template</a>
  </div>

  <table class="w-full border border-gray-300 rounded">
    <thead class="bg-gray-100">
      <tr>
        <th class="p-2 border">#</th>
        <th class="p-2 border">Component</th>
        <th class="p-2 border">Name</th>
        <th class="p-2 border">Active</th>
        <th class="p-2 border">Actions</th>
      </tr>
    </thead>
    <tbody>
      @foreach($templates as $tpl)
        <tr class="hover:bg-gray-50">
          <td class="p-2 border">{{ $tpl->id }}</td>
          <td class="p-2 border">{{ $tpl->component }}</td>
          <td class="p-2 border">{{ $tpl->name }}</td>
          <td class="p-2 border">{{ $tpl->is_active ? '✅' : '❌' }}</td>
          <td class="p-2 border text-sm">
            <a href="{{ route('ui-builder.templates.preview', $tpl->id) }}" class="text-green-600 hover:underline">Preview</a> |
            <a href="#" class="text-blue-600 hover:underline">Edit</a> |
            <a href="#" class="text-red-600 hover:underline">Delete</a>
          </td>
        </tr>
      @endforeach
    </tbody>
  </table>
@endsection
```

---

### Responsive Preview View

`Resources/views/templates/preview.blade.php`

```blade
@extends('uibuilder::layouts.app')

@section('content')
  <h2 class="text-2xl font-semibold mb-4">Preview Template: {{ $template->name }}</h2>

  <div class="mb-4 space-x-2">
    <button onclick="setPreview('desktop')" class="px-3 py-1 bg-blue-600 text-white rounded">Desktop</button>
    <button onclick="setPreview('tablet')" class="px-3 py-1 bg-gray-300 text-gray-700 rounded">Tablet</button>
    <button onclick="setPreview('mobile')" class="px-3 py-1 bg-gray-300 text-gray-700 rounded">Mobile</button>
  </div>

  <div id="preview-wrapper" class="border bg-white shadow rounded overflow-hidden">
    <iframe id="preview-frame" class="w-full" style="height:800px"></iframe>
  </div>

  <script>
    const html = `{!! addslashes($template->html) !!}`;
    const css = `<style>{{ $template->css }}</style>`;
    const frame = document.getElementById('preview-frame');
    frame.onload = () => frame.contentDocument.body.innerHTML = css + html;
    frame.src = 'about:blank';

    function setPreview(mode) {
      const wrapper = document.getElementById('preview-wrapper');
      switch(mode) {
        case 'desktop': wrapper.style.width = '100%'; break;
        case 'tablet': wrapper.style.width = '768px'; break;
        case 'mobile': wrapper.style.width = '390px'; break;
      }
    }
  </script>
@endsection
```

---

## 🎨 Tailwind riêng

`Resources/assets/css/uibuilder.css`

```css
@tailwind base;
@tailwind components;
@tailwind utilities;

body { font-family: 'Inter', sans-serif; }
```

---

## 🧩 Service Provider

```php
<?php

namespace App\Modules\UiBuilder\Providers;

use Illuminate\Support\ServiceProvider;

class UiBuilderServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->loadRoutesFrom(__DIR__.'/../routes/api.php');
        $this->loadRoutesFrom(__DIR__.'/../routes/web.php');
        $this->loadMigrationsFrom(__DIR__.'/../Database/migrations');
        $this->loadViewsFrom(__DIR__.'/../Resources/views', 'uibuilder');
    }
}
```

---

## 📋 Yêu cầu đầu ra cho Cursor

1️⃣ Sinh đầy đủ module `UiBuilder` như trên.
2️⃣ CRUD API hoàn chỉnh (JSON).
3️⃣ Giao diện CRUD (Blade) dễ dùng, có **preview responsive**.
4️⃣ Style riêng biệt, Tailwind riêng.
5️⃣ Không kế thừa layout/style của CMS.
6️⃣ Config mapping theo `tenant_id` + `domain_id`.
7️⃣ Dễ tách module ra app riêng.
8️⃣ Code chuẩn PSR-12, Laravel 11.
9️⃣ Có comment hướng dẫn ở model, controller chính.

**Hãy scaffold module “UiBuilder” hoàn chỉnh theo hướng dẫn trên.**