Improve shortcode UI and add payment link shortcodes
✨ UI Improvements: - Completely redesigned shortcode display with clean categorization - Added collapsible section for all available shortcodes - Used emoji icons for better visual organization - Improved color coding and typography - Added "Used in this template" section with visual distinction ➕ New Shortcodes: - Added {payment_link} for direct payment links in emails - Added {thank_you_page} for public thank you page access - Updated relevant templates to include new payment shortcodes 🎯 Key Features: - Shortcodes organized by category (User, Order, Product, Access, etc.) - Visual hierarchy with proper spacing and borders - Hover effects and smooth transitions - Better readability with proper contrast 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -179,53 +179,193 @@ export function EmailTemplatePreview({
|
||||
</div>
|
||||
|
||||
{/* Shortcodes Used */}
|
||||
<div className="p-3 bg-blue-50 border border-blue-200 rounded">
|
||||
<h4 className="font-semibold text-sm mb-2">Shortcodes Used in This Template:</h4>
|
||||
<div className="grid grid-cols-2 md:grid-cols-3 gap-2 text-sm max-h-32 overflow-y-auto">
|
||||
{[
|
||||
// User information
|
||||
'{nama}', '{email}',
|
||||
// Order information
|
||||
'{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{status_pesanan}', '{invoice_url}',
|
||||
// Product information
|
||||
'{produk}', '{kategori_produk}', '{harga_produk}', '{deskripsi_produk}',
|
||||
// Access information
|
||||
'{link_akses}', '{username_akses}', '{password_akses}', '{kadaluarsa_akses}',
|
||||
// Consulting information
|
||||
'{tanggal_konsultasi}', '{jam_konsultasi}', '{durasi_konsultasi}', '{link_meet}',
|
||||
'{jenis_konsultasi}', '{topik_konsultasi}',
|
||||
// Event information
|
||||
'{judul_event}', '{tanggal_event}', '{jam_event}', '{link_event}', '{lokasi_event}', '{kapasitas_event}',
|
||||
// Bootcamp/Course information
|
||||
'{judul_bootcamp}', '{progres_bootcamp}', '{modul_selesai}', '{modul_selanjutnya}', '{link_progress}',
|
||||
// Company information
|
||||
'{nama_perusahaan}', '{website_perusahaan}', '{email_support}', '{telepon_support}',
|
||||
// Payment information
|
||||
'{bank_tujuan}', '{nomor_rekening}', '{atas_nama}', '{jumlah_pembayaran}', '{batas_pembayaran}'
|
||||
].filter(shortcode =>
|
||||
(template.email_subject && template.email_subject.includes(shortcode)) ||
|
||||
(template.email_body_html && template.email_body_html.includes(shortcode))
|
||||
).map(shortcode => (
|
||||
<code key={shortcode} className="bg-blue-100 px-2 py-1 rounded text-xs">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
{((template.email_subject && template.email_subject.includes('{')) ||
|
||||
(template.email_body_html && template.email_body_html.includes('{'))) && (
|
||||
<div className="mt-3 pt-3 border-t border-blue-200">
|
||||
<p className="text-xs text-blue-700">
|
||||
<strong>All Available Shortcodes:</strong> User ({`{nama}`}, {`{email}`}), Orders ({`{order_id}`}, {`{tanggal_pesanan}`}, {`{total}`}, {`{metode_pembayaran}`}, {`{status_pesanan}`}, {`{invoice_url}`}),
|
||||
Products ({`{produk}`}, {`{kategori_produk}`}, {`{harga_produk}`}),
|
||||
Access ({`{link_akses}`}, {`{username_akses}`}, {`{password_akses}`}),
|
||||
Consulting ({`{tanggal_konsultasi}`}, {`{jam_konsultasi}`}, {`{link_meet}`}),
|
||||
Events ({`{judul_event}`}, {`{tanggal_event}`}, {`{link_event}`}),
|
||||
Bootcamp ({`{judul_bootcamp}`}, {`{progres_bootcamp}`}, {`{modul_selesai}`}),
|
||||
Payment ({`{bank_tujuan}`}, {`{nomor_rekening}`}, {`{jumlah_pembayaran}`}),
|
||||
Company ({`{nama_perusahaan}`}, {`{email_support}`})
|
||||
</p>
|
||||
<div className="p-4 bg-blue-50 border border-blue-200 rounded-lg">
|
||||
<h4 className="font-semibold text-sm mb-3 flex items-center gap-2">
|
||||
<span className="w-2 h-2 bg-blue-500 rounded-full"></span>
|
||||
Shortcodes Available
|
||||
</h4>
|
||||
|
||||
{/* Used in this template */}
|
||||
<div className="mb-4">
|
||||
<p className="text-xs font-medium text-blue-700 mb-2">Used in this template:</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{[
|
||||
// User information
|
||||
'{nama}', '{email}',
|
||||
// Order information
|
||||
'{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{status_pesanan}', '{invoice_url}',
|
||||
// Product information
|
||||
'{produk}', '{kategori_produk}', '{harga_produk}', '{deskripsi_produk}',
|
||||
// Access information
|
||||
'{link_akses}', '{username_akses}', '{password_akses}', '{kadaluarsa_akses}',
|
||||
// Consulting information
|
||||
'{tanggal_konsultasi}', '{jam_konsultasi}', '{durasi_konsultasi}', '{link_meet}',
|
||||
'{jenis_konsultasi}', '{topik_konsultasi}',
|
||||
// Event information
|
||||
'{judul_event}', '{tanggal_event}', '{jam_event}', '{link_event}', '{lokasi_event}', '{kapasitas_event}',
|
||||
// Bootcamp/Course information
|
||||
'{judul_bootcamp}', '{progres_bootcamp}', '{modul_selesai}', '{modul_selanjutnya}', '{link_progress}',
|
||||
// Company information
|
||||
'{nama_perusahaan}', '{website_perusahaan}', '{email_support}', '{telepon_support}',
|
||||
// Payment information
|
||||
'{bank_tujuan}', '{nomor_rekening}', '{atas_nama}', '{jumlah_pembayaran}', '{batas_pembayaran}',
|
||||
'{payment_link}', '{thank_you_page}'
|
||||
].filter(shortcode =>
|
||||
(template.email_subject && template.email_subject.includes(shortcode)) ||
|
||||
(template.email_body_html && template.email_body_html.includes(shortcode))
|
||||
).map(shortcode => (
|
||||
<code key={shortcode} className="bg-blue-100 text-blue-800 px-2 py-1 rounded text-xs font-mono border border-blue-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
{![
|
||||
// User information
|
||||
'{nama}', '{email}',
|
||||
// Order information
|
||||
'{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{status_pesanan}', '{invoice_url}',
|
||||
// Product information
|
||||
'{produk}', '{kategori_produk}', '{harga_produk}', '{deskripsi_produk}',
|
||||
// Access information
|
||||
'{link_akses}', '{username_akses}', '{password_akses}', '{kadaluarsa_akses}',
|
||||
// Consulting information
|
||||
'{tanggal_konsultasi}', '{jam_konsultasi}', '{durasi_konsultasi}', '{link_meet}',
|
||||
'{jenis_konsultasi}', '{topik_konsultasi}',
|
||||
// Event information
|
||||
'{judul_event}', '{tanggal_event}', '{jam_event}', '{link_event}', '{lokasi_event}', '{kapasitas_event}',
|
||||
// Bootcamp/Course information
|
||||
'{judul_bootcamp}', '{progres_bootcamp}', '{modul_selesai}', '{modul_selanjutnya}', '{link_progress}',
|
||||
// Company information
|
||||
'{nama_perusahaan}', '{website_perusahaan}', '{email_support}', '{telepon_support}',
|
||||
// Payment information
|
||||
'{bank_tujuan}', '{nomor_rekening}', '{atas_nama}', '{jumlah_pembayaran}', '{batas_pembayaran}',
|
||||
'{payment_link}', '{thank_you_page}'
|
||||
].some(shortcode =>
|
||||
(template.email_subject && template.email_subject.includes(shortcode)) ||
|
||||
(template.email_body_html && template.email_body_html.includes(shortcode))
|
||||
) && (
|
||||
<span className="text-xs text-gray-500 italic">No shortcodes used yet</span>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* All available shortcodes */}
|
||||
<details className="group">
|
||||
<summary className="cursor-pointer text-xs font-medium text-blue-700 hover:text-blue-900 transition-colors flex items-center gap-1">
|
||||
<span className="group-open:rotate-90 transition-transform">▶</span>
|
||||
View all available shortcodes
|
||||
</summary>
|
||||
<div className="mt-3 pt-3 border-t border-blue-200 space-y-3">
|
||||
|
||||
{/* User Information */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-gray-700 mb-1">👤 User Information</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{['{nama}', '{email}'].map(shortcode => (
|
||||
<code key={shortcode} className="bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs font-mono border border-gray-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Order Information */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-gray-700 mb-1">📦 Order Information</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{['{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{status_pesanan}', '{invoice_url}'].map(shortcode => (
|
||||
<code key={shortcode} className="bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs font-mono border border-gray-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Product Information */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-gray-700 mb-1">🛍️ Product Information</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{['{produk}', '{kategori_produk}', '{harga_produk}', '{deskripsi_produk}'].map(shortcode => (
|
||||
<code key={shortcode} className="bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs font-mono border border-gray-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Access Information */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-gray-700 mb-1">🔐 Access Information</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{['{link_akses}', '{username_akses}', '{password_akses}', '{kadaluarsa_akses}'].map(shortcode => (
|
||||
<code key={shortcode} className="bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs font-mono border border-gray-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Payment Information */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-gray-700 mb-1">💳 Payment Information</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{['{bank_tujuan}', '{nomor_rekening}', '{atas_nama}', '{jumlah_pembayaran}', '{batas_pembayaran}', '{payment_link}', '{thank_you_page}'].map(shortcode => (
|
||||
<code key={shortcode} className="bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs font-mono border border-gray-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Consulting Information */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-gray-700 mb-1">📅 Consulting Information</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{['{tanggal_konsultasi}', '{jam_konsultasi}', '{durasi_konsultasi}', '{link_meet}', '{jenis_konsultasi}', '{topik_konsultasi}'].map(shortcode => (
|
||||
<code key={shortcode} className="bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs font-mono border border-gray-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Event Information */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-gray-700 mb-1">🎪 Event Information</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{['{judul_event}', '{tanggal_event}', '{jam_event}', '{link_event}', '{lokasi_event}', '{kapasitas_event}'].map(shortcode => (
|
||||
<code key={shortcode} className="bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs font-mono border border-gray-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Bootcamp Information */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-gray-700 mb-1">🎓 Bootcamp Information</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{['{judul_bootcamp}', '{progres_bootcamp}', '{modul_selesai}', '{modul_selanjutnya}', '{link_progress}'].map(shortcode => (
|
||||
<code key={shortcode} className="bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs font-mono border border-gray-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Company Information */}
|
||||
<div>
|
||||
<p className="text-xs font-semibold text-gray-700 mb-1">🏢 Company Information</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{['{nama_perusahaan}', '{website_perusahaan}', '{email_support}', '{telepon_support}'].map(shortcode => (
|
||||
<code key={shortcode} className="bg-gray-100 text-gray-700 px-2 py-1 rounded text-xs font-mono border border-gray-300">
|
||||
{shortcode}
|
||||
</code>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
|
||||
{/* Template Actions */}
|
||||
|
||||
@@ -24,10 +24,10 @@ interface NotificationTemplate {
|
||||
}
|
||||
|
||||
const RELEVANT_SHORTCODES = {
|
||||
'payment_success': ['{nama}', '{email}', '{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{produk}', '{link_akses}'],
|
||||
'payment_success': ['{nama}', '{email}', '{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{produk}', '{link_akses}', '{thank_you_page}'],
|
||||
'access_granted': ['{nama}', '{email}', '{produk}', '{link_akses}', '{username_akses}', '{password_akses}', '{kadaluarsa_akses}'],
|
||||
'order_created': ['{nama}', '{email}', '{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{produk}'],
|
||||
'payment_reminder': ['{nama}', '{email}', '{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{batas_pembayaran}', '{jumlah_pembayaran}', '{bank_tujuan}', '{nomor_rekening}'],
|
||||
'order_created': ['{nama}', '{email}', '{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{produk}', '{payment_link}'],
|
||||
'payment_reminder': ['{nama}', '{email}', '{order_id}', '{tanggal_pesanan}', '{total}', '{metode_pembayaran}', '{batas_pembayaran}', '{jumlah_pembayaran}', '{bank_tujuan}', '{nomor_rekening}', '{payment_link}'],
|
||||
'consulting_scheduled': ['{nama}', '{email}', '{tanggal_konsultasi}', '{jam_konsultasi}', '{durasi_konsultasi}', '{link_meet}', '{jenis_konsultasi}', '{topik_konsultasi}'],
|
||||
'event_reminder': ['{nama}', '{email}', '{judul_event}', '{tanggal_event}', '{jam_event}', '{link_event}', '{lokasi_event}', '{kapasitas_event}'],
|
||||
'bootcamp_progress': ['{nama}', '{email}', '{judul_bootcamp}', '{progres_bootcamp}', '{modul_selesai}', '{modul_selanjutnya}', '{link_progress}'],
|
||||
|
||||
@@ -405,7 +405,9 @@ export class ShortcodeProcessor {
|
||||
nomor_rekening: '123-456-7890',
|
||||
atas_nama: 'PT Access Hub Indonesia',
|
||||
jumlah_pembayaran: 'Rp 1.500.000',
|
||||
batas_pembayaran: '22 Desember 2025 23:59'
|
||||
batas_pembayaran: '22 Desember 2025 23:59',
|
||||
payment_link: 'https://accesshub.example.com/payment/ORD-123456',
|
||||
thank_you_page: 'https://accesshub.example.com/thank-you/ORD-123456'
|
||||
};
|
||||
|
||||
static process(content: string, customData: Record<string, string> = {}): string {
|
||||
|
||||
Reference in New Issue
Block a user