const COUNTRY = ["5", "5"]; const AREA = ["4", "7"]; const NINE = ["9"]; const FIRST = ["9", "2", "7", "4"]; const LAST = ["2", "3", "6", "5"]; export function getWhatsAppNumber() { return [...COUNTRY, ...AREA, ...NINE, ...FIRST, ...LAST].join(""); } export function getWhatsAppDisplayNumber() { return `+${COUNTRY.join("")} ${AREA.join("")} ${NINE.join("")}${FIRST.join("")}-${LAST.join("")}`; } export function buildWhatsAppUrl(message: string) { return `https://wa.me/${getWhatsAppNumber()}?text=${encodeURIComponent(message)}`; } /** * Nomes dos serviços e dos cases, montados no servidor (app/layout.tsx) a partir de lib/site-content.ts: * esse arquivo reúne o texto de todas as páginas e não deve ir inteiro para o navegador. */ export interface WhatsAppContexts { /** slug do serviço -> nome do serviço */ services: Record; /** id do case -> nome do projeto ou do cliente */ cases: Record; } /** Entra na frase "Quero conversar sobre {assunto}." da mensagem. */ export const AI_REVIEW_SUBJECT = "a revisão de um aplicativo feito com IA"; /** * Assuntos das páginas sem slug. Cabeçalho, botão flutuante e corpo da mesma página usam a mesma frase; * /cases e /servicos repetem a que os botões do corpo dessas páginas já usam. */ export const HOME_SUBJECT = "um site ou sistema para a minha empresa"; export const CASES_SUBJECT = "um projeto parecido com os cases do portfólio"; export const SERVICES_SUBJECT = "Sites, sistemas e aplicativos"; export const RESUME_SUBJECT = "um projeto, depois de ver o seu currículo"; /** Frase padrão para quem quer algo como um projeto publicado (case de cliente ou de laboratório). */ export function similarProjectSubject(title: string) { return `um projeto parecido com o ${title}`; } /** Assunto de cada página sem parâmetro, pelo caminho sem a barra final (só a home mantém a barra). */ const INDEX_SUBJECTS: Readonly> = { "/": HOME_SUBJECT, "/ia": AI_REVIEW_SUBJECT, "/cases": CASES_SUBJECT, "/servicos": SERVICES_SUBJECT, "/curriculo": RESUME_SUBJECT, }; /** Páginas com um parâmetro no caminho: em que tabela de nomes ele se procura e como o nome vira assunto. */ const DETAIL_ROUTES = [ { pattern: /^\/servicos\/([^/]+)$/, table: "services", subject: (name: string) => name, }, { pattern: /^\/cases\/([^/]+)$/, table: "cases", subject: similarProjectSubject, }, ] as const; /** * Nome pela chave; chave ausente, nome vazio ou só com espaços valem como ausente, para a mensagem cair no assunto * padrão em vez de "sobre .". */ function lookup( table: Record | undefined, key: string | undefined, ) { const name = table && key !== undefined && Object.hasOwn(table, key) ? table[key].trim() : ""; return name || undefined; } /** * Assunto da conversa de WhatsApp para a rota atual. Em /servicos/ cita o serviço, em /cases/ o case, * em /ia a revisão de aplicativo e nas páginas-índice (home, /cases, /servicos, /curriculo) o assunto da própria * página; nas demais rotas devolve undefined e a mensagem fala de "um projeto". */ export function whatsAppSubjectForPath( pathname: string | null | undefined, contexts?: WhatsAppContexts, ): string | undefined { const path = pathname?.replace(/(.)\/$/, "$1") ?? ""; if (Object.hasOwn(INDEX_SUBJECTS, path)) return INDEX_SUBJECTS[path]; for (const { pattern, table, subject } of DETAIL_ROUTES) { const name = lookup(contexts?.[table], pattern.exec(path)?.[1]); if (name) return subject(name); } return undefined; } /** Páginas de serviço e de case. */ export function isServiceOrCasePath(pathname: string | null | undefined) { return /^\/(servicos|cases)\/[^/]+\/?$/.test(pathname ?? ""); } /** * Páginas em que o botão do cabeçalho abre o WhatsApp com o assunto da página, em vez de ir ao formulário da home: * serviço e case, e também /ia, /cases, /servicos e /curriculo. Na home e nas demais rotas ele leva ao formulário. */ export function headerOpensWhatsApp(pathname: string | null | undefined) { return ( isServiceOrCasePath(pathname) || /^\/(ia|cases|servicos|curriculo)\/?$/.test(pathname ?? "") ); }