LevelOS-Core/UI/Dashboards/Cadastros/ClienteCadastroPanel.cs

531 lines
22 KiB
C#

using BLL;
using CustomMessageBox;
using DAL;
using System.Drawing;
using System.Windows.Forms;
using MLL;
namespace UI
{
public class ClienteCadastroPanel : UserControl
{
private string _connectionString = DadosDaConexao.ObterConexao();
private readonly Color AccentBlue = Color.FromArgb(37, 99, 235);
private readonly Color TextDark = Color.FromArgb(30, 41, 59);
private readonly Color BorderColor = Color.FromArgb(226, 232, 240);
private Panel pnlToolbar = null!;
private Panel mainScroll = null!;
private Panel content = null!;
// Identificação
private RoundTextBox txtId = null!, txtEmpresaId = null!, txtNome = null!, txtNomeFantasia = null!;
private RoundTextBox txtTipoPessoa = null!, txtDocumento = null!, txtRG = null!;
private RoundTextBox txtInscricaoMunicipal = null!, txtDataNascimento = null!;
private RoundTextBox txtGrupo = null!, txtTipoConsumidor = null!;
// Contatos
private RoundTextBox txtContato = null!, txtTelefone1 = null!, txtTelefone2 = null!;
private RoundTextBox txtCelular = null!, txtWhatsapp = null!, txtEmail = null!, txtEmailNFe = null!, txtSite = null!;
// Endereço
private RoundTextBox txtCep = null!, txtEndereco = null!, txtNumero = null!, txtComplemento = null!;
private RoundTextBox txtBairro = null!, txtCidade = null!, txtUF = null!, txtPais = null!;
// Financeiro
private RoundTextBox txtLimiteCredito = null!, txtVendedorPadraoId = null!, txtObservacoesCobranca = null!;
private CheckBox chkBloqueado = null!, chkAtivo = null!;
// Carteiras
private RoundTextBox txtBitcoin = null!, txtEthereum = null!, txtLitecoin = null!;
// Extras
private RoundTextBox txtObservacoes = null!;
private RoundTextBox txtCampoExtra1 = null!, txtCampoExtra2 = null!, txtCampoExtra3 = null!;
// Info (readonly)
private RoundTextBox txtUltimaCompra = null!, txtCriadoEm = null!, txtAtualizadoEm = null!;
//Funções Auxiliares
private void CarregarConfiguracoesSistema()
{
BLLEmpresaConfig empresaConfig = new BLLEmpresaConfig(_connectionString);
int codEmpresa = empresaConfig.ObterEmpresaAtivaId();
this.txtEmpresaId.Text = codEmpresa.ToString();
}
private DateTime? ConverterData(string texto)
{
if (string.IsNullOrWhiteSpace(texto))
return null;
if (DateTime.TryParse(texto, out DateTime data))
return data;
return null;
}
private RoundTextBox[] TodosOsCampos() => new[]
{
txtId, txtEmpresaId, txtNome, txtNomeFantasia,
txtTipoPessoa, txtDocumento, txtRG,
txtInscricaoMunicipal, txtDataNascimento,
txtGrupo, txtTipoConsumidor,
txtContato, txtTelefone1, txtTelefone2,
txtCelular, txtWhatsapp, txtEmail, txtEmailNFe, txtSite,
txtCep, txtEndereco, txtNumero, txtComplemento,
txtBairro, txtCidade, txtUF, txtPais,
txtLimiteCredito, txtVendedorPadraoId, txtObservacoesCobranca,
txtBitcoin, txtEthereum, txtLitecoin,
txtObservacoes, txtCampoExtra1, txtCampoExtra2, txtCampoExtra3
};
private void SetCampos(bool enabled)
{
foreach (var campo in TodosOsCampos())
{
campo.Enabled = enabled;
campo.BackColor = enabled ? Color.White : Color.FromArgb(241, 245, 249);
}
chkBloqueado.Enabled = enabled;
chkAtivo.Enabled = enabled;
}
public ClienteCadastroPanel()
{
Dock = DockStyle.Fill;
BackColor = Color.White;
DoubleBuffered = true;
InitializeLayout();
SetCampos(false);
}
private void InitializeLayout()
{
this.Controls.Clear();
// ── TOOLBAR ───────────────────────────────────────────────────────
pnlToolbar = new Panel
{
Dock = DockStyle.Top,
Height = 55,
BackColor = Color.FromArgb(248, 250, 252),
BorderStyle = BorderStyle.None
};
var flowButtons = new FlowLayoutPanel
{
Dock = DockStyle.Fill,
Padding = new Padding(12, 10, 0, 0),
BackColor = Color.Transparent
};
var btnNovo = CreateToolbarButton("Novo", Color.FromArgb(34, 197, 94));
var btnAlterar = CreateToolbarButton("Alterar", Color.FromArgb(245, 158, 11));
var btnExcluir = CreateToolbarButton("Excluir", Color.FromArgb(239, 68, 68));
var btnLocalizar = CreateToolbarButton("Localizar", AccentBlue);
var btnSalvar = CreateToolbarButton("Salvar", AccentBlue);
var btnCancelar = CreateToolbarButton("Cancelar", Color.FromArgb(148, 163, 184));
btnNovo.Click += (s, e) => BtnNovo_Click();
btnAlterar.Click += (s, e) => BtnAlterar_Click();
btnExcluir.Click += (s, e) => BtnExcluir_Click();
btnLocalizar.Click += (s, e) => BtnLocalizar_Click();
btnSalvar.Click += (s, e) => BtnSalvar_Click();
btnCancelar.Click += (s, e) => BtnCancelar_Click();
flowButtons.Controls.AddRange(new Control[]
{ btnNovo, btnAlterar, btnExcluir, btnLocalizar, btnSalvar, btnCancelar });
pnlToolbar.Controls.Add(flowButtons);
this.Controls.Add(pnlToolbar);
// ── SCROLL + CONTENT ──────────────────────────────────────────────
mainScroll = new Panel
{
Dock = DockStyle.Fill,
AutoScroll = true,
BackColor = Color.White
};
this.Controls.Add(mainScroll);
mainScroll.BringToFront();
content = new Panel
{
Width = 1100,
Height = 900,
Location = new Point(0, 0),
BackColor = Color.White
};
mainScroll.Controls.Add(content);
const int rowH = 52;
const int secGap = 10;
const int secH = 28;
const int inputH = 28;
int y = 10;
// ── 1. IDENTIFICAÇÃO DO CLIENTE ───────────────────────────────────
content.Controls.Add(CreateSectionHeader("IDENTIFICAÇÃO DO CLIENTE", y));
y += secH + 4;
txtId = AddInput(content, "ID", 20, y, 60, inputH);
txtEmpresaId = AddInput(content, "Empresa ID", 90, y, 80, inputH);
txtNome = AddInput(content, "Nome / Razão Social", 180, y, 390, inputH);
txtNomeFantasia = AddInput(content, "Nome Fantasia", 580, y, 360, inputH);
y += rowH;
txtDocumento = AddInput(content, "CPF/CNPJ", 20, y, 170, inputH);
DocumentoHelper.Registrar(txtDocumento);
txtRG = AddInput(content, "RG / Insc. Estadual", 200, y, 170, inputH);
txtInscricaoMunicipal = AddInput(content, "Insc. Municipal", 380, y, 130, inputH);
txtDataNascimento = AddInput(content, "Dt. Nascimento", 520, y, 130, inputH);
txtTipoPessoa = AddInput(content, "Tipo Pessoa", 660, y, 110, inputH);
txtGrupo = AddInput(content, "Grupo", 780, y, 110, inputH);
txtTipoConsumidor = AddInput(content, "Tipo Consumidor", 900, y, 140, inputH);
y += rowH;
// ── 2. CONTATOS E COMUNICAÇÃO ─────────────────────────────────────
y += secGap;
content.Controls.Add(CreateSectionHeader("CONTATOS E COMUNICAÇÃO", y));
y += secH + 4;
txtContato = AddInput(content, "Contato", 20, y, 180, inputH);
txtEmail = AddInput(content, "E-mail", 210, y, 230, inputH);
txtEmailNFe = AddInput(content, "E-mail XML/NFe", 450, y, 230, inputH);
txtSite = AddInput(content, "Site", 690, y, 250, inputH);
y += rowH;
txtTelefone1 = AddInput(content, "Telefone 1", 20, y, 155, inputH);
txtTelefone2 = AddInput(content, "Telefone 2", 185, y, 155, inputH);
txtCelular = AddInput(content, "Celular", 350, y, 155, inputH);
txtWhatsapp = AddInput(content, "WhatsApp", 515, y, 155, inputH);
y += rowH;
// ── 3. ENDEREÇO COMPLETO ──────────────────────────────────────────
y += secGap;
content.Controls.Add(CreateSectionHeader("ENDEREÇO COMPLETO", y));
y += secH + 4;
txtCep = AddInput(content, "CEP", 20, y, 95, inputH);
txtCep.Leave += (s, e) =>
{
string cep = txtCep.Text.Trim().Replace("-", "");
if (cep.Length != 8) return;
if (TLL.VerifyCep.verificaCEP(cep))
{
txtEndereco.Text = TLL.VerifyCep.endereco;
txtBairro.Text = TLL.VerifyCep.bairro;
txtCidade.Text = TLL.VerifyCep.cidade;
txtUF.Text = TLL.VerifyCep.estado;
// Formata o CEP com hífen
txtCep.Text = $"{cep[..5]}-{cep[5..]}";
}
else
{
NT_MessageBox.Show("CEP não encontrado.", "CEP",
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
};//cep
txtEndereco = AddInput(content, "Logradouro", 125, y, 370, inputH);
txtNumero = AddInput(content, "Nº", 505, y, 60, inputH);
txtComplemento = AddInput(content, "Complemento", 575, y, 175, inputH);
txtBairro = AddInput(content, "Bairro", 760, y, 180, inputH);
y += rowH;
txtCidade = AddInput(content, "Cidade", 20, y, 280, inputH);
txtUF = AddInput(content, "UF", 310, y, 55, inputH);
txtPais = AddInput(content, "País", 375, y, 150, inputH);
y += rowH;
// ── 4. FINANCEIRO ─────────────────────────────────────────────────
y += secGap;
content.Controls.Add(CreateSectionHeader("FINANCEIRO", y));
y += secH + 4;
txtLimiteCredito = AddInput(content, "Limite de Crédito", 20, y, 150, inputH);
txtVendedorPadraoId = AddInput(content, "Vendedor Padrão ID", 180, y, 120, inputH);
txtObservacoesCobranca = AddInput(content, "Obs. de Cobrança", 310, y, 380, inputH);
chkBloqueado = CreateCheckBox("Bloqueado", 705, y + 18);
chkAtivo = CreateCheckBox("Ativo", 805, y + 18);
content.Controls.Add(chkBloqueado);
content.Controls.Add(chkAtivo);
y += rowH;
// ── 5. CARTEIRAS DIGITAIS ─────────────────────────────────────────
y += secGap;
content.Controls.Add(CreateSectionHeader("CARTEIRAS DIGITAIS", y));
y += secH + 4;
txtBitcoin = AddInput(content, "Bitcoin (BTC)", 20, y, 290, inputH);
txtEthereum = AddInput(content, "Ethereum (ETH)", 320, y, 290, inputH);
txtLitecoin = AddInput(content, "Litecoin (LTC)", 620, y, 290, inputH);
y += rowH;
// ── 6. CAMPOS EXTRAS ──────────────────────────────────────────────
y += secGap;
content.Controls.Add(CreateSectionHeader("CAMPOS EXTRAS", y));
y += secH + 4;
txtCampoExtra1 = AddInput(content, "Campo Extra 1", 20, y, 290, inputH);
txtCampoExtra2 = AddInput(content, "Campo Extra 2", 320, y, 290, inputH);
txtCampoExtra3 = AddInput(content, "Campo Extra 3", 620, y, 290, inputH);
y += rowH;
// ── 7. OBSERVAÇÕES ────────────────────────────────────────────────
y += secGap;
content.Controls.Add(CreateSectionHeader("OBSERVAÇÕES", y));
y += secH + 4;
txtObservacoes = AddInput(content, "Observações Internas", 20, y, 920, inputH);
y += rowH;
// ── 8. INFORMAÇÕES DO REGISTRO ────────────────────────────────────
y += secGap;
content.Controls.Add(CreateSectionHeader("INFORMAÇÕES DO REGISTRO", y));
y += secH + 4;
txtUltimaCompra = AddInput(content, "Última Compra", 20, y, 175, inputH, readOnly: true);
txtCriadoEm = AddInput(content, "Criado Em", 205, y, 175, inputH, readOnly: true);
txtAtualizadoEm = AddInput(content, "Atualizado Em", 390, y, 175, inputH, readOnly: true);
y += rowH;
content.Height = y + 10;
}
// ── EVENTOS ───────────────────────────────────────────────────────────
private void BtnNovo_Click()
{
foreach (var campo in TodosOsCampos())
campo.Text = string.Empty;
chkBloqueado.Checked = false;
chkAtivo.Checked = true;
SetCampos(true);
txtId.Enabled = false;
txtId.BackColor = Color.FromArgb(241, 245, 249);
this.CarregarConfiguracoesSistema();
txtEmpresaId.Enabled = false;
txtEmpresaId.BackColor = Color.FromArgb(241, 245, 249);
}
private void BtnAlterar_Click()
{
if (string.IsNullOrWhiteSpace(txtId.Text))
{
MessageBox.Show(
"Nenhum registro selecionado para alterar.",
"Atenção",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
return;
}
SetCampos(true);
txtId.Enabled = false;
txtId.BackColor = Color.FromArgb(241, 245, 249);
txtEmpresaId.Enabled = false;
txtEmpresaId.BackColor = Color.FromArgb(241, 245, 249);
}
private void BtnExcluir_Click()
{
// Solicita confirmação e exclui o registro atual
}
private void BtnLocalizar_Click()
{
// Abre tela/diálogo de busca e preenche os campos
}
private void BtnSalvar_Click()
{
var bll = new BLLClientes(_connectionString);
// 🔒 validação básica front
if (string.IsNullOrWhiteSpace(txtNome.Text) ||
string.IsNullOrWhiteSpace(txtDocumento.Text))
{
NT_MessageBox.Show("Preencha ao menos Nome e Documento.",
"Atenção", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
bool isNew = string.IsNullOrWhiteSpace(txtId.Text);
var cliente = new ModeloCliente
{
Id = isNew ? 0 : int.Parse(txtId.Text),
EmpresaId = int.TryParse(txtEmpresaId.Text, out var emp) ? emp : 0,
Nome = txtNome.Text,
NomeFantasia = txtNomeFantasia.Text,
TipoPessoa = txtTipoPessoa.Text,
Documento = txtDocumento.Text,
RG = txtRG.Text,
InscricaoMunicipal = txtInscricaoMunicipal.Text,
DataNascimento = ConverterData(txtDataNascimento.Text),
Contato = txtContato.Text,
Telefone1 = txtTelefone1.Text,
Telefone2 = txtTelefone2.Text,
Celular = txtCelular.Text,
Whatsapp = txtWhatsapp.Text,
Email = txtEmail.Text,
EmailNFe = txtEmailNFe.Text,
Site = txtSite.Text,
Grupo = txtGrupo.Text,
Cep = txtCep.Text,
Endereco = txtEndereco.Text,
Numero = int.TryParse(txtNumero.Text, out var num) ? num : null,
Complemento = txtComplemento.Text,
Bairro = txtBairro.Text,
Cidade = txtCidade.Text,
UF = txtUF.Text,
Pais = txtPais.Text,
LimiteCredito = decimal.TryParse(txtLimiteCredito.Text, out var lim) ? lim : 0,
Bloqueado = chkBloqueado.Checked,
ObservacoesCobranca = txtObservacoesCobranca.Text,
VendedorPadraoId = int.TryParse(txtVendedorPadraoId.Text, out var vend) ? vend : null,
TipoConsumidor = txtTipoConsumidor.Text,
Observacoes = txtObservacoes.Text,
CampoExtra1 = txtCampoExtra1.Text,
CampoExtra2 = txtCampoExtra2.Text,
CampoExtra3 = txtCampoExtra3.Text,
Bitcoin = txtBitcoin.Text,
Ethereum = txtEthereum.Text,
Litecoin = txtLitecoin.Text,
Ativo = chkAtivo.Checked,
UltimaCompra = ConverterData(txtUltimaCompra.Text),
// 🔥 esses o banco já gera, mas mantém compatível
CriadoEm = DateTime.Now,
AtualizadoEm = DateTime.Now
};
bool sucesso = false;
try
{
sucesso = isNew
? bll.Inserir(cliente)
: bll.Alterar(cliente);
}
catch (Exception ex)
{
NT_MessageBox.Show(ex.Message,
"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
if (!sucesso)
{
NT_MessageBox.Show("Erro ao salvar cliente.",
"Erro", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
SetCampos(false);
NT_MessageBox.Show("Cliente salvo com sucesso!",
"Sucesso", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void BtnCancelar_Click()
{
foreach (var campo in TodosOsCampos())
campo.Text = string.Empty;
chkBloqueado.Checked = false;
chkAtivo.Checked = false;
SetCampos(false);
}
// ── HELPERS ───────────────────────────────────────────────────────────
private Panel CreateSectionHeader(string title, int y)
{
var pnl = new Panel { Location = new Point(20, y), Width = 1000, Height = 26 };
var lbl = new Label
{
Text = title,
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
ForeColor = AccentBlue,
AutoSize = true,
Location = new Point(0, 0)
};
var line = new Panel
{
BackColor = BorderColor,
Height = 1,
Width = 980,
Location = new Point(0, 20)
};
pnl.Controls.Add(lbl);
pnl.Controls.Add(line);
return pnl;
}
private RoundTextBox AddInput(Control parent, string label,
int x, int y, int width, int height,
bool readOnly = false)
{
var lbl = new Label
{
Text = label,
Location = new Point(x, y),
Font = new Font("Segoe UI", 7.5f, FontStyle.Bold),
ForeColor = readOnly ? Color.Gray : TextDark,
AutoSize = true
};
var txt = new RoundTextBox
{
Location = new Point(x, y + 16),
Size = new Size(width, height),
Radius = 4,
BorderColor = readOnly ? Color.FromArgb(203, 213, 225) : BorderColor,
FocusColor = AccentBlue,
ReadOnly = readOnly,
BackColor = readOnly ? Color.FromArgb(241, 245, 249) : Color.White
};
parent.Controls.Add(lbl);
parent.Controls.Add(txt);
return txt;
}
private CheckBox CreateCheckBox(string text, int x, int y) => new CheckBox
{
Text = text,
Location = new Point(x, y),
Font = new Font("Segoe UI", 8.5f, FontStyle.Bold),
ForeColor = TextDark,
AutoSize = true
};
private RoundButton CreateToolbarButton(string text, Color color) => new RoundButton
{
Text = text,
Size = new Size(95, 32),
BackColor = color,
ForeColor = Color.White,
Font = new Font("Segoe UI Semibold", 8.5f),
Margin = new Padding(0, 0, 6, 0),
Cursor = Cursors.Hand
};
}
}