fernando-bold commited on
Commit
070478f
·
verified ·
1 Parent(s): 9a6eb3a

"use client"

Browse files

import { useState, useEffect } from "react"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card"
import { Input } from "@/components/ui/input"
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Textarea } from "@/components/ui/textarea"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Separator } from "@/components/ui/separator"
import { ScrollArea } from "@/components/ui/scroll-area"
import { toast } from "@/hooks/use-toast"
import type { WhatsAppMessageTemplate, WhatsAppTemplateComponent } from "@/lib/services/whatsapp-service"
import { templateCategories } from "@/lib/templates/whatsapp-templates"
import { seasonalCategories } from "@/lib/templates/seasonal-templates"
import { CheckCircle, AlertCircle, Clock, Plus, Search, Save, RefreshCw, Zap, Send, Calendar } from "lucide-react"

export default function WhatsAppTemplatesPage() {
const [templates, setTemplates] = useState<WhatsAppMessageTemplate[]>([])
const [loading, setLoading] = useState(true)
const [selectedTemplate, setSelectedTemplate] = useState<WhatsAppMessageTemplate | null>(null)
const [activeTab, setActiveTab] = useState("all")
const [activeCategory, setActiveCategory] = useState("all")
const [searchQuery, setSearchQuery] = useState("")
const [isCreating, setIsCreating] = useState(false)
const [isSaving, setIsSaving] = useState(false)
const [isTesting, setIsTesting] = useState(false)
const [testPhoneNumber, setTestPhoneNumber] = useState("")
const [newTemplate, setNewTemplate] = useState({
name: "",
category: "UTILITY" as "MARKETING" | "UTILITY" | "AUTHENTICATION",
language: "pt_BR",
components: [] as WhatsAppTemplateComponent[],
})

// Fetch templates on component mount
useEffect(() => {
fetchTemplates()
}, [])

// Fetch templates from API
const fetchTemplates = async () => {
setLoading(true)
try {
// In a real implementation, this would call an API endpoint
// For now, we'll use the predefined templates
const standardTemplates: WhatsAppMessageTemplate[] = Object.values(templateCategories)
.flatMap((category) => Object.values(category))
.map((template) => ({
id: template.name,
name: template.name,
language: template.language,
components: template.components,
status: Math.random() > 0.3 ? "APPROVED" : Math.random() > 0.5 ? "PENDING" : "REJECTED",
category: "standard",
}))

// Add seasonal templates
const seasonalTemplatesList: WhatsAppMessageTemplate[] = Object.values(seasonalCategories)
.flatMap((category) => Object.values(category))
.map((template) => ({
id: template.name,
name: template.name,
language: template.language,
components: template.components,
status: Math.random() > 0.3 ? "APPROVED" : Math.random() > 0.5 ? "PENDING" : "REJECTED",
category: "seasonal",
}))

// Add additional templates for offers, purchases, checkouts
const additionalTemplates: WhatsAppMessageTemplate[] = [
{
id: "purchase_confirmation",
name: "purchase_confirmation",
language: "pt_BR",
components: [
{
type: "HEADER",
format: "TEXT",
text: "Compra Confirmada! 🔆",
},
{
type: "BODY",
text: "E aí, campeão da energia limpa! Sua compra do kit solar {{1}} foi confirmada. Valor total: R$ {{2}}. Prepare-se para revolucionar sua forma de consumir energia! Acompanhe o status do seu pedido #{{3}} pelo nosso app.",
example: {
body_text: [["Premium 450W", "15.990,00", "YS-78945"]],
},
},
{
type: "FOOTER",
text: "Yello Solar - Energia que não cai. Igual a gente.",
},
],
status: "APPROVED",
category: "transactional",
},
{
id: "checkout_abandoned",
name: "checkout_abandoned",
language: "pt_BR",
components: [
{
type: "HEADER",
format: "TEXT",
text: "Ei! Seu carrinho está com saudades 🛒",
},
{
type: "BODY",
text: "Fala, parceiro solar! Notamos que você deixou itens no carrinho. O kit {{1}} ainda está te esperando. Não perca a chance de economizar R$ {{2}} por mês na sua conta de luz. Bora finalizar essa revolução energética?",
example: {
body_text: [["Residencial 5kWp", "350,00"]],
},
},
{
type: "FOOTER",
text: "Yello Solar - A gente não desiste. De você e do planeta.",
},
{
type: "BUTTONS",
buttons: [
{
type: "URL",
text: "Finalizar Compra",
url: "https://yellosolar.com.br/checkout",
},
],
},
],
status: "APPROVED",
category: "transactional",
},
{
id: "special_promotion",
name: "special_promotion",
language: "pt_BR",
components: [
{
type: "HEADER",
format: "IMAGE",
},
{
type: "BODY",
text: "OFERTA RELÂMPAGO! ⚡ Só hoje: {{1}}% OFF em todos os kits solares. Use o cupom {{2}} e transforme sua casa em uma usina de economia. Oferta válida até {{3}}. Quem hesita não ilumina!",
example: {
body_text: [["25", "SOLPOWER25", "23:59 de hoje"]],
},
},
{
type: "FOOTER",
text: "Yello Solar - Ofertas tão quentes quanto o sol.",
},
{
type: "BUTTONS",
buttons: [
{
type: "URL",
text: "Ver Ofertas",
url: "https://yellosolar.com.br/promocoes",
},
],
},
],
status: "APPROVED",
category: "marketing",
},
{
id: "energy_savings_report",
name: "energy_savings_report",
language: "pt_BR",
components: [
{
type: "HEADER",
format: "TEXT",
text: "Relatório de Economia Solar 📊",
},
{
type: "BODY",
text: "Salve, revolucionário solar! Seu sistema gerou {{1}} kWh este mês, economizando R$ {{2}} na sua conta. Isso equivale a {{3}} árvores plantadas! Seu sistema está performando {{4}}% acima da média. Continue brilhando!",
example: {
body_text: [["580", "350,00", "12", "15"]],
},
},
{
type: "FOOTER",
text: "Yello Solar - Números que impressionam. Como nossos clientes.",
},
],
status: "APPROVED",
category: "transactional",
},
{
id: "financing_approved",
name: "financing_approved",
language: "pt_BR",
components: [
{
type: "HEADER",
format: "TEXT",
text: "Financiamento Aprovado! 💰",
},
{
type: "BODY",
text: "BOOOOM! Seu financiamento para o sistema solar foi APROVADO! Valor: R$ {{1}} em {{2}} parcelas de R$ {{3}}. Taxa de juros: {{4}}% a.a. Agora é só assinar o contrato digital que enviamos por email e começar a revolução energética na sua casa!",
example: {
body_text: [["25.990,00", "60", "599,00", "0,99"]],
},
},
{
type: "FOOTER",
text: "Yello Solar - Financiamos seu futuro brilhante.",
},
],
status: "APPROVED",
category: "transactional",
},
]

setTemplates([...standardTemplates, ...seasonalTemplatesList, ...additionalTemplates])
} catch (error) {
console.error("Error fetching templates:", error)
toast({
title: "Erro ao carregar templates",
description: "Não foi possível carregar os templates. Tente novamente.",
variant: "destructive",
})
} finally {
setLoading(false)
}
}

// Filter templates based on search query, active tab, and category
const filteredTemplates = templates.filter((template) => {
const matchesSearch = template.name.toLowerCase().includes(searchQuery.toLowerCase())
const matchesTab =
activeTab === "all" ||
(activeTab === "approved" && template.status === "APPROVED") ||
(activeTab === "pending" && template.status === "PENDING") ||
(activeTab === "rejected" && template.status === "REJECTED")
const matchesCategory = activeCategory === "all" || template.category === activeCategory

return matchesSearch && matchesTab && matchesCategory
})

// Handle template selection
const handleSelectTemplate = (template: WhatsAppMessageTemplate) => {
setSelectedTemplate(template)
setIsCreating(false)
}

// Handle creating a new template
const handleCreateNew = () => {
setIsCreating(true)
setSelectedTemplate(null)
setNewTemplate({
name: "",
category: "UTILITY",
language: "pt_BR",
components: [
{
type: "HEADER",
format: "TEXT",
text: "",
},
{
type: "BODY",
text: "",
},
{
type: "FOOTER",
text: "Yello Solar - Energia limpa para todos",
},
],
})
}

// Handle saving a template
const handleSaveTemplate = async () => {
setIsSaving(true)
try {

Files changed (7) hide show
  1. README.md +7 -4
  2. components/navbar.js +41 -0
  3. components/status-badge.js +57 -0
  4. components/template-card.js +104 -0
  5. index.html +44 -19
  6. script.js +108 -0
  7. style.css +36 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Whatsapp Template Wizard
3
- emoji: 👁
4
- colorFrom: red
5
  colorTo: pink
 
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: WhatsApp Template Wizard
3
+ colorFrom: yellow
 
4
  colorTo: pink
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://huggingface.co/deepsite).
components/navbar.js ADDED
@@ -0,0 +1,41 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomNavbar extends HTMLElement {
2
+ connectedCallback() {
3
+ this.attachShadow({ mode: 'open' });
4
+ this.shadowRoot.innerHTML = `
5
+ <style>
6
+ .navbar {
7
+ background-color: white;
8
+ box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
9
+ }
10
+ .nav-link:hover {
11
+ color: #3B82F6;
12
+ }
13
+ </style>
14
+ <div class="navbar px-6 py-4 rounded-xl">
15
+ <div class="flex justify-between items-center">
16
+ <div class="flex items-center space-x-8">
17
+ <a href="#" class="text-xl font-bold text-gray-800 flex items-center">
18
+ <i data-feather="message-square" class="text-primary-500 mr-2"></i>
19
+ WhatsApp Template Wizard
20
+ </a>
21
+ <nav class="hidden md:flex space-x-6">
22
+ <a href="#" class="nav-link text-gray-600 hover:text-primary-500">Templates</a>
23
+ <a href="#" class="nav-link text-gray-600 hover:text-primary-500">Categories</a>
24
+ <a href="#" class="nav-link text-gray-600 hover:text-primary-500">Analytics</a>
25
+ </nav>
26
+ </div>
27
+ <div class="flex items-center space-x-4">
28
+ <button class="p-2 rounded-full hover:bg-gray-100">
29
+ <i data-feather="bell"></i>
30
+ </button>
31
+ <div class="w-8 h-8 rounded-full bg-primary-500 flex items-center justify-center text-white">
32
+ <i data-feather="user"></i>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ </div>
37
+ `;
38
+ }
39
+ }
40
+
41
+ customElements.define('custom-navbar', CustomNavbar);
components/status-badge.js ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class StatusBadge extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.attachShadow({ mode: 'open' });
5
+ }
6
+
7
+ connectedCallback() {
8
+ const status = this.getAttribute('status') || '';
9
+ const icon = this.getAttribute('icon') || '';
10
+
11
+ this.shadowRoot.innerHTML = `
12
+ <style>
13
+ .badge {
14
+ display: inline-flex;
15
+ align-items: center;
16
+ padding: 0.25rem 0.5rem;
17
+ border-radius: 9999px;
18
+ font-size: 0.75rem;
19
+ line-height: 1rem;
20
+ font-weight: 500;
21
+ }
22
+ .approved {
23
+ background-color: #ECFDF5;
24
+ color: #059669;
25
+ }
26
+ .pending {
27
+ background-color: #FEF3C7;
28
+ color: #D97706;
29
+ }
30
+ .rejected {
31
+ background-color: #FEE2E2;
32
+ color: #DC2626;
33
+ }
34
+ .icon {
35
+ width: 0.75rem;
36
+ height: 0.75rem;
37
+ margin-right: 0.25rem;
38
+ }
39
+ </style>
40
+ <span class="badge ${status}">
41
+ ${icon ? `<i data-feather="${icon}" class="icon"></i>` : ''}
42
+ ${this.getStatusText(status)}
43
+ </span>
44
+ `;
45
+ }
46
+
47
+ getStatusText(status) {
48
+ switch(status) {
49
+ case 'approved': return 'Approved';
50
+ case 'pending': return 'Pending';
51
+ case 'rejected': return 'Rejected';
52
+ default: return status;
53
+ }
54
+ }
55
+ }
56
+
57
+ customElements.define('status-badge', StatusBadge);
components/template-card.js ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ class CustomTemplateCard extends HTMLElement {
2
+ constructor() {
3
+ super();
4
+ this.attachShadow({ mode: 'open' });
5
+ }
6
+
7
+ connectedCallback() {
8
+ const name = this.getAttribute('name') || '';
9
+ const status = this.getAttribute('status') || '';
10
+ const category = this.getAttribute('category') || '';
11
+ const language = this.getAttribute('language') || '';
12
+
13
+ this.shadowRoot.innerHTML = `
14
+ <style>
15
+ .card {
16
+ transition: all 0.2s ease;
17
+ cursor: pointer;
18
+ }
19
+ .card:hover {
20
+ transform: translateY(-2px);
21
+ box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
22
+ }
23
+ .badge-approved {
24
+ background-color: #10B981;
25
+ color: white;
26
+ }
27
+ .badge-pending {
28
+ background-color: #F59E0B;
29
+ color: white;
30
+ }
31
+ .badge-rejected {
32
+ background-color: #EF4444;
33
+ color: white;
34
+ }
35
+ .badge-transactional {
36
+ background-color: #8B5CF6;
37
+ color: white;
38
+ }
39
+ .badge-marketing {
40
+ background-color: #F97316;
41
+ color: white;
42
+ }
43
+ .badge-seasonal {
44
+ background-color: #3B82F6;
45
+ color: white;
46
+ }
47
+ </style>
48
+ <div class="card bg-white p-4 rounded-lg border border-gray-200">
49
+ <div class="flex justify-between items-start">
50
+ <div>
51
+ <h3 class="font-medium text-gray-800">${name.replace(/_/g, ' ')}</h3>
52
+ <div class="flex items-center mt-2 space-x-2">
53
+ <span class="text-xs px-2 py-1 rounded-full ${this.getCategoryClass(category)}">
54
+ ${this.getCategoryName(category)}
55
+ </span>
56
+ <span class="text-xs text-gray-500">${language}</span>
57
+ </div>
58
+ </div>
59
+ <span class="text-xs px-2 py-1 rounded-full ${this.getStatusClass(status)}">
60
+ ${this.getStatusName(status)}
61
+ </span>
62
+ </div>
63
+ </div>
64
+ `;
65
+ }
66
+
67
+ getStatusClass(status) {
68
+ switch(status) {
69
+ case 'approved': return 'badge-approved';
70
+ case 'pending': return 'badge-pending';
71
+ case 'rejected': return 'badge-rejected';
72
+ default: return 'bg-gray-100 text-gray-800';
73
+ }
74
+ }
75
+
76
+ getStatusName(status) {
77
+ switch(status) {
78
+ case 'approved': return 'Approved';
79
+ case 'pending': return 'Pending';
80
+ case 'rejected': return 'Rejected';
81
+ default: return status;
82
+ }
83
+ }
84
+
85
+ getCategoryClass(category) {
86
+ switch(category) {
87
+ case 'transactional': return 'badge-transactional';
88
+ case 'marketing': return 'badge-marketing';
89
+ case 'seasonal': return 'badge-seasonal';
90
+ default: return 'bg-gray-100 text-gray-800';
91
+ }
92
+ }
93
+
94
+ getCategoryName(category) {
95
+ switch(category) {
96
+ case 'transactional': return 'Transactional';
97
+ case 'marketing': return 'Marketing';
98
+ case 'seasonal': return 'Seasonal';
99
+ default: return category;
100
+ }
101
+ }
102
+ }
103
+
104
+ customElements.define('custom-template-card', CustomTemplateCard);
index.html CHANGED
@@ -1,19 +1,44 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>WhatsApp Template Wizard</title>
7
+ <link rel="stylesheet" href="style.css">
8
+ <script src="https://cdn.tailwindcss.com"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <script src="https://unpkg.com/feather-icons"></script>
11
+ <script>
12
+ tailwind.config = {
13
+ theme: {
14
+ extend: {
15
+ colors: {
16
+ primary: {
17
+ 500: '#F59E0B',
18
+ 600: '#D97706',
19
+ },
20
+ secondary: {
21
+ 500: '#3B82F6',
22
+ 600: '#2563EB',
23
+ }
24
+ }
25
+ }
26
+ }
27
+ }
28
+ </script>
29
+ </head>
30
+ <body class="bg-gray-50">
31
+ <div id="app" class="container mx-auto py-8">
32
+ <!-- App content will be rendered here -->
33
+ </div>
34
+
35
+ <script src="components/navbar.js"></script>
36
+ <script src="components/template-card.js"></script>
37
+ <script src="components/status-badge.js"></script>
38
+ <script src="script.js"></script>
39
+ <script>
40
+ feather.replace();
41
+ </script>
42
+ <script src="https://huggingface.co/deepsite/deepsite-badge.js"></script>
43
+ </body>
44
+ </html>
script.js ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ document.addEventListener('DOMContentLoaded', () => {
2
+ const app = document.getElementById('app');
3
+
4
+ // Main app structure
5
+ app.innerHTML = `
6
+ <custom-navbar></custom-navbar>
7
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-6 mt-8">
8
+ <!-- Templates list column -->
9
+ <div class="md:col-span-1">
10
+ <div class="bg-white rounded-xl shadow-sm p-6">
11
+ <div class="flex justify-between items-center mb-6">
12
+ <h2 class="text-xl font-bold text-gray-800">Templates</h2>
13
+ <button class="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg flex items-center">
14
+ <i data-feather="plus" class="w-4 h-4 mr-2"></i>
15
+ New
16
+ </button>
17
+ </div>
18
+
19
+ <div class="relative mb-4">
20
+ <i data-feather="search" class="absolute left-3 top-3 text-gray-400"></i>
21
+ <input type="text" placeholder="Search templates..."
22
+ class="w-full pl-10 pr-4 py-2 border border-gray-200 rounded-lg focus:ring-2 focus:ring-primary-500 focus:border-primary-500">
23
+ </div>
24
+
25
+ <div class="space-y-2 mb-4">
26
+ <button class="px-3 py-1 text-sm rounded-full bg-primary-100 text-primary-800">All</button>
27
+ <button class="px-3 py-1 text-sm rounded-full bg-gray-100 text-gray-800">Approved</button>
28
+ <button class="px-3 py-1 text-sm rounded-full bg-gray-100 text-gray-800">Pending</button>
29
+ <button class="px-3 py-1 text-sm rounded-full bg-gray-100 text-gray-800">Rejected</button>
30
+ </div>
31
+
32
+ <div class="space-y-3 h-[500px] overflow-y-auto">
33
+ <!-- Template cards will be inserted here -->
34
+ <custom-template-card
35
+ name="purchase_confirmation"
36
+ status="approved"
37
+ category="transactional"
38
+ language="pt_BR"
39
+ ></custom-template-card>
40
+
41
+ <custom-template-card
42
+ name="checkout_abandoned"
43
+ status="approved"
44
+ category="marketing"
45
+ language="pt_BR"
46
+ ></custom-template-card>
47
+
48
+ <custom-template-card
49
+ name="special_promotion"
50
+ status="pending"
51
+ category="marketing"
52
+ language="pt_BR"
53
+ ></custom-template-card>
54
+ </div>
55
+ </div>
56
+ </div>
57
+
58
+ <!-- Template editor column -->
59
+ <div class="md:col-span-2">
60
+ <div class="bg-white rounded-xl shadow-sm p-6 template-editor">
61
+ <div class="text-center py-12">
62
+ <div class="mx-auto w-12 h-12 rounded-full bg-primary-100 flex items-center justify-center mb-4">
63
+ <i data-feather="zap" class="text-primary-500"></i>
64
+ </div>
65
+ <h3 class="text-lg font-medium mb-2">No template selected</h3>
66
+ <p class="text-gray-500 mb-4">Select a template from the list or create a new one</p>
67
+ <button class="bg-primary-500 hover:bg-primary-600 text-white px-4 py-2 rounded-lg">
68
+ Create New Template
69
+ </button>
70
+ </div>
71
+ </div>
72
+ </div>
73
+ </div>
74
+ `;
75
+
76
+ // Initialize feather icons
77
+ feather.replace();
78
+ });
79
+
80
+ // Sample data for templates
81
+ const templates = [
82
+ {
83
+ id: "purchase_confirmation",
84
+ name: "purchase_confirmation",
85
+ language: "pt_BR",
86
+ components: [
87
+ {
88
+ type: "HEADER",
89
+ format: "TEXT",
90
+ text: "Compra Confirmada! 🔆",
91
+ },
92
+ {
93
+ type: "BODY",
94
+ text: "E aí, campeão da energia limpa! Sua compra do kit solar {{1}} foi confirmada. Valor total: R$ {{2}}. Prepare-se para revolucionar sua forma de consumir energia! Acompanhe o status do seu pedido #{{3}} pelo nosso app.",
95
+ example: {
96
+ body_text: [["Premium 450W", "15.990,00", "YS-78945"]],
97
+ },
98
+ },
99
+ {
100
+ type: "FOOTER",
101
+ text: "Yello Solar - Energia que não cai. Igual a gente.",
102
+ },
103
+ ],
104
+ status: "APPROVED",
105
+ category: "transactional",
106
+ },
107
+ // More templates...
108
+ ];
style.css CHANGED
@@ -1,28 +1,46 @@
 
 
1
  body {
2
- padding: 2rem;
3
- font-family: -apple-system, BlinkMacSystemFont, "Arial", sans-serif;
 
 
 
 
 
 
 
 
 
 
 
 
4
  }
5
 
6
- h1 {
7
- font-size: 16px;
8
- margin-top: 0;
 
 
 
 
9
  }
10
 
11
- p {
12
- color: rgb(107, 114, 128);
13
- font-size: 15px;
14
- margin-bottom: 10px;
15
- margin-top: 5px;
16
  }
17
 
18
- .card {
19
- max-width: 620px;
20
- margin: 0 auto;
21
- padding: 16px;
22
- border: 1px solid lightgray;
23
- border-radius: 16px;
24
  }
25
 
26
- .card p:last-child {
27
- margin-bottom: 0;
 
28
  }
 
 
 
 
 
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
2
+
3
  body {
4
+ font-family: 'Inter', sans-serif;
5
+ }
6
+
7
+ .template-card:hover {
8
+ transform: translateY(-2px);
9
+ box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
10
+ }
11
+
12
+ .template-editor {
13
+ transition: all 0.3s ease;
14
+ }
15
+
16
+ .loading-spinner {
17
+ animation: spin 1s linear infinite;
18
  }
19
 
20
+ @keyframes spin {
21
+ from {
22
+ transform: rotate(0deg);
23
+ }
24
+ to {
25
+ transform: rotate(360deg);
26
+ }
27
  }
28
 
29
+ /* Custom scrollbar */
30
+ ::-webkit-scrollbar {
31
+ width: 8px;
32
+ height: 8px;
 
33
  }
34
 
35
+ ::-webkit-scrollbar-track {
36
+ background: #f1f1f1;
 
 
 
 
37
  }
38
 
39
+ ::-webkit-scrollbar-thumb {
40
+ background: #cbd5e0;
41
+ border-radius: 4px;
42
  }
43
+
44
+ ::-webkit-scrollbar-thumb:hover {
45
+ background: #a0aec0;
46
+ }