'https://res.cloudinary.com/izpast9i/image/upload/v1786503590/email_banner_cloud_vps.png', ]; public function render(EmailNotificationTemplate $tpl, Invoice $invoice, string $companyName = ''): string { $blocks = collect($tpl->blocks) ->filter(fn($b) => $b['enabled'] ?? false) ->sortBy('order') ->values(); $bodyHtml = ''; foreach ($blocks as $block) { $bodyHtml .= $this->renderBlock($block, $invoice, $companyName); } $title = $tpl->header_title ?? 'Thông báo hóa đơn'; return $this->wrapLayout($title, $bodyHtml, $companyName, self::BANNERS[$tpl->type] ?? null); } /** * Render a vm_credentials template using the emailData array from SendVmCredentialsEmailJob. * $emailData keys: company_name, client_name, product_name, product_billing, product_price, * service_host, service_username, service_port, service_password, os_name, service_due_exp */ public function renderVmCredentials(EmailNotificationTemplate $tpl, array $emailData, ?Invoice $invoice = null): string { $blocks = collect($tpl->blocks) ->filter(fn($b) => $b['enabled'] ?? false) ->sortBy('order') ->values(); $companyName = $emailData['company_name'] ?? ''; $bodyHtml = ''; foreach ($blocks as $block) { $bodyHtml .= match ($block['type'] ?? '') { 'greeting' => $this->renderView('emails.partials.greeting', ['name' => $emailData['client_name'] ?? 'Quý khách']), 'vm_credentials' => $this->renderView('emails.partials.vm-credentials', ['fields' => $block['config']['fields'] ?? null, 'data' => $emailData]), 'product_info' => $this->renderView('emails.partials.product-info', ['fields' => $block['config']['fields'] ?? null, 'data' => $emailData]), 'invoice_info' => $invoice ? $this->renderView('emails.partials.invoice-info', ['fields' => $block['config']['fields'] ?? null, 'invoice' => $invoice]) : '', 'order_items' => $invoice ? $this->renderOrderItems($invoice) : '', 'attachments' => $invoice ? $this->renderAttachments($invoice) : '', 'custom_text' => $this->renderView('emails.partials.custom-text', ['content' => $block['config']['content'] ?? '']), 'footer' => $this->renderView('emails.partials.signature', ['companyName' => $companyName]), default => '', }; } $title = $tpl->header_title ?? 'Thông tin truy cập VPS'; return $this->wrapLayout($title, $bodyHtml, $companyName, self::BANNERS[$tpl->type] ?? null); } public function renderPreview(EmailNotificationTemplate $tpl): string { if ($tpl->type === 'vm_credentials') { return $this->renderVmCredentials($tpl, $this->sampleVmData(), null); } $invoice = $this->sampleInvoice(); return $this->render($tpl, $invoice, 'Công ty Demo'); } // ─── Block renderers ────────────────────────────────────────────────────── private function renderBlock(array $block, Invoice $invoice, string $companyName): string { return match ($block['type'] ?? '') { 'greeting' => $this->renderView('emails.partials.greeting', ['name' => $invoice->customer?->fullname ?? 'Quý khách']), 'invoice_info' => $this->renderView('emails.partials.invoice-info', ['fields' => $block['config']['fields'] ?? null, 'invoice' => $invoice]), 'customer_info' => $this->renderView('emails.partials.customer-info', ['fields' => $block['config']['fields'] ?? null, 'customer' => $invoice->customer]), 'order_items' => $this->renderOrderItems($invoice), 'attachments' => $this->renderAttachments($invoice), 'custom_text' => $this->renderView('emails.partials.custom-text', ['content' => $block['config']['content'] ?? '']), 'footer' => $this->renderView('emails.partials.signature', ['companyName' => $companyName]), default => '', }; } private function renderOrderItems(Invoice $invoice): string { $order = $invoice->order; if (!$order) return ''; $order->loadMissing('orderItems.product'); return $this->renderView('emails.partials.order-items', ['items' => $order->orderItems]); } private function renderAttachments(Invoice $invoice): string { $invoice->loadMissing('attachments'); return $this->renderView('emails.partials.attachments', ['attachments' => $invoice->attachments]); } private function renderView(string $view, array $data): string { return View::make($view, $data)->render(); } // ─── Layout wrapper ─────────────────────────────────────────────────────── private function wrapLayout(string $title, string $body, string $companyName, ?string $bannerUrl = null): string { return View::make('emails.layouts.notification', [ 'title' => $title, 'body' => $body, 'companyName' => $companyName ?: config('app.name', 'Thế Giới Số'), 'bannerUrl' => $bannerUrl, ])->render(); } // ─── Sample data for preview ────────────────────────────────────────────── private function sampleVmData(): array { return [ 'company_name' => 'Công ty Demo', 'company_logo' => '', 'client_name' => 'Nguyễn Văn A', 'product_name' => 'VPS Starter', 'product_billing' => 'Hàng tháng', 'product_price' => '420.000', 'service_host' => '203.113.x.x', 'service_username' => 'root', 'service_port' => '22', 'service_password' => 'P@ssw0rd!2026', 'os_name' => 'Ubuntu 22.04 LTS', 'service_due_exp' => date('d/m/Y', strtotime('+1 month')), ]; } private function sampleInvoice(): Invoice { $invoice = new Invoice([ 'invoice_number' => 'INV-20260521-00001', 'sub_total' => 420000, 'tax' => 0, 'total' => 420000, 'status' => 2, 'payment_method' => 'credit', ]); $invoice->created_at = now(); $invoice->due_date = now()->addDays(7)->toDateString(); return $invoice; } }