const getAccessToken = () => { if (typeof window !== 'undefined') return localStorage.getItem('token') || ''; return ''; }; export const normalizeJid = (jid: string) => { if (!jid) return ''; const [user] = jid.split('@'); const [cleanUser] = user.split(':'); return cleanUser; }; export const formatPhone = (phone: string, remoteJid?: string): string => { const raw = String(phone || '').trim(); const jid = String(remoteJid || ''); const cleaned = raw.replace(/\D/g, ''); // ── @lid — identificador interno do WhatsApp: exibe como +número ────────── if (jid.endsWith('@lid')) { const id = (normalizeJid(jid) || cleaned).replace(/\D/g, ''); return id ? `+${id}` : raw; } // ── Brasil (55) — 12 ou 13 dígitos ─────────────────────────────────────── if ((cleaned.length === 12 || cleaned.length === 13) && cleaned.startsWith('55')) { return cleaned.replace(/^(\d{2})(\d{2})(\d{4,5})(\d{4})$/, '+$1 $2 $3-$4'); } // ── EUA / Canadá (1) — 11 dígitos ──────────────────────────────────────── if (cleaned.length === 11 && cleaned.startsWith('1')) { return cleaned.replace(/^(\d{1})(\d{3})(\d{3})(\d{4})$/, '+$1 ($2) $3-$4'); } // ── Outros países — formato E.164 genérico ──────────────────────────────── if (cleaned.length >= 7 && cleaned.length <= 15) { return `+${cleaned}`; } return raw || cleaned; }; export const getAvatarInitials = (chat: any) => { const name = chat.displayName || chat.subject || chat.phone || ''; return name.slice(0, 2).toUpperCase(); }; export const getAvatarColor = (id: string): string => { let hash = 0; const cleanId = String(id || 'anon'); for (let i = 0; i < cleanId.length; i++) { hash = cleanId.charCodeAt(i) + ((hash << 5) - hash); } const h = Math.abs(hash % 360); // HSL: S=65%, L=45% for a vibrant, accessible look with white text return `hsl(${h}, 65%, 45%)`; }; export const getLabelColor = (index: number) => { const colors = [ 'bg-gray-500', 'bg-red-500', 'bg-orange-500', 'bg-yellow-500', 'bg-green-500', 'bg-teal-500', 'bg-blue-500', 'bg-indigo-500', 'bg-purple-500', 'bg-pink-500' ]; return colors[index % colors.length] || 'bg-gray-500'; }; export const getMediaUrl = (url: string | null | undefined): string | null => { if (!url) return null; if (url.startsWith('http')) return url; const apiBase = ''; // satélite: same-origin (URLs http/Wasabi já retornam acima) // Path local (/media/...) — servido pelo Express static do backend if (url.startsWith('/media/')) return `${apiBase}${url}`; // Path Wasabi — proxiado pela rota /api/storage/view/ do backend const clean = url.startsWith('/') ? url.slice(1) : url; return `${apiBase}/api/storage/view/${clean}`; }; export const getAvatarProxyUrl = (chat: any, _type: 'instance' | 'contact' = 'contact'): string | null => { // Satélite: não há proxy de avatar exposto na ext API — retorna null e o // componente Avatar cai para as iniciais (fallback limpo, sem 404s). return null; }; export const parseSafeDate = (timestamp: any): Date => { if (!timestamp) return new Date(); let d = new Date(timestamp); // If invalid and a number (or numeric string) if (isNaN(d.getTime())) { const num = Number(timestamp); if (!isNaN(num)) { // Unix seconds (Whats APIs often use this) vs ms d = new Date(num > 10000000000 ? num : num * 1000); } } return isNaN(d.getTime()) ? new Date() : d; }; export default function UtilsPage() { return null; }