Feat licitacoes contratos #30

Merged
killer-cf merged 7 commits from feat-licitacoes-contratos into master 2025-11-19 12:31:19 +00:00
28 changed files with 1461 additions and 6008 deletions
Showing only changes of commit b844260399 - Show all commits

View File

@@ -5,7 +5,6 @@
import { Building2, Phone, Mail, Plus, Users, Pencil, X } from "lucide-svelte"; import { Building2, Phone, Mail, Plus, Users, Pencil, X } from "lucide-svelte";
import { resolve } from "$app/paths"; import { resolve } from "$app/paths";
import { maskCNPJ, maskCEP, maskPhone, maskUF, onlyDigits } from "$lib/utils/masks"; import { maskCNPJ, maskCEP, maskPhone, maskUF, onlyDigits } from "$lib/utils/masks";
import "$lib/svelte-compat";
const client = useConvexClient(); const client = useConvexClient();
const empresasQuery = useQuery(api.empresas.list, {}); const empresasQuery = useQuery(api.empresas.list, {});
@@ -76,13 +75,12 @@
let carregandoCnpj = $state(false); let carregandoCnpj = $state(false);
let erroCnpj = $state(""); let erroCnpj = $state("");
type ReceitaWsResponse = { type BrasilApiCnpjResponse = {
status?: string; razao_social?: string;
message?: string; nome_fantasia?: string;
nome?: string;
fantasia?: string;
telefone?: string;
email?: string; email?: string;
ddd_telefone_1?: string;
telefone?: string;
cep?: string; cep?: string;
logradouro?: string; logradouro?: string;
numero?: string; numero?: string;
@@ -90,6 +88,7 @@
bairro?: string; bairro?: string;
municipio?: string; municipio?: string;
uf?: string; uf?: string;
message?: string;
}; };
function handleEmpresaCnpjInput(event: Event) { function handleEmpresaCnpjInput(event: Event) {
@@ -105,21 +104,23 @@
carregandoCnpj = true; carregandoCnpj = true;
erroCnpj = ""; erroCnpj = "";
try { try {
const response = await fetch(`https://www.receitaws.com.br/v1/cnpj/${digits}`); const response = await fetch(`https://brasilapi.com.br/api/cnpj/v1/${digits}`);
const data: ReceitaWsResponse = await response.json(); const data: BrasilApiCnpjResponse = await response.json();
if (data.status === "ERROR") { if (!response.ok) {
throw new Error(data.message || "CNPJ não encontrado."); throw new Error(data.message || "CNPJ não encontrado.");
} }
if (data.nome && !empresaForm.razao_social) { if (data.razao_social && !empresaForm.razao_social) {
empresaForm.razao_social = data.nome; empresaForm.razao_social = data.razao_social;
} }
if (data.fantasia && !empresaForm.nome_fantasia) { if (data.nome_fantasia && !empresaForm.nome_fantasia) {
empresaForm.nome_fantasia = data.fantasia; empresaForm.nome_fantasia = data.nome_fantasia;
} }
if (data.telefone && !empresaForm.telefone) {
empresaForm.telefone = maskPhone(data.telefone); const telefoneFonte = data.ddd_telefone_1 ?? data.telefone;
if (telefoneFonte && !empresaForm.telefone) {
empresaForm.telefone = maskPhone(telefoneFonte);
} }
if (data.email && !empresaForm.email) { if (data.email && !empresaForm.email) {
empresaForm.email = data.email; empresaForm.email = data.email;
@@ -463,8 +464,8 @@
<table class="table table-zebra"> <table class="table table-zebra">
<thead> <thead>
<tr> <tr>
<th>Razão social / Nome fantasia</th>
<th>CNPJ</th> <th>CNPJ</th>
<th>Razão social / Nome fantasia</th>
<th>Telefone</th> <th>Telefone</th>
<th>E-mail</th> <th>E-mail</th>
<th>Ações</th> <th>Ações</th>
@@ -473,6 +474,7 @@
<tbody> <tbody>
{#each empresasQuery.data as empresa (empresa._id)} {#each empresasQuery.data as empresa (empresa._id)}
<tr> <tr>
<td>{empresa.cnpj}</td>
<td> <td>
<div class="flex flex-col"> <div class="flex flex-col">
<span class="font-semibold">{empresa.razao_social}</span> <span class="font-semibold">{empresa.razao_social}</span>
@@ -481,7 +483,6 @@
{/if} {/if}
</div> </div>
</td> </td>
<td>{empresa.cnpj}</td>
<td class="flex items-center gap-2"> <td class="flex items-center gap-2">
<Phone class="h-4 w-4 text-base-content/60" strokeWidth={2} /> <Phone class="h-4 w-4 text-base-content/60" strokeWidth={2} />
<span>{empresa.telefone}</span> <span>{empresa.telefone}</span>

View File

@@ -15,6 +15,7 @@ import type * as actions_smtp from "../actions/smtp.js";
import type * as actions_utils_nodeCrypto from "../actions/utils/nodeCrypto.js"; import type * as actions_utils_nodeCrypto from "../actions/utils/nodeCrypto.js";
import type * as atestadosLicencas from "../atestadosLicencas.js"; import type * as atestadosLicencas from "../atestadosLicencas.js";
import type * as ausencias from "../ausencias.js"; import type * as ausencias from "../ausencias.js";
import type * as autenticacao from "../autenticacao.js";
import type * as auth from "../auth.js"; import type * as auth from "../auth.js";
import type * as auth_utils from "../auth/utils.js"; import type * as auth_utils from "../auth/utils.js";
import type * as chamados from "../chamados.js"; import type * as chamados from "../chamados.js";
@@ -64,6 +65,7 @@ declare const fullApi: ApiFromModules<{
"actions/utils/nodeCrypto": typeof actions_utils_nodeCrypto; "actions/utils/nodeCrypto": typeof actions_utils_nodeCrypto;
atestadosLicencas: typeof atestadosLicencas; atestadosLicencas: typeof atestadosLicencas;
ausencias: typeof ausencias; ausencias: typeof ausencias;
autenticacao: typeof autenticacao;
auth: typeof auth; auth: typeof auth;
"auth/utils": typeof auth_utils; "auth/utils": typeof auth_utils;
chamados: typeof chamados; chamados: typeof chamados;