sexta-feira, 28 de agosto de 2026

Meu Pau

Esse é meu Pau. Bonito??

Olá a todas

<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ContaAlerta - Gerenciador de Contas</title>
    
    <!-- Tailwind CSS para estilo rápido e responsivo -->
    <script src="https://cdn.tailwindcss.com"></script>
    
    <!-- Google Fonts -->
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">

    <style>
        body {
            font-family: 'Inter', sans-serif;
            background-color: #f3f4f6;
            -webkit-tap-highlight-color: transparent;
        }
        .card-shadow {
            box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
        }
        /* Animação suave para novos itens */
        @keyframes slideIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }
        .bill-item {
            animation: slideIn 0.3s ease-out;
        }
    </style>
</head>
<body class="bg-gray-100 min-h-screen text-gray-800 pb-20">

    <!-- Cabeçalho -->
    <header class="bg-blue-600 text-white p-4 shadow-md sticky top-0 z-10">
        <div class="max-w-md mx-auto flex justify-between items-center">
            <div>
                <h1 class="text-xl font-bold flex items-center gap-2">
                    <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><line x1="20" y1="8" x2="20" y2="14"></line><line x1="23" y1="11" x2="17" y2="11"></line></svg>
                    ContaAlerta
                </h1>
                <p class="text-xs text-blue-100 mt-1" id="dateDisplay">Carregando data...</p>
            </div>
            <button onclick="checkNotificationsManually()" class="bg-blue-500 hover:bg-blue-400 p-2 rounded-full transition" title="Verificar Notificações">
                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 8A6 6 0 0 0 6 8c0 7-3 9-3 9h18s-3-2-3-9"></path><path d="M13.73 21a2 2 0 0 1-3.46 0"></path></svg>
            </button>
        </div>
    </header>

    <main class="max-w-md mx-auto p-4 space-y-6">

        <!-- Card de Resumo -->
        <div class="bg-white rounded-xl p-5 card-shadow text-center">
            <h2 class="text-gray-500 text-sm font-medium uppercase tracking-wide">Total Pendente</h2>
            <div class="text-4xl font-bold text-gray-800 mt-2" id="totalPending">R$ 0,00</div>
            <p class="text-sm text-gray-400 mt-1" id="pendingCount">Nenhuma conta pendente</p>
        </div>

        <!-- Formulário de Adição -->
        <div class="bg-white rounded-xl p-5 card-shadow">
            <h3 class="font-bold text-lg mb-4 flex items-center gap-2">
                <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-blue-600"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="16"></line><line x1="8" y1="12" x2="16" y2="12"></line></svg>
                Nova Conta
            </h3>
            <form id="billForm" onsubmit="addBill(event)" class="space-y-4">
                <div class="grid grid-cols-2 gap-4">
                    <div>
                        <label class="block text-xs font-medium text-gray-700 mb-1">Tipo</label>
                        <div class="relative">
                            <select id="type" class="block w-full rounded-lg border-gray-300 bg-gray-50 border p-2.5 text-sm focus:border-blue-500 focus:ring-blue-500 outline-none">
                                <option value="luz">💡 Luz</option>
                                <option value="agua">💧 Água</option>
                                <option value="internet">🌐 Internet</option>
                                <option value="cartao">💳 Cartão</option>
                                <option value="outros">📝 Outros</option>
                            </select>
                        </div>
                    </div>
                    <div>
                        <label class="block text-xs font-medium text-gray-700 mb-1">Valor (R$)</label>
                        <input type="number" id="amount" step="0.01" required placeholder="0,00" class="block w-full rounded-lg border-gray-300 bg-gray-50 border p-2.5 text-sm focus:border-blue-500 focus:ring-blue-500 outline-none">
                    </div>
                </div>
                <div>
                    <label class="block text-xs font-medium text-gray-700 mb-1">Vencimento</label>
                    <input type="date" id="dueDate" required class="block w-full rounded-lg border-gray-300 bg-gray-50 border p-2.5 text-sm focus:border-blue-500 focus:ring-blue-500 outline-none text-gray-600">
                </div>
                <button type="submit" class="w-full text-white bg-blue-600 hover:bg-blue-700 font-medium rounded-lg text-sm px-5 py-3 text-center transition shadow-lg shadow-blue-500/30">
                    Agendar Lembrete
                </button>
            </form>
        </div>

        <!-- Lista de Contas -->
        <div>
            <h3 class="font-bold text-lg mb-3 text-gray-700">Minhas Contas</h3>
            <div id="billsList" class="space-y-3 pb-10">
                <!-- Os itens serão inseridos aqui via JS -->
            </div>
            <div id="emptyState" class="hidden text-center py-10 text-gray-400">
                <svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" class="mx-auto mb-3 opacity-50"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path><polyline points="14 2 14 8 20 8"></polyline><line x1="16" y1="13" x2="8" y2="13"></line><line x1="16" y1="17" x2="8" y2="17"></line><polyline points="10 9 9 9 8 9"></polyline></svg>
                <p>Nenhuma conta cadastrada.</p>
            </div>
        </div>

    </main>

    <!-- Notificação Toast (In-App) -->
    <div id="toast" class="fixed bottom-4 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white px-4 py-3 rounded-lg shadow-lg flex items-center gap-3 transition-all duration-300 opacity-0 translate-y-10 pointer-events-none z-50 w-11/12 max-w-sm">
        <div id="toastIcon">🔔</div>
        <div class="text-sm flex-1" id="toastMessage">Mensagem</div>
    </div>

    <script>
        // --- Configurações Iniciais ---
        let bills = JSON.parse(localStorage.getItem('contaAlertaBills')) || [];

        // --- Funções Auxiliares de Data ---
        function getTodayDateString() {
            const today = new Date();
            return today.toISOString().split('T')[0];
        }

        function formatDateBR(dateString) {
            if (!dateString) return '';
            const [year, month, day] = dateString.split('-');
            return `${day}/${month}/${year}`;
        }

        // Define a data mínima do input como hoje
        document.getElementById('dueDate').min = getTodayDateString();
        
        // Exibe data atual no header
        const optionsDate = { weekday: 'long', day: 'numeric', month: 'long' };
        document.getElementById('dateDisplay').innerText = new Date().toLocaleDateString('pt-BR', optionsDate);

        // --- Core do App ---

        function saveBills() {
            localStorage.setItem('contaAlertaBills', JSON.stringify(bills));
            renderBills();
            updateSummary();
        }

        function addBill(event) {
            event.preventDefault();

            const type = document.getElementById('type').value;
            const amount = parseFloat(document.getElementById('amount').value);
            const date = document.getElementById('dueDate').value;

            const newBill = {
                id: Date.now(),
                type,
                amount,
                date,
                paid: false
            };

            bills.push(newBill);
            saveBills();
            
            // Limpa o form
            document.getElementById('billForm').reset();
            showToast('Conta adicionada com sucesso!', 'success');
            
            // Verifica se precisa avisar algo imediatamente
            checkNotificationsManually();
        }

        function deleteBill(id) {
            if(confirm('Tem certeza que deseja excluir esta conta?')) {
                bills = bills.filter(bill => bill.id !== id);
                saveBills();
            }
        }

        function togglePaid(id) {
            const bill = bills.find(b => b.id === id);
            if (bill) {
                bill.paid = !bill.paid;
                saveBills();
                if(bill.paid) showToast('Conta marcada como paga! 🎉', 'success');
            }
        }

        function getStatus(dueDate, isPaid) {
            if (isPaid) return { text: 'PAGO', color: 'bg-green-100 text-green-700', icon: 'check' };

            const today = new Date();
            today.setHours(0,0,0,0);
            
            // Ajuste fuso horário para comparação correta
            const due = new Date(dueDate + 'T12:00:00'); 
            const diffTime = due - today;
            const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

            if (diffDays < 0) return { text: 'VENCIDO', color: 'bg-red-100 text-red-700', icon: 'alert' };
            if (diffDays === 0) return { text: 'HOJE', color: 'bg-orange-100 text-orange-700', icon: 'clock' };
            if (diffDays === 1) return { text: 'AMANHÃ', color: 'bg-yellow-100 text-yellow-800', icon: 'bell' };
            return { text: `Faltam ${diffDays} dias`, color: 'bg-blue-50 text-blue-600', icon: 'calendar' };
        }

        function getIconForType(type) {
            switch(type) {
                case 'luz': return '⚡';
                case 'agua': return '💧';
                case 'internet': return '🌐';
                case 'cartao': return '💳';
                default: return '📝';
            }
        }

        function renderBills() {
            const list = document.getElementById('billsList');
            const empty = document.getElementById('emptyState');
            
            list.innerHTML = '';

            // Ordenar: Pendentes e próximas primeiro
            const sortedBills = [...bills].sort((a, b) => {
                if (a.paid !== b.paid) return a.paid ? 1 : -1;
                return new Date(a.date) - new Date(b.date);
            });

            if (sortedBills.length === 0) {
                empty.classList.remove('hidden');
                return;
            } else {
                empty.classList.add('hidden');
            }

            sortedBills.forEach(bill => {
                const status = getStatus(bill.date, bill.paid);
                const typeLabel = bill.type.charAt(0).toUpperCase() + bill.type.slice(1);
                
                const html = `
                <div class="bill-item bg-white rounded-lg p-4 card-shadow flex items-center justify-between border-l-4 ${bill.paid ? 'border-green-500 opacity-60' : (status.text === 'VENCIDO' || status.text === 'HOJE' ? 'border-red-500' : 'border-blue-500')}">
                    <div class="flex items-center gap-3">
                        <div class="bg-gray-100 w-10 h-10 rounded-full flex items-center justify-center text-xl">
                            ${getIconForType(bill.type)}
                        </div>
                        <div>
                            <p class="font-bold text-gray-800">${typeLabel}</p>
                            <p class="text-sm text-gray-500">Vence: ${formatDateBR(bill.date)}</p>
                            <span class="inline-block mt-1 text-xs px-2 py-0.5 rounded-full font-bold ${status.color}">
                                ${status.text}
                            </span>
                        </div>
                    </div>
                    <div class="text-right">
                        <p class="font-bold text-gray-800">R$ ${bill.amount.toFixed(2).replace('.', ',')}</p>
                        <div class="flex gap-2 mt-2 justify-end">
                            <button onclick="togglePaid(${bill.id})" class="text-xs p-1.5 rounded bg-gray-100 hover:bg-gray-200 text-gray-600" title="${bill.paid ? 'Marcar como não pago' : 'Marcar como pago'}">
                                ${bill.paid ? '↩️' : '✅'}
                            </button>
                            <button onclick="deleteBill(${bill.id})" class="text-xs p-1.5 rounded bg-red-50 hover:bg-red-100 text-red-600" title="Excluir">
                                🗑️
                            </button>
                        </div>
                    </div>
                </div>
                `;
                list.innerHTML += html;
            });
        }

        function updateSummary() {
            const pending = bills.filter(b => !b.paid);
            const total = pending.reduce((acc, curr) => acc + curr.amount, 0);
            
            document.getElementById('totalPending').innerText = `R$ ${total.toFixed(2).replace('.', ',')}`;
            document.getElementById('pendingCount').innerText = pending.length === 1 
                ? '1 conta pendente' 
                : `${pending.length} contas pendentes`;
        }

        // --- Lógica de Notificação ---

        function requestNotificationPermission() {
            if (!("Notification" in window)) {
                console.log("Este navegador não suporta notificações de desktop");
                return;
            }
            if (Notification.permission !== "denied" && Notification.permission !== "granted") {
                Notification.requestPermission();
            }
        }

        function checkNotificationsManually() {
            // Verificar contas que vencem AMANHÃ ou HOJE e não estão pagas
            const today = new Date();
            today.setHours(0,0,0,0);

            const pendingBills = bills.filter(b => !b.paid);
            let alertCount = 0;

            pendingBills.forEach(bill => {
                const due = new Date(bill.date + 'T12:00:00');
                const diffTime = due - today;
                const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));

                // Lógica principal: Avisar se faltar 1 dia
                if (diffDays === 1) {
                    sendBrowserNotification(`Lembrete: ${bill.type}`, `Sua conta de R$ ${bill.amount} vence AMANHÃ!`);
                    alertCount++;
                } else if (diffDays === 0) {
                    sendBrowserNotification(`URGENTE: ${bill.type}`, `Sua conta vence HOJE!`);
                    alertCount++;
                }
            });

            if(alertCount > 0) {
                showToast(`Você tem ${alertCount} conta(s) precisando de atenção!`, 'warning');
            } else {
                showToast('Nenhuma notificação pendente.', 'info');
            }
        }

        function sendBrowserNotification(title, body) {
            if (Notification.permission === "granted") {
                new Notification(title, {
                    body: body,
                    icon: 'https://cdn-icons-png.flaticon.com/512/1077/1077884.png' // Ícone genérico de conta
                });
            }
        }

        // --- Toast (UI Notification) ---
        function showToast(message, type = 'info') {
            const toast = document.getElementById('toast');
            const msgEl = document.getElementById('toastMessage');
            const iconEl = document.getElementById('toastIcon');

            msgEl.innerText = message;
            
            if(type === 'success') {
                toast.className = "fixed bottom-4 left-1/2 transform -translate-x-1/2 bg-green-600 text-white px-4 py-3 rounded-lg shadow-lg flex items-center gap-3 transition-all duration-300 z-50 w-11/12 max-w-sm";
                iconEl.innerText = '✅';
            } else if (type === 'warning') {
                toast.className = "fixed bottom-4 left-1/2 transform -translate-x-1/2 bg-orange-600 text-white px-4 py-3 rounded-lg shadow-lg flex items-center gap-3 transition-all duration-300 z-50 w-11/12 max-w-sm";
                iconEl.innerText = '⚠️';
            } else {
                toast.className = "fixed bottom-4 left-1/2 transform -translate-x-1/2 bg-gray-800 text-white px-4 py-3 rounded-lg shadow-lg flex items-center gap-3 transition-all duration-300 z-50 w-11/12 max-w-sm";
                iconEl.innerText = 'ℹ️';
            }

            // Show
            toast.classList.remove('opacity-0', 'translate-y-10', 'pointer-events-none');
            
            // Hide after 3s
            setTimeout(() => {
                toast.classList.add('opacity-0', 'translate-y-10', 'pointer-events-none');
            }, 3000);
        }

        // --- Inicialização ---
        window.onload = function() {
            renderBills();
            updateSummary();
            requestNotificationPermission();
            
            // Verifica automaticamente ao carregar
            setTimeout(checkNotificationsManually, 1000);
        };

    </script>
</body>
</html>