update
This commit is contained in:
@@ -2,75 +2,158 @@
|
||||
|
||||
namespace App\Support;
|
||||
|
||||
/**
|
||||
* Khung 700px dùng chung cho template email trong tbl.template: header (banner) + footer
|
||||
* (menu dịch vụ + thông tin công ty). Mỗi scenario chỉ cần viết phần <tr class="NoiDungKM">.
|
||||
*
|
||||
* Thông tin công ty hardcode ở footer vì EmailTemplateRenderer chỉ thay placeholder dạng
|
||||
* {{key}} đã khai báo trong metadata.variables — mọi scenario đều phải khai lại nếu muốn
|
||||
* footer động, không đáng.
|
||||
*/
|
||||
class EmailTemplateShell
|
||||
{
|
||||
/** Bọc phần nội dung vào khung chuẩn. */
|
||||
private const BRAND = '#f16723';
|
||||
|
||||
private const SERVICE_LINKS = [
|
||||
'Premium Hosting' => 'https://tgs.com.vn/premium-hosting/',
|
||||
'Cloud Server' => 'https://tgs.com.vn/cloud-server/',
|
||||
'Thuê Server' => 'https://tgs.com.vn/may-chu-rieng',
|
||||
'Thiết kế website' => 'https://tgs.com.vn/thiet-ke-website/',
|
||||
];
|
||||
|
||||
public static function wrap(string $bodyHtml): string
|
||||
{
|
||||
return self::header() . $bodyHtml . self::footer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Mở khối NoiDungKM với style chữ chuẩn, để scenario chỉ viết nội dung bên trong.
|
||||
*/
|
||||
public static function page(string $innerHtml): string
|
||||
{
|
||||
return self::wrap(self::body($innerHtml));
|
||||
}
|
||||
|
||||
public static function body(string $innerHtml): string
|
||||
{
|
||||
return '<tr class="NoiDungKM"><td style="width: 700px; padding: 32px 48px; background-color: #ffffff; font-family: Montserrat,-apple-system,sans-serif; font-size: 15px; line-height: 24px; color: #626262;" valign="top">'
|
||||
return '<tr class="NoiDungKM"><td style="box-sizing: border-box; width: 700px; padding: 32px 48px; background-color: #ffffff; font-family: Montserrat,-apple-system,sans-serif; font-size: 15px; line-height: 24px; color: #626262;" valign="top" bgcolor="#ffffff" width="700">'
|
||||
. $innerHtml
|
||||
. '</td></tr>';
|
||||
}
|
||||
|
||||
/** Khối "Lưu ý: email tự động" dùng ở cuối hầu hết scenario. */
|
||||
public static function title(string $html): string
|
||||
{
|
||||
return '<p style="box-sizing: border-box; margin: 0 0 6px 0; font-size: 21px; font-weight: bold; text-align: center; color: ' . self::BRAND . ';">' . $html . '</p>';
|
||||
}
|
||||
|
||||
public static function subtitle(string $html): string
|
||||
{
|
||||
return '<p style="box-sizing: border-box; margin: 0 0 8px 0; font-size: 14px; text-align: center; color: #6b7280;">' . $html . '</p>';
|
||||
}
|
||||
|
||||
public static function highlight(string $html): string
|
||||
{
|
||||
return '<table style="box-sizing: border-box; margin: 24px auto;" cellspacing="0" cellpadding="0"><tbody><tr>'
|
||||
. '<td style="box-sizing: border-box; background-color: #fff7f2; border: 2px dashed ' . self::BRAND . '; border-radius: 8px; padding: 14px 36px;" align="center" bgcolor="#fff7f2">'
|
||||
. '<span style="box-sizing: border-box; font-family: \'Courier New\', monospace; font-size: 30px; font-weight: 700; letter-spacing: 6px; color: ' . self::BRAND . ';">' . $html . '</span>'
|
||||
. '</td></tr></tbody></table>';
|
||||
}
|
||||
|
||||
public static function heading(string $html): string
|
||||
{
|
||||
return '<p style="box-sizing: border-box; margin: 0 0 8px 0; font-weight: bold; color: #374151;">' . $html . '</p>';
|
||||
}
|
||||
|
||||
public static function greeting(string $nameHtml): string
|
||||
{
|
||||
return '<p style="box-sizing: border-box; margin: 24px 0 16px 0;">Kính chào <strong style="box-sizing: border-box; color: ' . self::BRAND . ';">' . $nameHtml . '</strong>,</p>';
|
||||
}
|
||||
|
||||
public static function paragraph(string $html): string
|
||||
{
|
||||
return '<p style="box-sizing: border-box; margin: 0 0 20px 0; text-align: justify;">' . $html . '</p>';
|
||||
}
|
||||
|
||||
public static function button(string $url, string $label): string
|
||||
{
|
||||
return '<table style="box-sizing: border-box; margin: 24px auto;" cellspacing="0" cellpadding="0"><tbody><tr>'
|
||||
. '<td style="box-sizing: border-box; background-color: ' . self::BRAND . '; padding: 12px 24px; border-radius: 4px;" align="center" bgcolor="' . self::BRAND . '">'
|
||||
. '<a style="box-sizing: border-box; text-decoration: none; font-size: 14px; font-weight: 600; color: #ffffff;" href="' . $url . '" target="_blank" rel="noopener">' . $label . '</a>'
|
||||
. '</td></tr></tbody></table>';
|
||||
}
|
||||
|
||||
public static function note(string $html, string $label = 'Lưu ý:'): string
|
||||
{
|
||||
return '<table style="box-sizing: border-box; width: 100%; border-collapse: collapse; margin: 0 0 20px 0;" role="presentation" width="100%" cellspacing="0" cellpadding="0"><tbody><tr>'
|
||||
. '<td style="box-sizing: border-box; padding: 14px 16px; border-left: 3px solid ' . self::BRAND . '; background-color: #f8fafc; font-size: 13px; line-height: 20px; color: #626262;" bgcolor="#f8fafc">'
|
||||
. '<strong style="box-sizing: border-box; color: #374151;">' . $label . '</strong> ' . $html
|
||||
. '</td></tr></tbody></table>';
|
||||
}
|
||||
|
||||
public static function autoNotice(): string
|
||||
{
|
||||
return <<<'HTML'
|
||||
<table style="width: 100%; border-collapse: collapse;" role="presentation" cellspacing="0" cellpadding="0"><tbody><tr>
|
||||
<td style="padding: 14px 16px; border-left: 3px solid #f16723; background-color: #f8fafc; font-size: 13px; line-height: 20px; color: #626262;"><strong style="color: #374151;">Lưu ý:</strong> Đây là email được gửi tự động. Vui lòng không trả lời email này.</td>
|
||||
</tr></tbody></table>
|
||||
HTML;
|
||||
return self::note('Đây là email được gửi tự động. Vui lòng không trả lời email này.');
|
||||
}
|
||||
|
||||
public static function supportLine(): string
|
||||
{
|
||||
return self::paragraph('Mọi thắc mắc xin liên hệ <strong>support@tgs.com.vn</strong> hoặc <strong>(028) 7309. 7379</strong>.');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, string> $rows label => value HTML (đã escape)
|
||||
*/
|
||||
public static function infoTable(array $rows, string $extraRowsHtml = ''): string
|
||||
{
|
||||
$html = '';
|
||||
foreach ($rows as $label => $value) {
|
||||
$html .= self::row($label, $value);
|
||||
}
|
||||
|
||||
return '<table style="box-sizing: border-box; width: 100%; border-collapse: collapse; table-layout: fixed; margin: 0 0 20px 0; border: 1px solid #e8e8e8;" role="presentation" width="100%" cellspacing="0" cellpadding="0"><tbody>'
|
||||
. $html . $extraRowsHtml
|
||||
. '</tbody></table>';
|
||||
}
|
||||
|
||||
public static function row(string $label, string $valueHtml): string
|
||||
{
|
||||
return '<tr><td style="box-sizing: border-box; width: 38%; padding: 8px 12px; border-bottom: 1px solid #e8e8e8; background-color: #fafafa; color: #626262;" bgcolor="#fafafa">' . $label . '</td>'
|
||||
. '<td style="box-sizing: border-box; padding: 8px 12px; border-bottom: 1px solid #e8e8e8; color: #374151;"><strong>' . $valueHtml . '</strong></td></tr>';
|
||||
}
|
||||
|
||||
public static function header(): string
|
||||
{
|
||||
return <<<'HTML'
|
||||
<table style="border-collapse: collapse; width: 100%; background-color: #efefef;" border="0" cellspacing="0" cellpadding="0"><tbody><tr><td style="padding: 20px;" align="center" valign="top"><table style="padding-top: 20px; padding-bottom: 20px; border-collapse: collapse; background-color: #ffffff; width: 700px;" border="0" cellspacing="0" cellpadding="0"><tbody>
|
||||
<tr class="Header"><td style="width: 700px;" valign="top"><table align="center" width="700" bgcolor="#ffffff" style="border-collapse: collapse; width: 700px; max-width: 100%; text-align: center; background-color: #ffffff; border-top: 5px solid #f16723;" border="0" cellspacing="0" cellpadding="0"><tbody><tr><td style="padding: 0;"><a href="https://tgs.com.vn" style="display: block;" target="_blank" rel="noopener"><img src="https://res.cloudinary.com/izpast9i/image/upload/v1786499308/email_header.png" alt="Thư gửi từ CÔNG TY CỔ PHẦN GIẢI PHÁP CÔNG NGHỆ THẾ GIỚI SỐ" style="width: 100%; display: block; border: none;" width="700"></a></td></tr></tbody></table></td></tr>
|
||||
<table style="box-sizing: border-box; border-collapse: collapse; width: 100%; background-color: #efefef;" border="0" width="100%" cellspacing="0" cellpadding="0" bgcolor="#efefef"><tbody><tr><td style="box-sizing: border-box; padding: 20px;" align="center" valign="top"><table style="box-sizing: border-box; padding-top: 20px; padding-bottom: 20px; border-collapse: collapse; background-color: #ffffff; width: 700px;" border="0" width="700" cellspacing="0" cellpadding="0" bgcolor="#ffffff"><tbody>
|
||||
<tr class="Header"><td style="box-sizing: border-box; width: 700px;" valign="top" width="700"><table style="box-sizing: border-box; border-collapse: collapse; width: 700px; max-width: 100%; text-align: center; background-color: #ffffff; border-top: 5px solid #f16723;" border="0" width="700" cellspacing="0" cellpadding="0" align="center" bgcolor="#ffffff"><tbody><tr><td style="box-sizing: border-box; padding: 0;"><a style="box-sizing: border-box; display: block;" href="https://tgs.com.vn" target="_blank" rel="noopener"><img style="box-sizing: border-box; width: 100%; display: block; border: none;" src="https://res.cloudinary.com/izpast9i/image/upload/v1786499308/email_header.png" alt="Thư gửi từ CÔNG TY CỔ PHẦN GIẢI PHÁP CÔNG NGHỆ THẾ GIỚI SỐ" width="700"></a></td></tr></tbody></table></td></tr>
|
||||
HTML;
|
||||
}
|
||||
|
||||
public static function footer(): string
|
||||
{
|
||||
return <<<'HTML'
|
||||
<tr class="Footer"><td align="center" valign="top"><table border="0" cellpadding="0" cellspacing="0" width="700" align="center" background="https://res.cloudinary.com/izpast9i/image/upload/v1786500298/email_footer.png" bgcolor="#F16723" style="border-collapse: collapse; width: 700px; background-image: url("https://res.cloudinary.com/izpast9i/image/upload/v1786500298/email_footer.png"); background-size: cover; background-position: center; background-repeat: no-repeat;"><tbody>
|
||||
<tr><td style="padding: 40px 30px 20px 30px; text-align: center;"><table border="0" cellpadding="0" cellspacing="0" width="100%" style="border-collapse: separate; border-spacing: 8px 0; width: 100%;"><tbody><tr>
|
||||
<td width="25%" style="border: 1px solid rgba(255,255,255,0.35); border-radius: 8px; padding: 6px 4px; font-size: 12px; line-height: 16px; color: #ffffff; text-align: center; background-color: rgba(255,255,255,0.18);"><a href="https://tgs.com.vn/premium-hosting/" target="_blank" rel="noopener" style="color: #ffffff; text-decoration: none;">Premium Hosting</a></td>
|
||||
<td width="25%" style="border: 1px solid rgba(255,255,255,0.35); border-radius: 8px; padding: 6px 4px; font-size: 12px; line-height: 16px; color: #ffffff; text-align: center; background-color: rgba(255,255,255,0.18);"><a href="https://tgs.com.vn/cloud-server/" target="_blank" rel="noopener" style="color: #ffffff; text-decoration: none;">Cloud Server</a></td>
|
||||
<td width="25%" style="border: 1px solid rgba(255,255,255,0.35); border-radius: 8px; padding: 6px 4px; font-size: 12px; line-height: 16px; color: #ffffff; text-align: center; background-color: rgba(255,255,255,0.18);"><a href="https://cloudemail.vn/" target="_blank" rel="noopener" style="color: #ffffff; text-decoration: none;">Email doanh nghiệp</a></td>
|
||||
<td width="25%" style="border: 1px solid rgba(255,255,255,0.35); border-radius: 8px; padding: 6px 4px; font-size: 12px; line-height: 16px; color: #ffffff; text-align: center; background-color: rgba(255,255,255,0.18);"><a href="https://tgs.com.vn/thiet-ke-website/" target="_blank" rel="noopener" style="color: #ffffff; text-decoration: none;">Thiết kế website</a></td>
|
||||
</tr></tbody></table></td></tr>
|
||||
<tr><td style="padding: 6px 30px 0 30px; text-align: center;"><strong style="font-size: 14px; line-height: 22px; color: #ffffff;">CÔNG TY CỔ PHẦN GIẢI PHÁP CÔNG NGHỆ THẾ GIỚI SỐ</strong></td></tr>
|
||||
<tr><td style="padding: 6px 30px 0 30px; text-align: center;"><span style="font-size: 12px; line-height: 18px; color: #ffffff;">Địa chỉ: 128/38 Tân Hương, Phường Phú Thọ Hòa, Thành Phố Hồ Chí Minh</span></td></tr>
|
||||
<tr><td style="padding: 6px 30px 0 30px; text-align: center;"><span style="font-size: 12px; line-height: 18px; color: #ffffff;">Tel: (028) 7309. 7379 - MST: 0318443116</span></td></tr>
|
||||
<tr><td style="padding: 6px 30px 0 30px; text-align: center;"><span style="font-size: 12px; line-height: 18px; color: #ffffff;">Email: <a href="mailto:support@tgs.com.vn" style="color: #ffffff; text-decoration: none;">support@tgs.com.vn</a></span></td></tr>
|
||||
<tr><td style="padding: 6px 30px 0 30px; text-align: center;"><span style="font-size: 12px; line-height: 18px; color: #ffffff;"><a href="https://www.tgs.com.vn" style="color: #ffffff; text-decoration: underline;">www.TGS.com.vn</a> & <a href="https://www.thegioiso.cloud" style="color: #ffffff; text-decoration: underline;">www.thegioiso.CLOUD</a> & <a href="https://www.thegioiserver.com" style="color: #ffffff; text-decoration: underline;">www.thegioiSERVER.com</a> & <a href="https://www.cloudemail.vn" style="color: #ffffff; text-decoration: underline;">www.CloudEmail.vn</a></span></td></tr>
|
||||
<tr><td style="padding: 6px 30px 16px 30px; text-align: center;"><span style="font-size: 12px; line-height: 20px; color: #ffffff; font-weight: bold;">Thế Giới Số - Premium HOSTING • CLOUD • SERVER & WEBSITE | 15+ năm Phụng Sự</span></td></tr>
|
||||
</tbody></table></td></tr>
|
||||
</tbody></table></td></tr></tbody></table>
|
||||
HTML;
|
||||
return '<tr class="Footer"><td style="box-sizing: border-box;" align="center" valign="top">'
|
||||
. '<table style="box-sizing: border-box; border-collapse: collapse; width: 700px; font-family: Montserrat,-apple-system,sans-serif; background-image: url(\'https://res.cloudinary.com/izpast9i/image/upload/v1786500298/email_footer.png\'); background-size: cover; background-position: center; background-repeat: no-repeat;" border="0" width="700" cellspacing="0" cellpadding="0" align="center" bgcolor="#F16723"><tbody>'
|
||||
. self::serviceBanner()
|
||||
. self::companyInfo()
|
||||
. '</tbody></table></td></tr>'
|
||||
. '</tbody></table></td></tr></tbody></table>';
|
||||
}
|
||||
|
||||
private static function serviceBanner(): string
|
||||
{
|
||||
$cells = '';
|
||||
foreach (self::SERVICE_LINKS as $label => $url) {
|
||||
$cells .= '<td style="box-sizing: border-box; border: 1px solid rgba(255,255,255,0.35); border-radius: 8px; padding: 6px 4px; font-size: 12px; line-height: 16px; color: #ffffff; text-align: center; background-color: rgba(255,255,255,0.18);" align="center" width="25%">'
|
||||
. '<a style="box-sizing: border-box; color: #ffffff; text-decoration: none;" href="' . $url . '" target="_blank" rel="noopener">' . $label . '</a></td>';
|
||||
}
|
||||
|
||||
return '<tr><td style="box-sizing: border-box; padding: 40px 30px 20px 30px; text-align: center;" align="center">'
|
||||
. '<table style="box-sizing: border-box; border-collapse: separate; border-spacing: 8px 0; width: 100%;" border="0" width="100%" cellspacing="0" cellpadding="0"><tbody><tr>'
|
||||
. $cells
|
||||
. '</tr></tbody></table></td></tr>';
|
||||
}
|
||||
|
||||
private static function companyInfo(): string
|
||||
{
|
||||
$line = fn (string $html, string $padding = '6px 30px 0 30px') => '<tr><td style="box-sizing: border-box; padding: ' . $padding . '; text-align: center;" align="center">' . $html . '</td></tr>';
|
||||
$text = 'box-sizing: border-box; font-size: 12px; line-height: 18px; color: #ffffff;';
|
||||
|
||||
return $line('<strong style="box-sizing: border-box; font-size: 14px; line-height: 22px; color: #ffffff;">CÔNG TY CỔ PHẦN GIẢI PHÁP CÔNG NGHỆ THẾ GIỚI SỐ</strong>')
|
||||
. $line('<span style="' . $text . '">Địa chỉ: 128/38 Tân Hương, Phường Phú Thọ Hòa, Thành Phố Hồ Chí Minh</span>')
|
||||
. $line('<span style="' . $text . '">Tel: (028) 7309. 7379 - MST: 0318443116</span>')
|
||||
. $line('<span style="' . $text . '">Email: <a style="box-sizing: border-box; color: #ffffff; text-decoration: none;" href="mailto:support@tgs.com.vn">support@tgs.com.vn</a></span>')
|
||||
. $line('<span style="box-sizing: border-box; font-size: 12px; line-height: 20px; color: #ffffff; font-weight: bold;">🥇 Thế Giới Số 🥇 - Premium HOSTING • CLOUD • SERVER & WEBSITE | 15+ năm Phụng Sự🚀</span>', '6px 30px 16px 30px');
|
||||
}
|
||||
|
||||
/**
|
||||
* Bọc một đoạn HTML thành email hoàn chỉnh (doctype + head). Thay cho blade
|
||||
* emails.customer.template-envelope — để không còn mail nào đi qua Blade.
|
||||
*/
|
||||
public static function document(?string $title, string $bodyHtml): string
|
||||
{
|
||||
$safeTitle = htmlspecialchars((string) $title, ENT_QUOTES, 'UTF-8');
|
||||
|
||||
Reference in New Issue
Block a user