From 1f6541d7d436fed9cff63ce3e48dc67be69e7892 Mon Sep 17 00:00:00 2001 From: levelcode365 Date: Tue, 21 Apr 2026 21:15:37 -0300 Subject: [PATCH] 21/04/2026 - Criando novos formularios --- CPM/ComboBox/LV-COMBOBOXCUSTOM.resx | 120 +++++ .../Txt/SidebarControllBKP.txt | 424 +++++++++++++++ .../Cadastros/CalibracaoCadastroPanel.cs | 322 +++++++++++ .../CalibracaoPadraoCadastroPanel.cs | 322 +++++++++++ .../CalibracaoPadraoEnsaiosCadastroPanel.cs | 338 ++++++++++++ .../Calibracaoensaiocadastropanel.cs | 331 ++++++++++++ .../Cadastros/CartoesCadastroPanel.cs | 392 ++++++++++++++ .../Cadastros/ChamadoCadastroPanel.cs | 508 ++++++++++++++++++ .../Cadastros/UsuariosCadastroPanel.cs | 409 ++++++++++++++ .../Cadastros/UsuariosCadastroPanel.resx | 120 +++++ UI/Dashboards/Dashmain/MainForm.cs | 14 +- UI/Dashboards/Dashmain/SidebarControl.cs | 462 ++++++++++------ UI/UI.csproj | 4 + 13 files changed, 3608 insertions(+), 158 deletions(-) create mode 100644 CPM/ComboBox/LV-COMBOBOXCUSTOM.resx create mode 100644 UI/ArquivosAuxiliares/Txt/SidebarControllBKP.txt create mode 100644 UI/Dashboards/Cadastros/CalibracaoCadastroPanel.cs create mode 100644 UI/Dashboards/Cadastros/CalibracaoPadraoCadastroPanel.cs create mode 100644 UI/Dashboards/Cadastros/CalibracaoPadraoEnsaiosCadastroPanel.cs create mode 100644 UI/Dashboards/Cadastros/Calibracaoensaiocadastropanel.cs create mode 100644 UI/Dashboards/Cadastros/CartoesCadastroPanel.cs create mode 100644 UI/Dashboards/Cadastros/ChamadoCadastroPanel.cs create mode 100644 UI/Dashboards/Cadastros/UsuariosCadastroPanel.cs create mode 100644 UI/Dashboards/Cadastros/UsuariosCadastroPanel.resx diff --git a/CPM/ComboBox/LV-COMBOBOXCUSTOM.resx b/CPM/ComboBox/LV-COMBOBOXCUSTOM.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/CPM/ComboBox/LV-COMBOBOXCUSTOM.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/UI/ArquivosAuxiliares/Txt/SidebarControllBKP.txt b/UI/ArquivosAuxiliares/Txt/SidebarControllBKP.txt new file mode 100644 index 0000000..9bc837a --- /dev/null +++ b/UI/ArquivosAuxiliares/Txt/SidebarControllBKP.txt @@ -0,0 +1,424 @@ +using CustomMessageBox; +using DAL; +using DALL; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Windows.Forms; + +namespace UI +{ + public class SidebarControl : UserControl + { + //Recebendo a conexao + string _cx = DadosDaConexao.ObterConexao(); + + // ── Cores do Tema LevelOS ────────────────────────────────────────── + private static readonly Color NavyDark = Color.FromArgb(15, 30, 60); + private static readonly Color NavyMid = Color.FromArgb(26, 45, 80); + private static readonly Color AccentBlue = Color.FromArgb(37, 99, 235); + private static readonly Color TextLight = Color.FromArgb(255, 255, 255); + private static readonly Color TextMuted = Color.FromArgb(148, 163, 184); + private static readonly Color Divider = Color.FromArgb(40, 255, 255, 255); + + // ── Estado e Escalonamento (DPI) ─────────────────────────────────── + private float _scale = 1.0f; + private int _activeIndex = 0; + private int _hoverIndex = -1; + + // Propriedades Scaled (Ajustam-se ao monitor) + private int ScaledWidth => (int)(220 * _scale); + private int ScaledLogoH => (int)(55 * _scale); + private int ScaledSectionH => (int)(32 * _scale); + private int ScaledItemH => (int)(40 * _scale); + private int ScaledItemPadX => (int)(12 * _scale); + private int ScaledFooterH => (int)(50 * _scale); + private int ScaledIconSize => (int)(16 * _scale); + + // ── Submenus ─────────────────────────────────────────────────────── + private ContextMenuStrip _subMenuBanco, _subMenuConfiguracao, + _subMenuAjuda, _subMenuOrdemServico, _subMenuFinanceiro,_subMenuCadastro, _subMenuAgenda; + + public string UserName = "Levelcode", UserFunction = "Administrador"; + public event EventHandler? NavItemClicked; + + private readonly List _items = new() + { + new NavItem("Dashboard", SvgIcon.Grid, "Principal", null), + new NavItem("Cadastro", SvgIcon.UserPlus, null, "3"), + new NavItem("Ordens de Serviço", SvgIcon.FileText, null, "12"), + new NavItem("Agenda", SvgIcon.Calendar, null, null), + new NavItem("Produtos", SvgIcon.Package, "Gestão", null), + new NavItem("Estoque", SvgIcon.Inventory, null, null), + //new NavItem("Serviços", SvgIcon.Briefcase, null, null), + //new NavItem("Transportadoras", SvgIcon.Truck, null, null), + new NavItem("Financeiro", SvgIcon.DollarSign, null, null), + new NavItem("Banco de Dados", SvgIcon.Database, "Sistema", null), + new NavItem("Configurações", SvgIcon.Settings, null, null), + new NavItem("Suporte Técnico", SvgIcon.Support, "Ajuda", null), + }; + + public void backupFull(string conexao) + { + var backupService = new DALLBackupService(conexao); + var resultadoFull = backupService.ExecutarBackupFull(); + + if (resultadoFull.Sucesso) + NT_MessageBox.Show($"✅ Backup FULL concluído em {resultadoFull.Duracao.TotalSeconds:F1}s","Backup do banco de dados",MessageBoxButtons.OK, MessageBoxIcon.Information); + else + NT_MessageBox.Show($"❌ Erro no Backup FULL: {resultadoFull.Erro}","Erro ao tentar executar backup do sistema.",MessageBoxButtons.OK,MessageBoxIcon.Error); + }//Criar backup full + + public void backupDifrencial(string conexao) + { + var backupService = new DALLBackupService(conexao); + var resultadoDiff = backupService.ExecutarBackupDiferencial(); + + if (resultadoDiff.Sucesso) + NT_MessageBox.Show($"✅ Backup DIFERENCIAL concluído em {resultadoDiff.Duracao.TotalSeconds:F1}s","Backup diferencial concluido", MessageBoxButtons.OK, MessageBoxIcon.Information); + else + NT_MessageBox.Show($"❌ Erro no Backup DIFERENCIAL: {resultadoDiff.Erro}","Erro ao tentar executar backup diferencial no sistema", MessageBoxButtons.OK, MessageBoxIcon.Error); + }//Criar backup diferencial + + + + public SidebarControl() + { + BackColor = NavyDark; + DoubleBuffered = true; + this.SetStyle(ControlStyles.ResizeRedraw, true); + } + + protected override void OnHandleCreated(EventArgs e) + { + base.OnHandleCreated(e); + using (Graphics g = this.CreateGraphics()) { _scale = g.DpiX / 96f; } + this.Width = ScaledWidth; + SetupSubMenus(); + } + + private void SetupSubMenus() + { + //Submenu Cadastro + _subMenuCadastro = CreateStyledMenu(); + _subMenuCadastro.Items.Add("👤 Clientes", null, (s, e) => {NavItemClicked?.Invoke(this, 99);}); + _subMenuCadastro.Items.Add("💻 Equipamentos", null, (s, e) => { NavItemClicked?.Invoke(this, 100); }); + _subMenuCadastro.Items.Add("📜 Contratos", null, (s, e) => { NavItemClicked?.Invoke(this, 101); }); + _subMenuCadastro.Items.Add("🏭 Fornecedores", null, (s, e) => { NavItemClicked?.Invoke(this, 102); }); + _subMenuCadastro.Items.Add("👔 Funcionários", null, (s, e) => { NavItemClicked?.Invoke(this, 103); }); + _subMenuCadastro.Items.Add("🚚 Transportadoras", null, (s, e) => { NavItemClicked?.Invoke(this, 104); }); + _subMenuCadastro.Items.Add("🛠️ Serviços", null, (s, e) => { NavItemClicked?.Invoke(this, 105); }); + _subMenuCadastro.Items.Add("🏢 Empresa", null, (s, e) => { NavItemClicked?.Invoke(this, 106); }); + _subMenuCadastro.Items.Add("🔑 Usuários do Sistema", null, (s, e) => { NavItemClicked?.Invoke(this, 107); }); + + _subMenuBanco = CreateStyledMenu(); + _subMenuBanco.Items.Add("⚙️ Configuração Database", null, (s, e) => showForms
()); // Substitua pelo seu Form + _subMenuBanco.Items.Add("💾 Backup de Dados (FULL)", null, (s, e) => backupFull(this._cx)); + _subMenuBanco.Items.Add("⚡ Backup de Dados (DIFF)", null, (s, e) => backupDifrencial(this._cx)); + _subMenuBanco.Items.Add("🔄 Restaurar Banco"); + + + //submenu Configurações + _subMenuConfiguracao = CreateStyledMenu(); + _subMenuConfiguracao.Items.Add("🖼️ Personalização de OS"); + _subMenuConfiguracao.Items.Add("🖥️ Personalização de Sistema"); + _subMenuConfiguracao.Items.Add(" Configuração Empresa", null, (s, e) => { NavItemClicked?.Invoke(this, 202); }); + _subMenuConfiguracao.Items.Add(new ToolStripSeparator()); + _subMenuConfiguracao.Items.Add("📂 FTP-Cliente"); // Pasta para arquivos + _subMenuConfiguracao.Items.Add("💬 Telegram-Cliente"); // Balão de conversa + _subMenuConfiguracao.Items.Add("📩 SMTP-Cliente"); // Envelope de saída + _subMenuConfiguracao.Items.Add(new ToolStripSeparator()); + // Automação + _subMenuConfiguracao.Items.Add("⏰ Backups Automáticos"); // Relógio para agendamento + _subMenuConfiguracao.Items.Add("☁️ Backup em Nuvem"); + + _subMenuAjuda = CreateStyledMenu(); + _subMenuAjuda.Items.Add("💬 Atendimento Online"); + _subMenuAjuda.Items.Add("📖 Manual do Sistema"); + + _subMenuOrdemServico = CreateStyledMenu(); + + _subMenuOrdemServico.Items.Add("✚ Abrir nova O.S", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("✎ Alterar O.S", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("🔒 Encerrar O.S", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("🔍 Localizar O.S", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("📋 Orçamento de O.S", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("📜 Histórico de O.S", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("📊 Relatório de O.S", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("🖨 Imprimir", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("⚠️ Chamado Técnico", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("🌐 OS WEB", null, (s, e) => { /* Lógica */ }); + _subMenuOrdemServico.Items.Add("🔓 Reabrir OS", null, (s, e) => { /* Lógica */ }); + + _subMenuFinanceiro = CreateStyledMenu(); + + _subMenuFinanceiro.Items.Add("💳 Contas", null, (s, e) => { /* Lógica */ }); + _subMenuFinanceiro.Items.Add("📈 Contas a receber", null, (s, e) => { /* Lógica */ }); + _subMenuFinanceiro.Items.Add("📉 Contas a pagar", null, (s, e) => { /* Lógica */ }); + _subMenuFinanceiro.Items.Add("📉 Boletos/Duplicatas", null, (s, e) => { NavItemClicked?.Invoke(this, 500); }); + _subMenuFinanceiro.Items.Add(new ToolStripSeparator()); // Linha divisória + _subMenuFinanceiro.Items.Add("🛒 Compras", null, (s, e) => { /* Lógica */ }); + _subMenuFinanceiro.Items.Add("💰 Vendas", null, (s, e) => { /* Lógica */ }); + _subMenuFinanceiro.Items.Add("🧾 Notas Fiscais", null, (s, e) => { /* Lógica */ }); + _subMenuFinanceiro.Items.Add(new ToolStripSeparator()); // Linha divisória + _subMenuFinanceiro.Items.Add("📂 Arquivo Contador", null, (s, e) => { /* Lógica */ }); + _subMenuFinanceiro.Items.Add("🏦 Dados Bancários", null, (s, e) => { /* Lógica */ }); + _subMenuFinanceiro.Items.Add("🕒 Histórico Financeiro", null, (s, e) => { /* Lógica */ }); + + + // private ContextMenuStrip _subMenuAgenda; + _subMenuAgenda = CreateStyledMenu(); + //_subMenuAgenda.Items.Add("➕ Novo compromisso", null, (s, e) => {showForms();}); + _subMenuAgenda.Items.Add("➕ Novo compromisso", null, (s, e) => { NavItemClicked?.Invoke(this, 300); }); + _subMenuAgenda.Items.Add("🔍 Consultar compromissos", null, (s, e) => { NavItemClicked?.Invoke(this, 301); }); + _subMenuAgenda.Items.Add("✏️ Alterar compromisso", null, (s, e) => { /* Lógica de edição */ }); + _subMenuAgenda.Items.Add("🖨️ Imprimir", null, (s, e) => { /* Lógica de relatório */ }); + } + + private ContextMenuStrip CreateStyledMenu() + { + return new ContextMenuStrip + { + BackColor = NavyMid, + ForeColor = TextLight, + ShowImageMargin = false, + Font = new Font("Segoe UI", 10f * _scale), + Renderer = new ToolStripProfessionalRenderer(new SubMenuColorTable()) + }; + } + + private void showForms() where T : Form, new() + { + using (T form = new T()) + { + form.StartPosition = FormStartPosition.CenterScreen; + form.ShowDialog(); + } + } + //Abrir agenda + // AgendaForm.cs + public class AgendaForm : Form + { + public AgendaForm() + { + Text = "Agenda de Compromissos"; + Size = new Size(1150, 780); + StartPosition = FormStartPosition.CenterScreen; + BackColor = Color.White; + + var panel = new AgendaCadastroPanel(); + Controls.Add(panel); + } + }//abrir agenda de compromissos + + protected override void OnPaint(PaintEventArgs e) + { + var g = e.Graphics; + g.SmoothingMode = SmoothingMode.AntiAlias; + g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit; + + DrawLogo(g); + DrawNavItems(g, ScaledLogoH + (int)(8 * _scale)); + DrawFooter(g); + } + + private void DrawNavItems(Graphics g, int startY) + { + int y = startY; + using var fSection = new Font("Segoe UI", 8f * _scale, FontStyle.Bold); + using var fItem = new Font("Segoe UI", 10f * _scale); + using var fItemSel = new Font("Segoe UI Semibold", 10f * _scale); + + for (int i = 0; i < _items.Count; i++) + { + var item = _items[i]; + if (item.Section != null) + { + y += (int)(10 * _scale); + g.DrawString(item.Section.ToUpper(), fSection, new SolidBrush(Color.FromArgb(120, TextMuted)), ScaledItemPadX + (int)(8 * _scale), y); + y += ScaledSectionH; + } + + bool isActive = (i == _activeIndex); + bool isHover = (i == _hoverIndex && !isActive); + var itemRect = new Rectangle(ScaledItemPadX, y, Width - ScaledItemPadX * 2, ScaledItemH); + + if (isActive) FillRoundRect(g, new SolidBrush(AccentBlue), itemRect, (int)(6 * _scale)); + else if (isHover) FillRoundRect(g, new SolidBrush(Color.FromArgb(20, 255, 255, 255)), itemRect, (int)(6 * _scale)); + + var color = isActive ? TextLight : Color.FromArgb(200, TextLight); + DrawIcon(g, item.Icon, ScaledItemPadX + (int)(10 * _scale), y + (ScaledItemH - ScaledIconSize) / 2, ScaledIconSize, color); + g.DrawString(item.Label, isActive ? fItemSel : fItem, new SolidBrush(color), ScaledItemPadX + (int)(36 * _scale), y + (ScaledItemH - (int)(16 * _scale)) / 2); + + if (HasSubMenu(item.Label)) + g.DrawString("›", fItem, new SolidBrush(Color.FromArgb(100, TextLight)), Width - (int)(30 * _scale), y + (ScaledItemH - (int)(18 * _scale)) / 2); + + y += ScaledItemH + (int)(2 * _scale); + } + } + + // Adicione "Cadastro" na verificação + private bool HasSubMenu(string label) => + label == "Cadastro" || // <-- Adicionado aqui + label == "Banco de Dados" || + label == "Financeiro" || + label == "Ordens de Serviço" || + label == "Configurações" || + label == "Suporte Técnico" || + label == "Agenda" + ; + + protected override void OnMouseClick(MouseEventArgs e) + { + int hit = HitTest(e.Y); + if (hit >= 0) + { + _activeIndex = hit; Invalidate(); + string label = _items[hit].Label; + Point menuPos = new Point(Width + 2, e.Y - (int)(15 * _scale)); + + if (label == "Banco de Dados") _subMenuBanco.Show(this, menuPos); + else if (label == "Financeiro") _subMenuFinanceiro.Show(this, menuPos); + else if(label == "Agenda") _subMenuAgenda.Show(this, menuPos); + else if (label == "Ordens de Serviço") _subMenuOrdemServico.Show(this, menuPos); + else if (label == "Configurações") _subMenuConfiguracao.Show(this, menuPos); + else if (label == "Suporte Técnico") _subMenuAjuda.Show(this, menuPos); + else if (label == "Cadastro") _subMenuCadastro.Show(this, menuPos); + else NavItemClicked?.Invoke(this, hit); + } + } + + private int HitTest(int mouseY) + { + int y = ScaledLogoH + (int)(8 * _scale); + for (int i = 0; i < _items.Count; i++) + { + if (_items[i].Section != null) y += (int)(10 * _scale) + ScaledSectionH; + if (mouseY >= y && mouseY < y + ScaledItemH) return i; + y += ScaledItemH + (int)(2 * _scale); + } + return -1; + } + + protected override void OnMouseMove(MouseEventArgs e) { int hit = HitTest(e.Y); if (hit != _hoverIndex) { _hoverIndex = hit; Invalidate(); } } + protected override void OnMouseLeave(EventArgs e) { _hoverIndex = -1; Invalidate(); } + + private void DrawLogo(Graphics g) + { + var iconRect = new Rectangle((int)(16 * _scale), (int)(18 * _scale), (int)(34 * _scale), (int)(34 * _scale)); + FillRoundRect(g, new SolidBrush(AccentBlue), iconRect, (int)(8 * _scale)); + using var fIcon = new Font("Segoe UI", 14f * _scale, FontStyle.Bold); + DrawCenteredString(g, "S", fIcon, TextLight, iconRect); + g.DrawString("LevelOS", new Font("Segoe UI Semibold", 13f * _scale), new SolidBrush(TextLight), 58 * _scale, 20 * _scale); + g.DrawString("SISTEMA ERP", new Font("Segoe UI", 8f * _scale), new SolidBrush(TextMuted), 59 * _scale, 38 * _scale); + g.DrawLine(new Pen(Divider), 0, ScaledLogoH, Width, ScaledLogoH); + } + + private void DrawFooter(Graphics g) + { + int fy = Height - ScaledFooterH; + g.DrawLine(new Pen(Divider), 0, fy, Width, fy); + var avRect = new Rectangle((int)(16 * _scale), fy + (int)(14 * _scale), (int)(32 * _scale), (int)(32 * _scale)); + g.FillEllipse(new SolidBrush(AccentBlue), avRect); + DrawCenteredString(g, "AD", new Font("Segoe UI Semibold", 10f * _scale), TextLight, avRect); + g.DrawString(UserName, new Font("Segoe UI Semibold", 11f * _scale), new SolidBrush(TextLight), 56 * _scale, fy + (14 * _scale)); + g.DrawString(UserFunction, new Font("Segoe UI", 9f * _scale), new SolidBrush(TextMuted), 57 * _scale, fy + (30 * _scale)); + } + + // ── MOTOR DE ÍCONES COMPLETO (GDI+) ──────────────────────────────── + private void DrawIcon(Graphics g, SvgIcon icon, int x, int y, int size, Color color) + { + using var p = new Pen(color, 1.6f * _scale) { StartCap = LineCap.Round, EndCap = LineCap.Round, LineJoin = LineJoin.Round }; + float s = size / 24f; + g.TranslateTransform(x, y); g.ScaleTransform(s, s); + + switch (icon) + { + case SvgIcon.Grid: + g.DrawRectangle(p, 3, 3, 7, 7); g.DrawRectangle(p, 14, 3, 7, 7); g.DrawRectangle(p, 3, 14, 7, 7); g.DrawRectangle(p, 14, 14, 7, 7); break; + case SvgIcon.Users: + g.DrawEllipse(p, 5, 3, 8, 8); g.DrawArc(p, 2, 13, 14, 8, 180, 180); g.DrawArc(p, 15, 8, 6, 6, 270, 180); break; + case SvgIcon.FileText: + g.DrawLines(p, new PointF[] { new(6, 2), new(6, 22), new(18, 22), new(18, 8), new(14, 2), new(6, 2) }); g.DrawLine(p, 14, 2, 14, 8); g.DrawLine(p, 14, 8, 18, 8); break; + case SvgIcon.Package: + g.DrawLines(p, new PointF[] { new(12, 2), new(2, 7), new(12, 12), new(22, 7), new(12, 2) }); g.DrawLine(p, 2, 7, 2, 17); g.DrawLine(p, 22, 7, 22, 17); g.DrawLine(p, 12, 12, 12, 22); break; + case SvgIcon.DollarSign: + g.DrawLine(p, 12, 2, 12, 22); g.DrawArc(p, 7, 5, 10, 7, 110, 250); g.DrawArc(p, 7, 12, 10, 7, 270, 250); break; + case SvgIcon.Database: + g.DrawEllipse(p, 4, 3, 16, 6); g.DrawLine(p, 4, 6, 4, 18); g.DrawLine(p, 20, 6, 20, 18); g.DrawArc(p, 4, 15, 16, 6, 0, 180); break; + case SvgIcon.Calendar: + g.DrawRectangle(p, 3, 4, 18, 17); g.DrawLine(p, 3, 9, 21, 9); g.DrawLine(p, 8, 2, 8, 6); g.DrawLine(p, 16, 2, 16, 6); break; + case SvgIcon.Truck: + g.DrawRectangle(p, 1, 5, 13, 11); g.DrawLines(p, new PointF[] { new(14, 16), new(14, 8), new(19, 8), new(23, 12), new(23, 16) }); + g.DrawEllipse(p, 3, 15, 4, 4); g.DrawEllipse(p, 17, 15, 4, 4); break; + case SvgIcon.Factory: + g.DrawRectangle(p, 2, 10, 20, 11); g.DrawLines(p, new PointF[] { new(2, 10), new(2, 5), new(8, 10), new(8, 5), new(14, 10) }); break; + case SvgIcon.Briefcase: + g.DrawRectangle(p, 3, 7, 18, 13); g.DrawArc(p, 9, 3, 6, 8, 180, 180); break; + case SvgIcon.Support: + g.DrawArc(p, 4, 4, 16, 16, 180, 180); g.DrawRectangle(p, 3, 13, 3, 5); g.DrawRectangle(p, 18, 13, 3, 5); break; + case SvgIcon.Inventory: + g.DrawRectangle(p, 3, 3, 18, 8); g.DrawRectangle(p, 3, 13, 18, 8); break; + case SvgIcon.Settings: + g.DrawEllipse(p, 9, 9, 6, 6); + for (int a = 0; a < 360; a += 45) + { + float r = a * (float)Math.PI / 180f; + g.DrawLine(p, 12 + (float)Math.Cos(r) * 8, 12 + (float)Math.Sin(r) * 8, 12 + (float)Math.Cos(r) * 11, 12 + (float)Math.Sin(r) * 11); + } + break; + case SvgIcon.User: g.DrawEllipse(p, 8, 2, 8, 8); g.DrawArc(p, 3, 14, 18, 8, 180, 180); break; + case SvgIcon.UserCheck: g.DrawEllipse(p, 8, 3, 8, 8); g.DrawArc(p, 3, 14, 18, 8, 180, 180); g.DrawRectangle(p, 10, 15, 4, 3); break; + case SvgIcon.UserPlus: + // Desenha o corpo do usuário (círculo e arco) + g.DrawEllipse(p, 4, 4, 8, 8); // Cabeça + g.DrawArc(p, 1, 14, 14, 8, 180, 180); // Ombros + + // Desenha o sinal de "+" ao lado + // Vertical + g.DrawLine(p, 19, 7, 19, 15); + // Horizontal + g.DrawLine(p, 15, 11, 23, 11); + break; + + + } + g.ResetTransform(); + } + + // ── Helpers ── + private static void FillRoundRect(Graphics g, Brush b, Rectangle r, int rad) { using var path = RoundRectPath(r, rad); g.FillPath(b, path); } + private static GraphicsPath RoundRectPath(Rectangle r, int rad) + { + var path = new GraphicsPath(); int d = Math.Max(rad * 2, 1); + path.AddArc(r.X, r.Y, d, d, 180, 90); path.AddArc(r.Right - d, r.Y, d, d, 270, 90); + path.AddArc(r.Right - d, r.Bottom - d, d, d, 0, 90); path.AddArc(r.X, r.Bottom - d, d, d, 90, 90); + path.CloseFigure(); return path; + } + private static void DrawCenteredString(Graphics g, string t, Font f, Color c, Rectangle r) + { + var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; + g.DrawString(t, f, new SolidBrush(c), r, sf); + } + + private class NavItem + { + public string Label { get; } + public SvgIcon Icon { get; } + public string? Section { get; } + public string? Badge { get; } + public NavItem(string l, SvgIcon i, string? s, string? b) { Label = l; Icon = i; Section = s; Badge = b; } + } + private class SubMenuColorTable : ProfessionalColorTable + { + public override Color ToolStripDropDownBackground => NavyMid; + public override Color MenuItemSelected => AccentBlue; + public override Color MenuItemBorder => Color.Transparent; + public override Color MenuItemSelectedGradientBegin => AccentBlue; + public override Color MenuItemSelectedGradientEnd => AccentBlue; + } + } + + public enum SvgIcon { Grid, Users, FileText, Package, DollarSign, User, Settings, Database, Truck, Factory, UserCheck, Briefcase, Support, Inventory, Wallet, ShoppingCart, ShoppingBag, Calendar , UserPlus} +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/CalibracaoCadastroPanel.cs b/UI/Dashboards/Cadastros/CalibracaoCadastroPanel.cs new file mode 100644 index 0000000..e790c73 --- /dev/null +++ b/UI/Dashboards/Cadastros/CalibracaoCadastroPanel.cs @@ -0,0 +1,322 @@ +using CPM; +using DAL; +using MLL; +using BLL; +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UI +{ + public class CalibracaoCadastroPanel : FormularioModelo + { + // ── CAMPOS DO FORMULÁRIO ────────────────────────────────────────────── + private LV_TEXTBOX1 txtIdCalibracao = null!; + private LV_TEXTBOX1 txtCodigo = null!; + private LV_TEXTBOX1 txtOsNumero = null!; + private LV_TEXTBOX1 txtData = null!; + private LV_TEXTBOX1 txtTemp = null!; + private LV_TEXTBOX1 txtHumidade = null!; + private LV_TEXTBOX1 txtResponsavel = null!; + private LV_TEXTBOX1 txtObserv = null!; + + // ── ESTADO DO FORMULÁRIO ────────────────────────────────────────────── + private enum ModoFormulario { Visualizacao, Novo, Edicao } + private ModoFormulario _modo = ModoFormulario.Visualizacao; + private int _idAtual = 0; + + // ── BLL ─────────────────────────────────────────────────────────────── + // private CalibracaoBLL _bll = null!; + + // ── CONSTRUTOR ──────────────────────────────────────────────────────── + public CalibracaoCadastroPanel() + { + Titulo = "Cadastro de Calibração"; + BuildForm(); + AplicarModo(ModoFormulario.Visualizacao); + } + + // ── CONSTRUÇÃO DOS CAMPOS ───────────────────────────────────────────── + private void BuildForm() + { + // ── SEÇÃO: IDENTIFICAÇÃO ────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Identificação", 20)); + + txtIdCalibracao = AddInput(content, "ID", 20, 58, 80, 32, readOnly: true); + + txtCodigo = AddInput(content, "Código", 120, 58, 200, 32); + txtCodigo.MaxLength = 50; + + txtOsNumero = AddInput(content, "Nº da OS", 340, 58, 200, 32); + txtOsNumero.MaxLength = 50; + + // ── SEÇÃO: CONDIÇÕES ────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Condições do ambiente", 120)); + + txtData = AddInput(content, "Data", 20, 158, 160, 32); + txtData.MaxLength = 20; + + txtTemp = AddInput(content, "Temperatura", 200, 158, 160, 32); + txtTemp.MaxLength = 20; + + txtHumidade = AddInput(content, "Humidade", 380, 158, 160, 32); + txtHumidade.MaxLength = 20; + + // ── SEÇÃO: RESPONSÁVEL ──────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Responsável", 220)); + + txtResponsavel = AddInput(content, "Responsável", 20, 258, 320, 32); + txtResponsavel.MaxLength = 100; + + // ── SEÇÃO: OBSERVAÇÕES ──────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Observações", 320)); + + // Observações — campo maior, multiline via LV_TEXTBOX1 + var lblObserv = new Label + { + Text = "Observações", + Location = new Point(20, 358), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + + txtObserv = new LV_TEXTBOX1 + { + Location = new Point(20, 374), + Size = new Size(720, 80), + BorderColor = BorderColor, + BorderFocusColor = AccentBlue, + Multiline = true, + MaxLength = 255 + }; + + content.Controls.Add(lblObserv); + content.Controls.Add(txtObserv); + + content.Height = 490; + } + + // ── MODOS DO FORMULÁRIO ─────────────────────────────────────────────── + private void AplicarModo(ModoFormulario modo) + { + _modo = modo; + + bool editando = modo == ModoFormulario.Novo || modo == ModoFormulario.Edicao; + + // Campos editáveis conforme o modo + txtCodigo.ReadOnly = !editando; + txtOsNumero.ReadOnly = !editando; + txtData.ReadOnly = !editando; + txtTemp.ReadOnly = !editando; + txtHumidade.ReadOnly = !editando; + txtResponsavel.ReadOnly = !editando; + txtObserv.ReadOnly = !editando; + + // Cor de fundo conforme estado + Color bgAtivo = Color.White; + Color bgInativo = ReadOnlyBg; + + txtCodigo.BackColor = editando ? bgAtivo : bgInativo; + txtOsNumero.BackColor = editando ? bgAtivo : bgInativo; + txtData.BackColor = editando ? bgAtivo : bgInativo; + txtTemp.BackColor = editando ? bgAtivo : bgInativo; + txtHumidade.BackColor = editando ? bgAtivo : bgInativo; + txtResponsavel.BackColor = editando ? bgAtivo : bgInativo; + txtObserv.BackColor = editando ? bgAtivo : bgInativo; + + // Bordas conforme estado + txtCodigo.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtOsNumero.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtData.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtTemp.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtHumidade.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtResponsavel.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtObserv.BorderColor = editando ? BorderColor : ReadOnlyBorder; + + // Botões + btnNovo.Enabled = !editando; + btnAlterar.Enabled = !editando && _idAtual > 0; + btnExcluir.Enabled = !editando && _idAtual > 0; + btnLocalizar.Enabled = !editando; + btnSalvar.Enabled = editando; + btnCancelar.Enabled = editando; + + if (modo == ModoFormulario.Novo) LimparCampos(); + } + + // ── POPULAR / LIMPAR CAMPOS ─────────────────────────────────────────── + private void PopularCampos(ModeloCalibracao m) + { + _idAtual = m.ID_CALIBRACAO; + + txtIdCalibracao.Text = m.ID_CALIBRACAO.ToString(); + txtCodigo.Text = m.CODIGO; + txtOsNumero.Text = m.OS_NUMERO; + txtData.Text = m.DATA; + txtTemp.Text = m.TEMP; + txtHumidade.Text = m.HUMIDADE; + txtResponsavel.Text = m.RESPONSABEL; + txtObserv.Text = m.OBSERV; + } + + private void LimparCampos() + { + _idAtual = 0; + + txtIdCalibracao.Text = string.Empty; + txtCodigo.Text = string.Empty; + txtOsNumero.Text = string.Empty; + txtData.Text = string.Empty; + txtTemp.Text = string.Empty; + txtHumidade.Text = string.Empty; + txtResponsavel.Text = string.Empty; + txtObserv.Text = string.Empty; + } + + // ── VALIDAÇÃO ───────────────────────────────────────────────────────── + private bool Validar() + { + if (string.IsNullOrWhiteSpace(txtCodigo.Text)) + { + MessageBox.Show("Informe o código da calibração.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtCodigo.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtOsNumero.Text)) + { + MessageBox.Show("Informe o número da OS.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtOsNumero.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtData.Text)) + { + MessageBox.Show("Informe a data da calibração.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtData.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtResponsavel.Text)) + { + MessageBox.Show("Informe o responsável pela calibração.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtResponsavel.Focus(); + return false; + } + + return true; + } + + // ── MONTAR MODELO A PARTIR DOS CAMPOS ───────────────────────────────── + private ModeloCalibracao MontarModelo() => new ModeloCalibracao( + _idAtual, + txtCodigo.Text.Trim(), + txtOsNumero.Text.Trim(), + txtData.Text.Trim(), + txtTemp.Text.Trim(), + txtHumidade.Text.Trim(), + txtResponsavel.Text.Trim(), + txtObserv.Text.Trim() + ); + + // ── EVENTOS ABSTRATOS ───────────────────────────────────────────────── + protected override void OnNovo() + { + AplicarModo(ModoFormulario.Novo); + txtCodigo.Focus(); + } + + protected override void OnAlterar() + { + if (_idAtual == 0) return; + AplicarModo(ModoFormulario.Edicao); + txtCodigo.Focus(); + } + + protected override void OnExcluir() + { + if (_idAtual == 0) return; + + var confirm = MessageBox.Show( + $"Deseja realmente excluir a calibração \"{txtCodigo.Text}\"?", + "Confirmar exclusão", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); + + if (confirm != DialogResult.Yes) return; + + try + { + // TODO: _bll.Excluir(_idAtual); + MessageBox.Show("Calibração excluída com sucesso.", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao excluir:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnLocalizar() + { + // TODO: abrir formulário de busca e retornar a calibração selecionada + // var frm = new FormularioBuscarCalibracao(); + // if (frm.ShowDialog() == DialogResult.OK) + // { + // PopularCampos(frm.CalibracaoSelecionada); + // AplicarModo(ModoFormulario.Visualizacao); + // } + + MessageBox.Show("Implemente o formulário de busca de calibrações.", + "Localizar", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + protected override void OnSalvar() + { + if (!Validar()) return; + + var modelo = MontarModelo(); + + try + { + if (_modo == ModoFormulario.Novo) + { + // TODO: _bll.Criar(modelo); + MessageBox.Show("Calibração cadastrada com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + // TODO: _bll.Atualizar(modelo); + MessageBox.Show("Calibração atualizada com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao salvar:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnCancelar() + { + if (_idAtual > 0) + { + // TODO: recarregar do banco se necessário + } + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/CalibracaoPadraoCadastroPanel.cs b/UI/Dashboards/Cadastros/CalibracaoPadraoCadastroPanel.cs new file mode 100644 index 0000000..07f1fa9 --- /dev/null +++ b/UI/Dashboards/Cadastros/CalibracaoPadraoCadastroPanel.cs @@ -0,0 +1,322 @@ +using CPM; +using DAL; +using MLL; +using BLL; +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UI +{ + public class CalibracaoPadraoCadastroPanel : FormularioModelo + { + // ── CAMPOS DO FORMULÁRIO ────────────────────────────────────────────── + private LV_TEXTBOX1 txtIdCalibracao = null!; + private LV_TEXTBOX1 txtCodigo = null!; + private LV_TEXTBOX1 txtOsNumero = null!; + private LV_TEXTBOX1 txtData = null!; + private LV_TEXTBOX1 txtTemp = null!; + private LV_TEXTBOX1 txtHumidade = null!; + private LV_TEXTBOX1 txtResponsavel = null!; + private LV_TEXTBOX1 txtObserv = null!; + + // ── ESTADO DO FORMULÁRIO ────────────────────────────────────────────── + private enum ModoFormulario { Visualizacao, Novo, Edicao } + private ModoFormulario _modo = ModoFormulario.Visualizacao; + private int _idAtual = 0; + + // ── BLL ─────────────────────────────────────────────────────────────── + // private CalibracaoPadrãoBLL _bll = null!; + + // ── CONSTRUTOR ──────────────────────────────────────────────────────── + public CalibracaoPadraoCadastroPanel() + { + Titulo = "Cadastro de Calibração Padrão"; + BuildForm(); + AplicarModo(ModoFormulario.Visualizacao); + } + + // ── CONSTRUÇÃO DOS CAMPOS ───────────────────────────────────────────── + private void BuildForm() + { + // ── SEÇÃO: IDENTIFICAÇÃO ────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Identificação", 20)); + + txtIdCalibracao = AddInput(content, "ID", 20, 58, 80, 32, readOnly: true); + + txtCodigo = AddInput(content, "Código", 120, 58, 200, 32); + txtCodigo.MaxLength = 50; + + txtOsNumero = AddInput(content, "Nº da OS", 340, 58, 200, 32); + txtOsNumero.MaxLength = 50; + + // ── SEÇÃO: CONDIÇÕES ────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Condições do ambiente", 120)); + + txtData = AddInput(content, "Data", 20, 158, 160, 32); + txtData.MaxLength = 20; + + txtTemp = AddInput(content, "Temperatura", 200, 158, 160, 32); + txtTemp.MaxLength = 20; + + txtHumidade = AddInput(content, "Humidade", 380, 158, 160, 32); + txtHumidade.MaxLength = 20; + + // ── SEÇÃO: RESPONSÁVEL ──────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Responsável", 220)); + + txtResponsavel = AddInput(content, "Responsável", 20, 258, 320, 32); + txtResponsavel.MaxLength = 100; + + // ── SEÇÃO: OBSERVAÇÕES ──────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Observações", 320)); + + // Observações — campo maior, multiline via LV_TEXTBOX1 + var lblObserv = new Label + { + Text = "Observações", + Location = new Point(20, 358), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + + txtObserv = new LV_TEXTBOX1 + { + Location = new Point(20, 374), + Size = new Size(720, 80), + BorderColor = BorderColor, + BorderFocusColor = AccentBlue, + Multiline = true, + MaxLength = 255 + }; + + content.Controls.Add(lblObserv); + content.Controls.Add(txtObserv); + + content.Height = 490; + } + + // ── MODOS DO FORMULÁRIO ─────────────────────────────────────────────── + private void AplicarModo(ModoFormulario modo) + { + _modo = modo; + + bool editando = modo == ModoFormulario.Novo || modo == ModoFormulario.Edicao; + + // Campos editáveis conforme o modo + txtCodigo.ReadOnly = !editando; + txtOsNumero.ReadOnly = !editando; + txtData.ReadOnly = !editando; + txtTemp.ReadOnly = !editando; + txtHumidade.ReadOnly = !editando; + txtResponsavel.ReadOnly = !editando; + txtObserv.ReadOnly = !editando; + + // Cor de fundo conforme estado + Color bgAtivo = Color.White; + Color bgInativo = ReadOnlyBg; + + txtCodigo.BackColor = editando ? bgAtivo : bgInativo; + txtOsNumero.BackColor = editando ? bgAtivo : bgInativo; + txtData.BackColor = editando ? bgAtivo : bgInativo; + txtTemp.BackColor = editando ? bgAtivo : bgInativo; + txtHumidade.BackColor = editando ? bgAtivo : bgInativo; + txtResponsavel.BackColor = editando ? bgAtivo : bgInativo; + txtObserv.BackColor = editando ? bgAtivo : bgInativo; + + // Bordas conforme estado + txtCodigo.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtOsNumero.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtData.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtTemp.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtHumidade.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtResponsavel.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtObserv.BorderColor = editando ? BorderColor : ReadOnlyBorder; + + // Botões + btnNovo.Enabled = !editando; + btnAlterar.Enabled = !editando && _idAtual > 0; + btnExcluir.Enabled = !editando && _idAtual > 0; + btnLocalizar.Enabled = !editando; + btnSalvar.Enabled = editando; + btnCancelar.Enabled = editando; + + if (modo == ModoFormulario.Novo) LimparCampos(); + } + + // ── POPULAR / LIMPAR CAMPOS ─────────────────────────────────────────── + private void PopularCampos(ModeloCalibracaoPadrao m) + { + _idAtual = m.ID_CALIBRACAO_PADRAO; + + txtIdCalibracao.Text = m.ID_CALIBRACAO_PADRAO.ToString(); + txtCodigo.Text = m.CODIGO; + txtOsNumero.Text = m.OS_NUMERO; + txtData.Text = m.DATA; + txtTemp.Text = m.TEMP; + txtHumidade.Text = m.HUMIDADE; + txtResponsavel.Text = m.RESPONSABEL; + txtObserv.Text = m.OBSERV; + } + + private void LimparCampos() + { + _idAtual = 0; + + txtIdCalibracao.Text = string.Empty; + txtCodigo.Text = string.Empty; + txtOsNumero.Text = string.Empty; + txtData.Text = string.Empty; + txtTemp.Text = string.Empty; + txtHumidade.Text = string.Empty; + txtResponsavel.Text = string.Empty; + txtObserv.Text = string.Empty; + } + + // ── VALIDAÇÃO ───────────────────────────────────────────────────────── + private bool Validar() + { + if (string.IsNullOrWhiteSpace(txtCodigo.Text)) + { + MessageBox.Show("Informe o código da calibração.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtCodigo.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtOsNumero.Text)) + { + MessageBox.Show("Informe o número da OS.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtOsNumero.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtData.Text)) + { + MessageBox.Show("Informe a data da calibração.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtData.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtResponsavel.Text)) + { + MessageBox.Show("Informe o responsável pela calibração.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtResponsavel.Focus(); + return false; + } + + return true; + } + + // ── MONTAR MODELO A PARTIR DOS CAMPOS ───────────────────────────────── + private ModeloCalibracaoPadrao MontarModelo() => new ModeloCalibracaoPadrao( + _idAtual, + txtCodigo.Text.Trim(), + txtOsNumero.Text.Trim(), + txtData.Text.Trim(), + txtTemp.Text.Trim(), + txtHumidade.Text.Trim(), + txtResponsavel.Text.Trim(), + txtObserv.Text.Trim() + ); + + // ── EVENTOS ABSTRATOS ───────────────────────────────────────────────── + protected override void OnNovo() + { + AplicarModo(ModoFormulario.Novo); + txtCodigo.Focus(); + } + + protected override void OnAlterar() + { + if (_idAtual == 0) return; + AplicarModo(ModoFormulario.Edicao); + txtCodigo.Focus(); + } + + protected override void OnExcluir() + { + if (_idAtual == 0) return; + + var confirm = MessageBox.Show( + $"Deseja realmente excluir a calibração \"{txtCodigo.Text}\"?", + "Confirmar exclusão", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); + + if (confirm != DialogResult.Yes) return; + + try + { + // TODO: _bll.Excluir(_idAtual); + MessageBox.Show("Calibração padrão excluída com sucesso.", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao excluir:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnLocalizar() + { + // TODO: abrir formulário de busca e retornar a calibração selecionada + // var frm = new FormularioBuscarCalibracaoPadrao(); + // if (frm.ShowDialog() == DialogResult.OK) + // { + // PopularCampos(frm.CalibracaoSelecionada); + // AplicarModo(ModoFormulario.Visualizacao); + // } + + MessageBox.Show("Implemente o formulário de busca de calibrações padrão.", + "Localizar", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + protected override void OnSalvar() + { + if (!Validar()) return; + + var modelo = MontarModelo(); + + try + { + if (_modo == ModoFormulario.Novo) + { + // TODO: _bll.Criar(modelo); + MessageBox.Show("Calibração padrão cadastrada com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + // TODO: _bll.Atualizar(modelo); + MessageBox.Show("Calibração padrão atualizada com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao salvar:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnCancelar() + { + if (_idAtual > 0) + { + // TODO: recarregar do banco se necessário + } + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/CalibracaoPadraoEnsaiosCadastroPanel.cs b/UI/Dashboards/Cadastros/CalibracaoPadraoEnsaiosCadastroPanel.cs new file mode 100644 index 0000000..44b7416 --- /dev/null +++ b/UI/Dashboards/Cadastros/CalibracaoPadraoEnsaiosCadastroPanel.cs @@ -0,0 +1,338 @@ +using CPM; +using DAL; +using MLL; +using BLL; +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UI +{ + public class CalibracaoPadraoEnsaiosCadastroPanel : FormularioModelo + { + // ── CAMPOS DO FORMULÁRIO ────────────────────────────────────────────── + private LV_TEXTBOX1 txtId = null!; + private LV_TEXTBOX1 txtCodigo = null!; + private LV_TEXTBOX1 txtCodCalibracao = null!; + private Button btnBuscarCod = null!; + private LV_TEXTBOX1 txtDescricao = null!; + private LV_TEXTBOX1 txtMinimo = null!; + private LV_TEXTBOX1 txtMaximo = null!; + private LV_TEXTBOX1 txtObtido = null!; + private LV_TEXTBOX1 txtUnidade = null!; + + // ── ESTADO ──────────────────────────────────────────────────────────── + private enum ModoFormulario { Visualizacao, Novo, Edicao } + private ModoFormulario _modo = ModoFormulario.Visualizacao; + private int _idAtual = 0; + + // ── BLL ─────────────────────────────────────────────────────────────── + // private CalibracaoPadraoEnsaiosBLL _bll = null!; + + // ── CONSTRUTOR ──────────────────────────────────────────────────────── + public CalibracaoPadraoEnsaiosCadastroPanel() + { + Titulo = "Cadastro de Ensaios de Calibração Padrão"; + BuildForm(); + AplicarModo(ModoFormulario.Visualizacao); + } + + // ── CONSTRUÇÃO DOS CAMPOS ───────────────────────────────────────────── + private void BuildForm() + { + // ── SEÇÃO: IDENTIFICAÇÃO ────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Identificação", 20)); + + txtId = AddInput(content, "ID", 20, 58, 80, 32, readOnly: true); + + txtCodigo = AddInput(content, "Código", 120, 58, 160, 32); + txtCodigo.MaxLength = 50; + + // Código da Calibração + botão buscar + var lblCod = new Label + { + Text = "Código da Calibração", + Location = new Point(300, 58), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + + txtCodCalibracao = new LV_TEXTBOX1 + { + Location = new Point(300, 74), + Size = new Size(220, 32), + BorderColor = BorderColor, + BorderFocusColor = AccentBlue, + ReadOnly = true, // sempre preenchido via busca + BackColor = ReadOnlyBg + }; + + btnBuscarCod = new Button + { + Text = "🔍 Buscar", + Location = new Point(528, 74), + Size = new Size(90, 32), + BackColor = AccentBlue, + ForeColor = Color.White, + Font = new Font("Segoe UI Semibold", 8.5f), + Cursor = Cursors.Hand, + FlatStyle = FlatStyle.Flat, + Enabled = false // habilitado apenas em modo edição + }; + btnBuscarCod.FlatAppearance.BorderSize = 0; + btnBuscarCod.Click += BtnBuscarCod_Click; + + content.Controls.Add(lblCod); + content.Controls.Add(txtCodCalibracao); + content.Controls.Add(btnBuscarCod); + + // ── SEÇÃO: ENSAIO ───────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Dados do Ensaio", 130)); + + txtDescricao = AddInput(content, "Descrição", 20, 168, 500, 32); + txtDescricao.MaxLength = 255; + + txtUnidade = AddInput(content, "Unidade", 540, 168, 160, 32); + txtUnidade.MaxLength = 50; + + // ── SEÇÃO: VALORES ──────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Valores", 230)); + + txtMinimo = AddInput(content, "Mínimo", 20, 268, 180, 32); + txtMinimo.MaxLength = 50; + + txtMaximo = AddInput(content, "Máximo", 220, 268, 180, 32); + txtMaximo.MaxLength = 50; + + txtObtido = AddInput(content, "Obtido", 420, 268, 180, 32); + txtObtido.MaxLength = 50; + + content.Height = 340; + } + + // ── MODOS DO FORMULÁRIO ─────────────────────────────────────────────── + private void AplicarModo(ModoFormulario modo) + { + _modo = modo; + + bool editando = modo == ModoFormulario.Novo || modo == ModoFormulario.Edicao; + + // Botão buscar só disponível ao editar + btnBuscarCod.Enabled = editando; + + // Campos editáveis + txtDescricao.ReadOnly = !editando; + txtMinimo.ReadOnly = !editando; + txtMaximo.ReadOnly = !editando; + txtObtido.ReadOnly = !editando; + txtUnidade.ReadOnly = !editando; + + // Cores + Color bgAtivo = Color.White; + Color bgInativo = ReadOnlyBg; + + txtDescricao.BackColor = editando ? bgAtivo : bgInativo; + txtMinimo.BackColor = editando ? bgAtivo : bgInativo; + txtMaximo.BackColor = editando ? bgAtivo : bgInativo; + txtObtido.BackColor = editando ? bgAtivo : bgInativo; + txtUnidade.BackColor = editando ? bgAtivo : bgInativo; + + // Bordas + txtDescricao.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtMinimo.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtMaximo.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtObtido.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtUnidade.BorderColor = editando ? BorderColor : ReadOnlyBorder; + + // Botões toolbar + btnNovo.Enabled = !editando; + btnAlterar.Enabled = !editando && _idAtual > 0; + btnExcluir.Enabled = !editando && _idAtual > 0; + btnLocalizar.Enabled = !editando; + btnSalvar.Enabled = editando; + btnCancelar.Enabled = editando; + + if (modo == ModoFormulario.Novo) LimparCampos(); + } + + // ── POPULAR / LIMPAR ────────────────────────────────────────────────── + private void PopularCampos(ModeloCalibracaoPadraoEnsaios m) + { + _idAtual = m.ID_CAL_PADRAO_ENSAIOS; + + txtId.Text = m.ID_CAL_PADRAO_ENSAIOS.ToString(); + txtCodigo.Text = m.CODIGO; + txtCodCalibracao.Text = m.COD_CALIBRACAO; + txtDescricao.Text = m.DESCRICAO; + txtMinimo.Text = m.MINIMO; + txtMaximo.Text = m.MAXIMO; + txtObtido.Text = m.OBTIDO; + txtUnidade.Text = m.UNIDADE; + } + + private void LimparCampos() + { + _idAtual = 0; + + txtId.Text = string.Empty; + txtCodigo.Text = string.Empty; + txtCodCalibracao.Text = string.Empty; + txtDescricao.Text = string.Empty; + txtMinimo.Text = string.Empty; + txtMaximo.Text = string.Empty; + txtObtido.Text = string.Empty; + txtUnidade.Text = string.Empty; + } + + // ── BUSCA DE CALIBRAÇÃO ─────────────────────────────────────────────── + private void BtnBuscarCod_Click(object? sender, EventArgs e) + { + // TODO: abrir formulário de busca de calibrações e retornar o código + // Exemplo: + // var frm = new FormularioBuscarCalibracao(); + // if (frm.ShowDialog() == DialogResult.OK) + // txtCodCalibracao.Text = frm.CodigoSelecionado; + + MessageBox.Show("Implemente o formulário de busca de calibrações.", + "Buscar Calibração", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + // ── VALIDAÇÃO ───────────────────────────────────────────────────────── + private bool Validar() + { + if (string.IsNullOrWhiteSpace(txtCodCalibracao.Text)) + { + MessageBox.Show("Selecione uma calibração.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + btnBuscarCod.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtDescricao.Text)) + { + MessageBox.Show("Informe a descrição do ensaio.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtDescricao.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtUnidade.Text)) + { + MessageBox.Show("Informe a unidade de medida.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtUnidade.Focus(); + return false; + } + + return true; + } + + // ── MONTAR MODELO ───────────────────────────────────────────────────── + private ModeloCalibracaoPadraoEnsaios MontarModelo() => new ModeloCalibracaoPadraoEnsaios( + _idAtual, + txtCodigo.Text.Trim(), + txtCodCalibracao.Text.Trim(), + txtDescricao.Text.Trim(), + txtMinimo.Text.Trim(), + txtMaximo.Text.Trim(), + txtObtido.Text.Trim(), + txtUnidade.Text.Trim() + ); + + // ── EVENTOS ABSTRATOS ───────────────────────────────────────────────── + protected override void OnNovo() + { + AplicarModo(ModoFormulario.Novo); + btnBuscarCod.Focus(); + } + + protected override void OnAlterar() + { + if (_idAtual == 0) return; + AplicarModo(ModoFormulario.Edicao); + txtDescricao.Focus(); + } + + protected override void OnExcluir() + { + if (_idAtual == 0) return; + + var confirm = MessageBox.Show( + $"Deseja realmente excluir o ensaio \"{txtDescricao.Text}\"?", + "Confirmar exclusão", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); + + if (confirm != DialogResult.Yes) return; + + try + { + // TODO: _bll.Excluir(_idAtual); + MessageBox.Show("Ensaio padrão excluído com sucesso.", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao excluir:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnLocalizar() + { + // TODO: abrir formulário de busca de ensaios padrão + // var frm = new FormularioBuscarCalibracaoPadraoEnsaios(); + // if (frm.ShowDialog() == DialogResult.OK) + // { + // PopularCampos(frm.EnsaioSelecionado); + // AplicarModo(ModoFormulario.Visualizacao); + // } + + MessageBox.Show("Implemente o formulário de busca de ensaios padrão.", + "Localizar", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + protected override void OnSalvar() + { + if (!Validar()) return; + + var modelo = MontarModelo(); + + try + { + if (_modo == ModoFormulario.Novo) + { + // TODO: _bll.Criar(modelo); + MessageBox.Show("Ensaio padrão cadastrado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + // TODO: _bll.Atualizar(modelo); + MessageBox.Show("Ensaio padrão atualizado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao salvar:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnCancelar() + { + if (_idAtual > 0) + { + // TODO: recarregar do banco se necessário + } + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/Calibracaoensaiocadastropanel.cs b/UI/Dashboards/Cadastros/Calibracaoensaiocadastropanel.cs new file mode 100644 index 0000000..2069104 --- /dev/null +++ b/UI/Dashboards/Cadastros/Calibracaoensaiocadastropanel.cs @@ -0,0 +1,331 @@ +using CPM; +using DAL; +using MLL; +using BLL; +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UI +{ + public class CalibracaoEnsaioCadastroPanel : FormularioModelo + { + // ── CAMPOS DO FORMULÁRIO ────────────────────────────────────────────── + private LV_TEXTBOX1 txtId = null!; + private LV_TEXTBOX1 txtCodCalibracao = null!; + private Button btnBuscarCod = null!; + private LV_TEXTBOX1 txtDescricao = null!; + private LV_TEXTBOX1 txtMinimo = null!; + private LV_TEXTBOX1 txtMaximo = null!; + private LV_TEXTBOX1 txtObtido = null!; + private LV_TEXTBOX1 txtUnidade = null!; + + // ── ESTADO ──────────────────────────────────────────────────────────── + private enum ModoFormulario { Visualizacao, Novo, Edicao } + private ModoFormulario _modo = ModoFormulario.Visualizacao; + private int _idAtual = 0; + + // ── BLL ─────────────────────────────────────────────────────────────── + // private CalibracaoEnsaioBLL _bll = null!; + + // ── CONSTRUTOR ──────────────────────────────────────────────────────── + public CalibracaoEnsaioCadastroPanel() + { + Titulo = "Cadastro de Ensaios de Calibração"; + BuildForm(); + AplicarModo(ModoFormulario.Visualizacao); + } + + // ── CONSTRUÇÃO DOS CAMPOS ───────────────────────────────────────────── + private void BuildForm() + { + // ── SEÇÃO: IDENTIFICAÇÃO ────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Identificação", 20)); + + txtId = AddInput(content, "ID", 20, 58, 80, 32, readOnly: true); + + // Código da Calibração + botão buscar + var lblCod = new Label + { + Text = "Código da Calibração", + Location = new Point(120, 58), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + + txtCodCalibracao = new LV_TEXTBOX1 + { + Location = new Point(120, 74), + Size = new Size(220, 32), + BorderColor = BorderColor, + BorderFocusColor = AccentBlue, + ReadOnly = true, // sempre preenchido via busca + BackColor = ReadOnlyBg + }; + + btnBuscarCod = new Button + { + Text = "🔍 Buscar", + Location = new Point(348, 74), + Size = new Size(90, 32), + BackColor = AccentBlue, + ForeColor = Color.White, + Font = new Font("Segoe UI Semibold", 8.5f), + Cursor = Cursors.Hand, + FlatStyle = FlatStyle.Flat, + Enabled = false // habilitado apenas em modo edição + }; + btnBuscarCod.FlatAppearance.BorderSize = 0; + btnBuscarCod.Click += BtnBuscarCod_Click; + + content.Controls.Add(lblCod); + content.Controls.Add(txtCodCalibracao); + content.Controls.Add(btnBuscarCod); + + // ── SEÇÃO: ENSAIO ───────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Dados do Ensaio", 130)); + + txtDescricao = AddInput(content, "Descrição", 20, 168, 500, 32); + txtDescricao.MaxLength = 255; + + txtUnidade = AddInput(content, "Unidade", 540, 168, 160, 32); + txtUnidade.MaxLength = 50; + + // ── SEÇÃO: VALORES ──────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Valores", 230)); + + txtMinimo = AddInput(content, "Mínimo", 20, 268, 180, 32); + txtMinimo.MaxLength = 50; + + txtMaximo = AddInput(content, "Máximo", 220, 268, 180, 32); + txtMaximo.MaxLength = 50; + + txtObtido = AddInput(content, "Obtido", 420, 268, 180, 32); + txtObtido.MaxLength = 50; + + content.Height = 340; + } + + // ── MODOS DO FORMULÁRIO ─────────────────────────────────────────────── + private void AplicarModo(ModoFormulario modo) + { + _modo = modo; + + bool editando = modo == ModoFormulario.Novo || modo == ModoFormulario.Edicao; + + // Botão buscar só disponível ao editar + btnBuscarCod.Enabled = editando; + + // Campos editáveis + txtDescricao.ReadOnly = !editando; + txtMinimo.ReadOnly = !editando; + txtMaximo.ReadOnly = !editando; + txtObtido.ReadOnly = !editando; + txtUnidade.ReadOnly = !editando; + + // Cores + Color bgAtivo = Color.White; + Color bgInativo = ReadOnlyBg; + + txtDescricao.BackColor = editando ? bgAtivo : bgInativo; + txtMinimo.BackColor = editando ? bgAtivo : bgInativo; + txtMaximo.BackColor = editando ? bgAtivo : bgInativo; + txtObtido.BackColor = editando ? bgAtivo : bgInativo; + txtUnidade.BackColor = editando ? bgAtivo : bgInativo; + + // Bordas + txtDescricao.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtMinimo.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtMaximo.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtObtido.BorderColor = editando ? BorderColor : ReadOnlyBorder; + txtUnidade.BorderColor = editando ? BorderColor : ReadOnlyBorder; + + // Botões toolbar + btnNovo.Enabled = !editando; + btnAlterar.Enabled = !editando && _idAtual > 0; + btnExcluir.Enabled = !editando && _idAtual > 0; + btnLocalizar.Enabled = !editando; + btnSalvar.Enabled = editando; + btnCancelar.Enabled = editando; + + if (modo == ModoFormulario.Novo) LimparCampos(); + } + + // ── POPULAR / LIMPAR ────────────────────────────────────────────────── + private void PopularCampos(ModeloCalibracaoEnsaio m) + { + _idAtual = m.ID_CALIBRACAO_ENSAIO; + + txtId.Text = m.ID_CALIBRACAO_ENSAIO.ToString(); + txtCodCalibracao.Text = m.COD_CALIBRACAO; + txtDescricao.Text = m.DESCRICAO; + txtMinimo.Text = m.MINIMO; + txtMaximo.Text = m.MAXIMO; + txtObtido.Text = m.OBTIDO; + txtUnidade.Text = m.UNIDADE; + } + + private void LimparCampos() + { + _idAtual = 0; + + txtId.Text = string.Empty; + txtCodCalibracao.Text = string.Empty; + txtDescricao.Text = string.Empty; + txtMinimo.Text = string.Empty; + txtMaximo.Text = string.Empty; + txtObtido.Text = string.Empty; + txtUnidade.Text = string.Empty; + } + + // ── BUSCA DE CALIBRAÇÃO ─────────────────────────────────────────────── + private void BtnBuscarCod_Click(object? sender, EventArgs e) + { + // TODO: abrir formulário de busca de calibrações e retornar o código + // Exemplo: + // var frm = new FormularioBuscarCalibracao(); + // if (frm.ShowDialog() == DialogResult.OK) + // txtCodCalibracao.Text = frm.CodigoSelecionado; + + MessageBox.Show("Implemente o formulário de busca de calibrações.", + "Buscar Calibração", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + // ── VALIDAÇÃO ───────────────────────────────────────────────────────── + private bool Validar() + { + if (string.IsNullOrWhiteSpace(txtCodCalibracao.Text)) + { + MessageBox.Show("Selecione uma calibração.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + btnBuscarCod.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtDescricao.Text)) + { + MessageBox.Show("Informe a descrição do ensaio.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtDescricao.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtUnidade.Text)) + { + MessageBox.Show("Informe a unidade de medida.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtUnidade.Focus(); + return false; + } + + return true; + } + + // ── MONTAR MODELO ───────────────────────────────────────────────────── + private ModeloCalibracaoEnsaio MontarModelo() => new ModeloCalibracaoEnsaio( + _idAtual, + txtCodCalibracao.Text.Trim(), + txtDescricao.Text.Trim(), + txtMinimo.Text.Trim(), + txtMaximo.Text.Trim(), + txtObtido.Text.Trim(), + txtUnidade.Text.Trim() + ); + + // ── EVENTOS ABSTRATOS ───────────────────────────────────────────────── + protected override void OnNovo() + { + AplicarModo(ModoFormulario.Novo); + btnBuscarCod.Focus(); + } + + protected override void OnAlterar() + { + if (_idAtual == 0) return; + AplicarModo(ModoFormulario.Edicao); + txtDescricao.Focus(); + } + + protected override void OnExcluir() + { + if (_idAtual == 0) return; + + var confirm = MessageBox.Show( + $"Deseja realmente excluir o ensaio \"{txtDescricao.Text}\"?", + "Confirmar exclusão", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); + + if (confirm != DialogResult.Yes) return; + + try + { + // TODO: _bll.Excluir(_idAtual); + MessageBox.Show("Ensaio excluído com sucesso.", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao excluir:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnLocalizar() + { + // TODO: abrir formulário de busca de ensaios + // var frm = new FormularioBuscarCalibracaoEnsaio(); + // if (frm.ShowDialog() == DialogResult.OK) + // { + // PopularCampos(frm.EnsaioSelecionado); + // AplicarModo(ModoFormulario.Visualizacao); + // } + + MessageBox.Show("Implemente o formulário de busca de ensaios.", + "Localizar", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + protected override void OnSalvar() + { + if (!Validar()) return; + + var modelo = MontarModelo(); + + try + { + if (_modo == ModoFormulario.Novo) + { + // TODO: _bll.Criar(modelo); + MessageBox.Show("Ensaio cadastrado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + // TODO: _bll.Atualizar(modelo); + MessageBox.Show("Ensaio atualizado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao salvar:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnCancelar() + { + if (_idAtual > 0) + { + // TODO: recarregar do banco se necessário + } + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/CartoesCadastroPanel.cs b/UI/Dashboards/Cadastros/CartoesCadastroPanel.cs new file mode 100644 index 0000000..97980f0 --- /dev/null +++ b/UI/Dashboards/Cadastros/CartoesCadastroPanel.cs @@ -0,0 +1,392 @@ +using CPM; +using DAL; +using MLL; +using BLL; +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UI +{ + public class CartoesCadastroPanel : FormularioModelo + { + // ── CAMPOS DO FORMULÁRIO ────────────────────────────────────────────── + private LV_TEXTBOX1 txtId = null!; + private LV_TEXTBOX1 txtCodigo = null!; + private LV_COMBOBOXCUSTOM cmbBandeira = null!; + private LV_TEXTBOX1 txtNumCartao = null!; + private LV_TEXTBOX1 txtNome = null!; + private LV_TEXTBOX1 txtValidade = null!; + private LV_TEXTBOX1 txtAutorizacao = null!; + private LV_TEXTBOX1 txtParcelas = null!; + private LV_TEXTBOX1 txtValor = null!; + private LV_TEXTBOX1 txtCodCliente = null!; + private LV_TEXTBOX1 txtResumo = null!; + private LV_TEXTBOX1 txtDebito = null!; + private LV_TEXTBOX1 txtCodConta = null!; + private LV_TEXTBOX1 txtDia = null!; + private LV_TEXTBOX1 txtCompensado = null!; + private LV_TEXTBOX1 txtObsComp = null!; + + // ── ESTADO ──────────────────────────────────────────────────────────── + private enum ModoFormulario { Visualizacao, Novo, Edicao } + private ModoFormulario _modo = ModoFormulario.Visualizacao; + private int _idAtual = 0; + + // ── BLL ─────────────────────────────────────────────────────────────── + // private CartoesBLL _bll = null!; + + // ── CONSTRUTOR ──────────────────────────────────────────────────────── + public CartoesCadastroPanel() + { + Titulo = "Cadastro de Cartões"; + BuildForm(); + AplicarModo(ModoFormulario.Visualizacao); + } + + // ── CONSTRUÇÃO DOS CAMPOS ───────────────────────────────────────────── + private void BuildForm() + { + // ── SEÇÃO: IDENTIFICAÇÃO ────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Identificação", 20)); + + txtId = AddInput(content, "ID", 20, 58, 80, 32, readOnly: true); + txtCodigo = AddInput(content, "Código", 120, 58, 160, 32); + txtCodigo.MaxLength = 50; + + // ── SEÇÃO: DADOS DO CARTÃO ──────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Dados do Cartão", 110)); + + // Bandeira — LV_COMBOBOXCUSTOM + var lblBandeira = new Label + { + Text = "Bandeira", + Location = new Point(20, 148), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + cmbBandeira = new LV_COMBOBOXCUSTOM + { + Location = new Point(20, 164), + Size = new Size(160, 32), + DropDownStyle = ComboBoxStyle.DropDownList, + BorderColor = BorderColor, + BackColor = Color.White, + ListBackColor = Color.White, + ListTextColor = TextDark, + IconColor = AccentBlue, + Font = new Font("Segoe UI", 9f) + }; + cmbBandeira.Items.Add("Visa"); + cmbBandeira.Items.Add("Mastercard"); + cmbBandeira.Items.Add("Elo"); + cmbBandeira.Items.Add("American Express"); + cmbBandeira.Items.Add("Hipercard"); + cmbBandeira.Items.Add("PayPal"); + cmbBandeira.Items.Add("Outro"); + cmbBandeira.SelectedIndex = 0; + content.Controls.Add(lblBandeira); + content.Controls.Add(cmbBandeira); + + txtNumCartao = AddInput(content, "Número do Cartão", 200, 148, 220, 32); + txtNumCartao.MaxLength = 20; + + txtNome = AddInput(content, "Nome no Cartão", 440, 148, 260, 32); + txtNome.MaxLength = 100; + + txtValidade = AddInput(content, "Validade", 20, 228, 120, 32); + txtValidade.MaxLength = 10; + + txtAutorizacao = AddInput(content, "Autorização", 160, 228, 180, 32); + txtAutorizacao.MaxLength = 50; + + txtParcelas = AddInput(content, "Parcelas", 360, 228, 100, 32); + txtParcelas.MaxLength = 10; + + txtValor = AddInput(content, "Valor", 480, 228, 140, 32); + txtValor.MaxLength = 20; + + // ── SEÇÃO: CLIENTE E CONTA ──────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Cliente e Conta", 290)); + + txtCodCliente = AddInput(content, "Cód. Cliente", 20, 328, 160, 32); + txtCodCliente.MaxLength = 50; + + txtCodConta = AddInput(content, "Cód. Conta", 200, 328, 160, 32); + txtCodConta.MaxLength = 50; + + txtDia = AddInput(content, "Dia", 380, 328, 80, 32); + txtDia.MaxLength = 5; + + txtDebito = AddInput(content, "Débito", 480, 328, 140, 32); + txtDebito.MaxLength = 20; + + // ── SEÇÃO: COMPENSAÇÃO ──────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Compensação", 390)); + + txtResumo = AddInput(content, "Resumo", 20, 428, 300, 32); + txtResumo.MaxLength = 255; + + txtCompensado = AddInput(content, "Compensado", 340, 428, 120, 32); + txtCompensado.MaxLength = 20; + + // Observações da compensação — multiline + var lblObsComp = new Label + { + Text = "Obs. Compensação", + Location = new Point(20, 490), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + txtObsComp = new LV_TEXTBOX1 + { + Location = new Point(20, 506), + Size = new Size(700, 70), + BorderColor = BorderColor, + BorderFocusColor = AccentBlue, + Multiline = true, + MaxLength = 255 + }; + content.Controls.Add(lblObsComp); + content.Controls.Add(txtObsComp); + + content.Height = 610; + } + + // ── CAMPOS EDITÁVEIS — lista para evitar repetição ──────────────────── + private LV_TEXTBOX1[] CamposEditaveis() => new[] + { + txtCodigo, txtNumCartao, txtNome, txtValidade, txtAutorizacao, + txtParcelas, txtValor, txtCodCliente, txtResumo, txtDebito, + txtCodConta, txtDia, txtCompensado, txtObsComp + }; + + // ── MODOS DO FORMULÁRIO ─────────────────────────────────────────────── + private void AplicarModo(ModoFormulario modo) + { + _modo = modo; + + bool editando = modo == ModoFormulario.Novo || modo == ModoFormulario.Edicao; + + foreach (var txt in CamposEditaveis()) + { + txt.ReadOnly = !editando; + txt.BackColor = editando ? Color.White : ReadOnlyBg; + txt.BorderColor = editando ? BorderColor : ReadOnlyBorder; + } + + cmbBandeira.Enabled = editando; + cmbBandeira.BorderColor = editando ? BorderColor : ReadOnlyBorder; + cmbBandeira.BackColor = editando ? Color.White : ReadOnlyBg; + + btnNovo.Enabled = !editando; + btnAlterar.Enabled = !editando && _idAtual > 0; + btnExcluir.Enabled = !editando && _idAtual > 0; + btnLocalizar.Enabled = !editando; + btnSalvar.Enabled = editando; + btnCancelar.Enabled = editando; + + if (modo == ModoFormulario.Novo) LimparCampos(); + } + + // ── POPULAR / LIMPAR ────────────────────────────────────────────────── + private void PopularCampos(ModeloCartoes m) + { + _idAtual = m.ID_COD_CARTAO; + + txtId.Text = m.ID_COD_CARTAO.ToString(); + txtCodigo.Text = m.CODIGO; + txtNumCartao.Text = m.NUM_CARTAO; + txtNome.Text = m.NOME; + txtValidade.Text = m.VALIDADE; + txtAutorizacao.Text = m.AUTORIZACAO; + txtParcelas.Text = m.PARCELAS; + txtValor.Text = m.VALOR; + txtCodCliente.Text = m.COD_CLIENTE; + txtResumo.Text = m.RESUMO; + txtDebito.Text = m.DEBITO; + txtCodConta.Text = m.COD_CONTA; + txtDia.Text = m.DIA; + txtCompensado.Text = m.COMPENSADO; + txtObsComp.Text = m.OBS_COMP; + + // Seleciona bandeira no ComboBox + for (int i = 0; i < cmbBandeira.Items.Count; i++) + { + if (cmbBandeira.Items[i]?.ToString() == m.BANDEIRA) + { + cmbBandeira.SelectedIndex = i; + break; + } + } + } + + private void LimparCampos() + { + _idAtual = 0; + txtId.Text = string.Empty; + txtCodigo.Text = string.Empty; + txtNumCartao.Text = string.Empty; + txtNome.Text = string.Empty; + txtValidade.Text = string.Empty; + txtAutorizacao.Text = string.Empty; + txtParcelas.Text = string.Empty; + txtValor.Text = string.Empty; + txtCodCliente.Text = string.Empty; + txtResumo.Text = string.Empty; + txtDebito.Text = string.Empty; + txtCodConta.Text = string.Empty; + txtDia.Text = string.Empty; + txtCompensado.Text = string.Empty; + txtObsComp.Text = string.Empty; + cmbBandeira.SelectedIndex = 0; + } + + // ── VALIDAÇÃO ───────────────────────────────────────────────────────── + private bool Validar() + { + if (string.IsNullOrWhiteSpace(txtCodigo.Text)) + { + MessageBox.Show("Informe o código do cartão.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtCodigo.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtNumCartao.Text)) + { + MessageBox.Show("Informe o número do cartão.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtNumCartao.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtValor.Text)) + { + MessageBox.Show("Informe o valor.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtValor.Focus(); + return false; + } + + return true; + } + + // ── MONTAR MODELO ───────────────────────────────────────────────────── + private ModeloCartoes MontarModelo() => new ModeloCartoes( + _idAtual, + txtCodigo.Text.Trim(), + cmbBandeira.SelectedItem?.ToString() ?? string.Empty, + txtNumCartao.Text.Trim(), + txtNome.Text.Trim(), + txtValidade.Text.Trim(), + txtAutorizacao.Text.Trim(), + txtParcelas.Text.Trim(), + txtValor.Text.Trim(), + txtCodCliente.Text.Trim(), + txtResumo.Text.Trim(), + txtDebito.Text.Trim(), + txtCodConta.Text.Trim(), + txtDia.Text.Trim(), + txtCompensado.Text.Trim(), + txtObsComp.Text.Trim() + ); + + // ── EVENTOS ABSTRATOS ───────────────────────────────────────────────── + protected override void OnNovo() + { + AplicarModo(ModoFormulario.Novo); + txtCodigo.Focus(); + } + + protected override void OnAlterar() + { + if (_idAtual == 0) return; + AplicarModo(ModoFormulario.Edicao); + txtCodigo.Focus(); + } + + protected override void OnExcluir() + { + if (_idAtual == 0) return; + + var confirm = MessageBox.Show( + $"Deseja realmente excluir o cartão \"{txtNumCartao.Text}\"?", + "Confirmar exclusão", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); + + if (confirm != DialogResult.Yes) return; + + try + { + // TODO: _bll.Excluir(_idAtual); + MessageBox.Show("Cartão excluído com sucesso.", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao excluir:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnLocalizar() + { + // TODO: abrir formulário de busca de cartões + // var frm = new FormularioBuscarCartoes(); + // if (frm.ShowDialog() == DialogResult.OK) + // { + // PopularCampos(frm.CartaoSelecionado); + // AplicarModo(ModoFormulario.Visualizacao); + // } + + MessageBox.Show("Implemente o formulário de busca de cartões.", + "Localizar", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + protected override void OnSalvar() + { + if (!Validar()) return; + + var modelo = MontarModelo(); + + try + { + if (_modo == ModoFormulario.Novo) + { + // TODO: _bll.Criar(modelo); + MessageBox.Show("Cartão cadastrado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + // TODO: _bll.Atualizar(modelo); + MessageBox.Show("Cartão atualizado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao salvar:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnCancelar() + { + if (_idAtual > 0) + { + // TODO: recarregar do banco se necessário + } + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/ChamadoCadastroPanel.cs b/UI/Dashboards/Cadastros/ChamadoCadastroPanel.cs new file mode 100644 index 0000000..7550f77 --- /dev/null +++ b/UI/Dashboards/Cadastros/ChamadoCadastroPanel.cs @@ -0,0 +1,508 @@ +using CPM; +using DAL; +using MLL; +using BLL; +using System; +using System.Drawing; +using System.Windows.Forms; + +namespace UI +{ + public class ChamadoCadastroPanel : FormularioModelo + { + // ── CAMPOS DO FORMULÁRIO ────────────────────────────────────────────── + private LV_TEXTBOX1 txtId = null!; + private LV_TEXTBOX1 txtCodigo = null!; + private LV_COMBOBOXCUSTOM cmbTipo = null!; + private LV_COMBOBOXCUSTOM cmbPrioridade = null!; + + // Cliente — busca + campos auto-preenchidos + private LV_TEXTBOX1 txtCodCliente = null!; + private Button btnBuscarCliente = null!; + private LV_TEXTBOX1 txtNomeAvulso = null!; + private LV_TEXTBOX1 txtFones = null!; + private LV_TEXTBOX1 txtEmail = null!; + private LV_TEXTBOX1 txtEnderCli = null!; + + private LV_TEXTBOX1 txtPara = null!; + private LV_TEXTBOX1 txtRealizado = null!; + private LV_TEXTBOX1 txtDiaChamado = null!; + private LV_TEXTBOX1 txtObs = null!; + + // ── ESTADO ──────────────────────────────────────────────────────────── + private enum ModoFormulario { Visualizacao, Novo, Edicao } + private ModoFormulario _modo = ModoFormulario.Visualizacao; + private int _idAtual = 0; + + // ── BLL ─────────────────────────────────────────────────────────────── + // private ChamadoBLL _bll = null!; + + // ── CONSTRUTOR ──────────────────────────────────────────────────────── + public ChamadoCadastroPanel() + { + Titulo = "Cadastro de Chamados"; + BuildForm(); + AplicarModo(ModoFormulario.Visualizacao); + } + + // ── CONSTRUÇÃO DOS CAMPOS ───────────────────────────────────────────── + private void BuildForm() + { + // ── SEÇÃO: IDENTIFICAÇÃO ────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Identificação", 20)); + + txtId = AddInput(content, "ID", 20, 58, 80, 32, readOnly: true); + txtCodigo = AddInput(content, "Código", 120, 58, 160, 32); + txtCodigo.MaxLength = 50; + + // Tipo + var lblTipo = new Label + { + Text = "Tipo", + Location = new Point(300, 58), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + cmbTipo = new LV_COMBOBOXCUSTOM + { + Location = new Point(300, 74), + Size = new Size(180, 32), + DropDownStyle = ComboBoxStyle.DropDownList, + BorderColor = BorderColor, + BackColor = Color.White, + ListBackColor = Color.White, + ListTextColor = TextDark, + IconColor = AccentBlue, + Font = new Font("Segoe UI", 9f) + }; + cmbTipo.Items.Add("Suporte Técnico"); + cmbTipo.Items.Add("Manutenção"); + cmbTipo.Items.Add("Instalação"); + cmbTipo.Items.Add("Consultoria"); + cmbTipo.Items.Add("Reclamação"); + cmbTipo.Items.Add("Outro"); + cmbTipo.SelectedIndex = 0; + content.Controls.Add(lblTipo); + content.Controls.Add(cmbTipo); + + // Prioridade + var lblPrioridade = new Label + { + Text = "Prioridade", + Location = new Point(500, 58), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + cmbPrioridade = new LV_COMBOBOXCUSTOM + { + Location = new Point(500, 74), + Size = new Size(160, 32), + DropDownStyle = ComboBoxStyle.DropDownList, + BorderColor = BorderColor, + BackColor = Color.White, + ListBackColor = Color.White, + ListTextColor = TextDark, + IconColor = AccentBlue, + Font = new Font("Segoe UI", 9f) + }; + cmbPrioridade.Items.Add("Baixa"); + cmbPrioridade.Items.Add("Normal"); + cmbPrioridade.Items.Add("Alta"); + cmbPrioridade.Items.Add("Urgente"); + cmbPrioridade.SelectedIndex = 1; // Normal como padrão + content.Controls.Add(lblPrioridade); + content.Controls.Add(cmbPrioridade); + + // ── SEÇÃO: CLIENTE ──────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Cliente", 128)); + + // Cód. Cliente + botão buscar + var lblCodCliente = new Label + { + Text = "Cód. Cliente", + Location = new Point(20, 166), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + txtCodCliente = new LV_TEXTBOX1 + { + Location = new Point(20, 182), + Size = new Size(160, 32), + BorderColor = BorderColor, + BorderFocusColor = AccentBlue, + ReadOnly = true, + BackColor = ReadOnlyBg + }; + btnBuscarCliente = new Button + { + Text = "🔍 Buscar", + Location = new Point(188, 182), + Size = new Size(90, 32), + BackColor = AccentBlue, + ForeColor = Color.White, + Font = new Font("Segoe UI Semibold", 8.5f), + Cursor = Cursors.Hand, + FlatStyle = FlatStyle.Flat, + Enabled = false + }; + btnBuscarCliente.FlatAppearance.BorderSize = 0; + btnBuscarCliente.Click += BtnBuscarCliente_Click; + + content.Controls.Add(lblCodCliente); + content.Controls.Add(txtCodCliente); + content.Controls.Add(btnBuscarCliente); + + txtNomeAvulso = AddInput(content, "Nome Avulso", 298, 166, 280, 32); + txtNomeAvulso.MaxLength = 150; + + // Fones — readonly, preenchido via busca + var lblFones = new Label + { + Text = "Fones", + Location = new Point(20, 234), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = Color.Gray, + AutoSize = true + }; + txtFones = new LV_TEXTBOX1 + { + Location = new Point(20, 250), + Size = new Size(200, 32), + BorderColor = ReadOnlyBorder, + BorderFocusColor = AccentBlue, + ReadOnly = true, + BackColor = ReadOnlyBg + }; + content.Controls.Add(lblFones); + content.Controls.Add(txtFones); + + txtEmail = AddInput(content, "E-mail", 240, 234, 240, 32); + txtEmail.MaxLength = 150; + + // Endereço — readonly, preenchido via busca + var lblEnderCli = new Label + { + Text = "Endereço", + Location = new Point(20, 302), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = Color.Gray, + AutoSize = true + }; + txtEnderCli = new LV_TEXTBOX1 + { + Location = new Point(20, 318), + Size = new Size(680, 32), + BorderColor = ReadOnlyBorder, + BorderFocusColor = AccentBlue, + ReadOnly = true, + BackColor = ReadOnlyBg + }; + content.Controls.Add(lblEnderCli); + content.Controls.Add(txtEnderCli); + + // ── SEÇÃO: CHAMADO ──────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Chamado", 370)); + + txtPara = AddInput(content, "Para", 20, 408, 260, 32); + txtPara.MaxLength = 100; + + txtDiaChamado = AddInput(content, "Data", 300, 408, 160, 32); + txtDiaChamado.MaxLength = 20; + + txtRealizado = AddInput(content, "Realizado", 480, 408, 220, 32); + txtRealizado.MaxLength = 50; + + // Observações — multiline + var lblObs = new Label + { + Text = "Observações", + Location = new Point(20, 460), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + txtObs = new LV_TEXTBOX1 + { + Location = new Point(20, 476), + Size = new Size(680, 70), + BorderColor = BorderColor, + BorderFocusColor = AccentBlue, + Multiline = true, + MaxLength = 500 + }; + content.Controls.Add(lblObs); + content.Controls.Add(txtObs); + + content.Height = 580; + } + + // ── CAMPOS EDITÁVEIS ────────────────────────────────────────────────── + private LV_TEXTBOX1[] CamposEditaveis() => new[] + { + txtCodigo, txtNomeAvulso, txtEmail, + txtPara, txtDiaChamado, txtRealizado, txtObs + }; + + // ── MODOS DO FORMULÁRIO ─────────────────────────────────────────────── + private void AplicarModo(ModoFormulario modo) + { + _modo = modo; + + bool editando = modo == ModoFormulario.Novo || modo == ModoFormulario.Edicao; + + // Campos editáveis normais + foreach (var txt in CamposEditaveis()) + { + txt.ReadOnly = !editando; + txt.BackColor = editando ? Color.White : ReadOnlyBg; + txt.BorderColor = editando ? BorderColor : ReadOnlyBorder; + } + + // Botão buscar cliente — só em modo edição + btnBuscarCliente.Enabled = editando; + + // ComboBoxes + cmbTipo.Enabled = editando; + cmbTipo.BorderColor = editando ? BorderColor : ReadOnlyBorder; + cmbTipo.BackColor = editando ? Color.White : ReadOnlyBg; + + cmbPrioridade.Enabled = editando; + cmbPrioridade.BorderColor = editando ? BorderColor : ReadOnlyBorder; + cmbPrioridade.BackColor = editando ? Color.White : ReadOnlyBg; + + // Fones e Endereço: sempre readonly — só mudam via busca de cliente + txtFones.BorderColor = ReadOnlyBorder; + txtFones.BackColor = ReadOnlyBg; + txtEnderCli.BorderColor = ReadOnlyBorder; + txtEnderCli.BackColor = ReadOnlyBg; + + // Botões toolbar + btnNovo.Enabled = !editando; + btnAlterar.Enabled = !editando && _idAtual > 0; + btnExcluir.Enabled = !editando && _idAtual > 0; + btnLocalizar.Enabled = !editando; + btnSalvar.Enabled = editando; + btnCancelar.Enabled = editando; + + if (modo == ModoFormulario.Novo) LimparCampos(); + } + + // ── BUSCA DE CLIENTE ────────────────────────────────────────────────── + private void BtnBuscarCliente_Click(object? sender, EventArgs e) + { + // TODO: abrir formulário de busca de clientes e retornar dados + // var frm = new FormularioBuscarCliente(); + // if (frm.ShowDialog() == DialogResult.OK) + // { + // var cli = frm.ClienteSelecionado; + // txtCodCliente.Text = cli.CODIGO; + // txtFones.Text = cli.FONE; + // txtEnderCli.Text = cli.ENDERECO; + // } + + MessageBox.Show("Implemente o formulário de busca de clientes.", + "Buscar Cliente", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + // ── POPULAR / LIMPAR ────────────────────────────────────────────────── + private void PopularCampos(ModeloChamado m) + { + _idAtual = m.ID_CHAMADO; + + txtId.Text = m.ID_CHAMADO.ToString(); + txtCodigo.Text = m.CODIGO; + txtCodCliente.Text = m.COD_CLIENTE; + txtNomeAvulso.Text = m.NOME_AVULSO; + txtFones.Text = m.FONES; + txtEmail.Text = m.EMAIL; + txtEnderCli.Text = m.ENDER_CLI; + txtPara.Text = m.PARA; + txtRealizado.Text = m.REALIZADO; + txtDiaChamado.Text = m.DIA_CHAMADO; + txtObs.Text = m.OBS; + + SelecionarCombo(cmbTipo, m.TIPO); + SelecionarCombo(cmbPrioridade, m.PRIORIDADE); + } + + private void LimparCampos() + { + _idAtual = 0; + + txtId.Text = string.Empty; + txtCodigo.Text = string.Empty; + txtCodCliente.Text = string.Empty; + txtNomeAvulso.Text = string.Empty; + txtFones.Text = string.Empty; + txtEmail.Text = string.Empty; + txtEnderCli.Text = string.Empty; + txtPara.Text = string.Empty; + txtRealizado.Text = string.Empty; + txtDiaChamado.Text = string.Empty; + txtObs.Text = string.Empty; + + cmbTipo.SelectedIndex = 0; + cmbPrioridade.SelectedIndex = 1; // Normal + } + + // ── HELPER: SELECIONAR ITEM NO COMBOBOX ─────────────────────────────── + private static void SelecionarCombo(LV_COMBOBOXCUSTOM cmb, string valor) + { + for (int i = 0; i < cmb.Items.Count; i++) + { + if (cmb.Items[i]?.ToString() == valor) + { + cmb.SelectedIndex = i; + return; + } + } + cmb.SelectedIndex = 0; + } + + // ── VALIDAÇÃO ───────────────────────────────────────────────────────── + private bool Validar() + { + if (string.IsNullOrWhiteSpace(txtCodigo.Text)) + { + MessageBox.Show("Informe o código do chamado.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtCodigo.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtCodCliente.Text) && + string.IsNullOrWhiteSpace(txtNomeAvulso.Text)) + { + MessageBox.Show("Informe o cliente ou o nome avulso.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + btnBuscarCliente.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtDiaChamado.Text)) + { + MessageBox.Show("Informe a data do chamado.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtDiaChamado.Focus(); + return false; + } + + return true; + } + + // ── MONTAR MODELO ───────────────────────────────────────────────────── + private ModeloChamado MontarModelo() => new ModeloChamado( + _idAtual, + txtCodigo.Text.Trim(), + cmbTipo.SelectedItem?.ToString() ?? string.Empty, + txtCodCliente.Text.Trim(), + txtNomeAvulso.Text.Trim(), + txtFones.Text.Trim(), + txtEmail.Text.Trim(), + txtPara.Text.Trim(), + cmbPrioridade.SelectedItem?.ToString() ?? string.Empty, + txtRealizado.Text.Trim(), + txtDiaChamado.Text.Trim(), + txtObs.Text.Trim(), + txtEnderCli.Text.Trim() + ); + + // ── EVENTOS ABSTRATOS ───────────────────────────────────────────────── + protected override void OnNovo() + { + AplicarModo(ModoFormulario.Novo); + txtCodigo.Focus(); + } + + protected override void OnAlterar() + { + if (_idAtual == 0) return; + AplicarModo(ModoFormulario.Edicao); + txtCodigo.Focus(); + } + + protected override void OnExcluir() + { + if (_idAtual == 0) return; + + var confirm = MessageBox.Show( + $"Deseja realmente excluir o chamado \"{txtCodigo.Text}\"?", + "Confirmar exclusão", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); + + if (confirm != DialogResult.Yes) return; + + try + { + // TODO: _bll.Excluir(_idAtual); + MessageBox.Show("Chamado excluído com sucesso.", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao excluir:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnLocalizar() + { + // TODO: abrir formulário de busca de chamados + // var frm = new FormularioBuscarChamado(); + // if (frm.ShowDialog() == DialogResult.OK) + // { + // PopularCampos(frm.ChamadoSelecionado); + // AplicarModo(ModoFormulario.Visualizacao); + // } + + MessageBox.Show("Implemente o formulário de busca de chamados.", + "Localizar", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + protected override void OnSalvar() + { + if (!Validar()) return; + + var modelo = MontarModelo(); + + try + { + if (_modo == ModoFormulario.Novo) + { + // TODO: _bll.Criar(modelo); + MessageBox.Show("Chamado cadastrado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else + { + // TODO: _bll.Atualizar(modelo); + MessageBox.Show("Chamado atualizado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao salvar:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnCancelar() + { + if (_idAtual > 0) + { + // TODO: recarregar do banco se necessário + } + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/UsuariosCadastroPanel.cs b/UI/Dashboards/Cadastros/UsuariosCadastroPanel.cs new file mode 100644 index 0000000..8e3cfa5 --- /dev/null +++ b/UI/Dashboards/Cadastros/UsuariosCadastroPanel.cs @@ -0,0 +1,409 @@ +using CPM; +using DAL; +using MLL; +using BLL; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; + +namespace UI +{ + public class UsuariosCadastroPanel : FormularioModelo + { + // ── CAMPOS DO FORMULÁRIO ────────────────────────────────────────────── + private LV_TEXTBOX1 txtId = null!; + private LV_TEXTBOX1 txtNome = null!; + private LV_TEXTBOX1 txtEmail = null!; + private LV_TEXTBOX1 txtUsuario = null!; + private LV_TEXTBOX1 txtSenha = null!; + private LV_TEXTBOX1 txtUltimoLogin = null!; + private LV_TEXTBOX1 txtCriadoEm = null!; + private CheckBox chkAtivo = null!; + private LV_COMBOBOXCUSTOM cmbPerfil = null!; + + // ── ESTADO DO FORMULÁRIO ────────────────────────────────────────────── + private enum ModoFormulario { Visualizacao, Novo, Edicao } + private ModoFormulario _modo = ModoFormulario.Visualizacao; + private int _usuarioAtualId = 0; + + // ── BLL ─────────────────────────────────────────────────────────────── + // Substitua pelos seus serviços reais quando implementar + // private UsuarioBLL _usuarioBLL = null!; + // private PerfilBLL _perfilBLL = null!; + + // ── CONSTRUTOR ──────────────────────────────────────────────────────── + public UsuariosCadastroPanel() + { + Titulo = "Cadastro de Usuários"; + BuildForm(); + AplicarModo(ModoFormulario.Visualizacao); + } + + // ── CONSTRUÇÃO DOS CAMPOS ───────────────────────────────────────────── + private void BuildForm() + { + // ── SEÇÃO: IDENTIFICAÇÃO ────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Identificação", 20)); + + txtId = AddInput(content, "ID", 20, 58, 80, 32, readOnly: true); + + txtNome = AddInput(content, "Nome completo", 120, 58, 320, 32); + txtNome.MaxLength = 255; + + txtEmail = AddInput(content, "E-mail", 460, 58, 280, 32); + txtEmail.MaxLength = 150; + + // ── SEÇÃO: ACESSO ───────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Acesso ao sistema", 120)); + + txtUsuario = AddInput(content, "Usuário (login)", 20, 158, 200, 32); + txtUsuario.MaxLength = 50; + + txtSenha = AddInput(content, "Senha", 240, 158, 200, 32); + txtSenha.PasswordChar = '●'; + txtSenha.MaxLength = 255; + + // Perfil — LV_COMBOBOXCUSTOM + var lblPerfil = new Label + { + Text = "Perfil de acesso", + Location = new Point(460, 158), + Font = new Font("Segoe UI", 7.5f, FontStyle.Bold), + ForeColor = TextDark, + AutoSize = true + }; + + cmbPerfil = new LV_COMBOBOXCUSTOM + { + Location = new Point(460, 174), + Size = new Size(280, 32), + DropDownStyle = ComboBoxStyle.DropDownList, + BorderColor = BorderColor, + BackColor = Color.White, + ListBackColor = Color.White, + ListTextColor = TextDark, + IconColor = AccentBlue, + Font = new Font("Segoe UI", 9f) + }; + + content.Controls.Add(lblPerfil); + content.Controls.Add(cmbPerfil); + + // ── SEÇÃO: STATUS ───────────────────────────────────────────────── + content.Controls.Add(CreateSectionHeader("Status", 230)); + + chkAtivo = CreateCheckBox("Usuário ativo", 20, 268); + chkAtivo.Checked = true; + content.Controls.Add(chkAtivo); + + // ── SEÇÃO: AUDITORIA (somente leitura) ──────────────────────────── + content.Controls.Add(CreateSectionHeader("Auditoria", 310)); + + txtUltimoLogin = AddInput(content, "Último login", 20, 348, 200, 32, readOnly: true); + txtCriadoEm = AddInput(content, "Criado em", 240, 348, 200, 32, readOnly: true); + + // Ajusta altura do content + content.Height = 420; + } + + // ── CARREGAR PERFIS DO BANCO ────────────────────────────────────────── + private void CarregarPerfis() + { + cmbPerfil.Items.Clear(); + cmbPerfil.Items.Add(new ComboItem(0, "— Selecione um perfil —")); + + try + { + // TODO: substituir pela chamada real à BLL + // var perfis = _perfilBLL.ListarAtivosPorEmpresa(empresaId); + // foreach (var p in perfis) + // cmbPerfil.Items.Add(new ComboItem(p.Id, p.Nome)); + + // ── Exemplo estático para desenvolvimento ── + cmbPerfil.Items.Add(new ComboItem(1, "Administrador")); + cmbPerfil.Items.Add(new ComboItem(2, "Técnico")); + cmbPerfil.Items.Add(new ComboItem(3, "Vendedor")); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao carregar perfis:\n{ex.Message}", + "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + + cmbPerfil.SelectedIndex = 0; + } + + // ── MODOS DO FORMULÁRIO ─────────────────────────────────────────────── + private void AplicarModo(ModoFormulario modo) + { + _modo = modo; + + bool editando = modo == ModoFormulario.Novo || modo == ModoFormulario.Edicao; + bool isNovo = modo == ModoFormulario.Novo; + + // Campos editáveis conforme o modo + txtNome.ReadOnly = !editando; + txtEmail.ReadOnly = !editando; + txtUsuario.ReadOnly = !editando; + txtSenha.ReadOnly = !editando; + cmbPerfil.Enabled = editando; + cmbPerfil.BorderColor = editando ? BorderColor : ReadOnlyBorder; + cmbPerfil.BackColor = editando ? Color.White : ReadOnlyBg; + chkAtivo.Enabled = editando; + + // Cor de fundo dos campos conforme readonly + Color bgAtivo = Color.White; + Color bgInativo = ReadOnlyBg; + + txtNome.BackColor = editando ? bgAtivo : bgInativo; + txtEmail.BackColor = editando ? bgAtivo : bgInativo; + txtUsuario.BackColor = editando ? bgAtivo : bgInativo; + txtSenha.BackColor = editando ? bgAtivo : bgInativo; + + // Senha: só obrigatória no cadastro novo + // Na edição, deixar em branco = manter senha atual + if (modo == ModoFormulario.Edicao) + { + var lblSenha = content.Controls.Find("lblSenhaInfo", true); + // Opcional: exibir aviso "deixe em branco para manter a senha" + } + + // Botões + btnNovo.Enabled = !editando; + btnAlterar.Enabled = !editando && _usuarioAtualId > 0; + btnExcluir.Enabled = !editando && _usuarioAtualId > 0; + btnLocalizar.Enabled = !editando; + btnSalvar.Enabled = editando; + btnCancelar.Enabled = editando; + + // No modo Novo limpa os campos + if (isNovo) LimparCampos(); + } + + // ── POPULAR CAMPOS COM UM USUÁRIO ───────────────────────────────────── + private void PopularCampos(ModeloUsuario u, int perfilId) + { + _usuarioAtualId = u.Id; + + txtId.Text = u.Id.ToString(); + txtNome.Text = u.Nome; + txtEmail.Text = u.Email; + txtUsuario.Text = u.Usuario; + txtSenha.Text = string.Empty; // nunca exibe hash + chkAtivo.Checked = u.Ativo; + txtUltimoLogin.Text = u.UltimoLogin.HasValue + ? u.UltimoLogin.Value.ToString("dd/MM/yyyy HH:mm") + : "Nunca"; + txtCriadoEm.Text = u.CriadoEm.ToString("dd/MM/yyyy HH:mm"); + + // Seleciona o perfil no ComboBox + for (int i = 0; i < cmbPerfil.Items.Count; i++) + { + if (cmbPerfil.Items[i] is ComboItem item && item.Id == perfilId) + { + cmbPerfil.SelectedIndex = i; + break; + } + } + } + + private void LimparCampos() + { + _usuarioAtualId = 0; + txtId.Text = string.Empty; + txtNome.Text = string.Empty; + txtEmail.Text = string.Empty; + txtUsuario.Text = string.Empty; + txtSenha.Text = string.Empty; + chkAtivo.Checked = true; + txtUltimoLogin.Text = string.Empty; + txtCriadoEm.Text = string.Empty; + if (cmbPerfil.Items.Count > 0) + cmbPerfil.SelectedIndex = 0; + } + + // ── VALIDAÇÃO ───────────────────────────────────────────────────────── + private bool Validar() + { + if (string.IsNullOrWhiteSpace(txtNome.Text)) + { + MessageBox.Show("Informe o nome do usuário.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtNome.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtEmail.Text)) + { + MessageBox.Show("Informe o e-mail.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtEmail.Focus(); + return false; + } + + if (string.IsNullOrWhiteSpace(txtUsuario.Text)) + { + MessageBox.Show("Informe o login do usuário.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtUsuario.Focus(); + return false; + } + + // Senha obrigatória apenas no cadastro novo + if (_modo == ModoFormulario.Novo && string.IsNullOrWhiteSpace(txtSenha.Text)) + { + MessageBox.Show("Informe a senha para o novo usuário.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + txtSenha.Focus(); + return false; + } + + if (cmbPerfil.SelectedItem is not ComboItem perfil || perfil.Id == 0) + { + MessageBox.Show("Selecione um perfil de acesso.", "Validação", + MessageBoxButtons.OK, MessageBoxIcon.Warning); + cmbPerfil.Focus(); + return false; + } + + return true; + } + + // ── EVENTOS ABSTRATOS ───────────────────────────────────────────────── + protected override void OnNovo() + { + CarregarPerfis(); + AplicarModo(ModoFormulario.Novo); + txtNome.Focus(); + } + + protected override void OnAlterar() + { + if (_usuarioAtualId == 0) return; + AplicarModo(ModoFormulario.Edicao); + txtNome.Focus(); + } + + protected override void OnExcluir() + { + if (_usuarioAtualId == 0) return; + + var confirm = MessageBox.Show( + $"Deseja realmente excluir o usuário \"{txtNome.Text}\"?", + "Confirmar exclusão", + MessageBoxButtons.YesNo, + MessageBoxIcon.Warning); + + if (confirm != DialogResult.Yes) return; + + try + { + // TODO: _usuarioBLL.Excluir(_usuarioAtualId); + MessageBox.Show("Usuário excluído com sucesso.", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao excluir:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnLocalizar() + { + // TODO: abrir formulário de busca e retornar o usuário selecionado + // Exemplo de como receber o retorno: + // var frm = new FormularioBuscarUsuario(); + // if (frm.ShowDialog() == DialogResult.OK) + // { + // var u = frm.UsuarioSelecionado; + // var perfilId = _usuarioBLL.ObterPerfilId(u.Id); + // CarregarPerfis(); + // PopularCampos(u, perfilId); + // AplicarModo(ModoFormulario.Visualizacao); + // } + + MessageBox.Show("Implemente o formulário de busca de usuários.", + "Localizar", MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + protected override void OnSalvar() + { + if (!Validar()) return; + + var perfil = (ComboItem)cmbPerfil.SelectedItem; + + try + { + if (_modo == ModoFormulario.Novo) + { + // TODO: chamar BLL para criar usuário e vincular perfil + // var novoUsuario = new ModeloUsuario + // { + // EmpresaId = SessaoAtual.EmpresaId, + // Nome = txtNome.Text.Trim(), + // Email = txtEmail.Text.Trim(), + // Usuario = txtUsuario.Text.Trim(), + // SenhaHash = HashHelper.GerarHash(txtSenha.Text), + // Ativo = chkAtivo.Checked, + // CriadoEm = DateTime.Now, + // AtualizadoEm = DateTime.Now + // }; + // int novoId = _usuarioBLL.Criar(novoUsuario); + // _usuarioBLL.VincularPerfil(novoId, perfil.Id); + + MessageBox.Show("Usuário criado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + else // Edicao + { + // TODO: chamar BLL para atualizar usuário e perfil + // var u = new ModeloUsuario { Id = _usuarioAtualId, ... }; + // if (!string.IsNullOrWhiteSpace(txtSenha.Text)) + // u.SenhaHash = HashHelper.GerarHash(txtSenha.Text); + // _usuarioBLL.Atualizar(u); + // _usuarioBLL.AtualizarPerfil(_usuarioAtualId, perfil.Id); + + MessageBox.Show("Usuário atualizado com sucesso!", "Sucesso", + MessageBoxButtons.OK, MessageBoxIcon.Information); + } + + AplicarModo(ModoFormulario.Visualizacao); + } + catch (Exception ex) + { + MessageBox.Show($"Erro ao salvar:\n{ex.Message}", "Erro", + MessageBoxButtons.OK, MessageBoxIcon.Error); + } + } + + protected override void OnCancelar() + { + if (_usuarioAtualId > 0) + { + // Volta para os dados que estavam antes + // TODO: recarregar do banco se necessário + } + LimparCampos(); + AplicarModo(ModoFormulario.Visualizacao); + } + + // ── CLASSE AUXILIAR PARA O COMBOBOX ────────────────────────────────── + private class ComboItem + { + public int Id { get; } + public string Nome { get; } + + public ComboItem(int id, string nome) + { + Id = id; + Nome = nome; + } + + public override string ToString() => Nome; + } + } +} \ No newline at end of file diff --git a/UI/Dashboards/Cadastros/UsuariosCadastroPanel.resx b/UI/Dashboards/Cadastros/UsuariosCadastroPanel.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/UI/Dashboards/Cadastros/UsuariosCadastroPanel.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/UI/Dashboards/Dashmain/MainForm.cs b/UI/Dashboards/Dashmain/MainForm.cs index 9dd8cc7..1cb99a7 100644 --- a/UI/Dashboards/Dashmain/MainForm.cs +++ b/UI/Dashboards/Dashmain/MainForm.cs @@ -26,6 +26,10 @@ namespace UI private readonly TransportadorasCadastroPanel _ptransportadorasCadastroPanel; private readonly ServicosCadastroPanel _pservicosCadastroPanel; + private readonly UsuariosCadastroPanel _pUsuarioCadastroPanel; + + private readonly ChamadoCadastroPanel _pChamadoCadastroPanel; + //Painel financeiro private readonly BoletoCadastroPanel _pboletoCadastroPanel; private readonly Panel _pOrdens; @@ -57,6 +61,8 @@ namespace UI _pfornecedoresCadastroPanel = new FornecedoresCadastroPanel { Dock = DockStyle.Fill, Visible = false }; _ptransportadorasCadastroPanel = new TransportadorasCadastroPanel { Dock = DockStyle.Fill, Visible = false }; _pservicosCadastroPanel = new ServicosCadastroPanel { Dock = DockStyle.Fill, Visible = false }; + _pUsuarioCadastroPanel = new UsuariosCadastroPanel { Dock = DockStyle.Fill, Visible=false }; + _pChamadoCadastroPanel = new ChamadoCadastroPanel { Dock = DockStyle.Fill, Visible = false }; _pOrdens = PlaceholderPanel("Ordens de Serviço", Color.FromArgb(22, 163, 74)); _pProdutos = PlaceholderPanel("Catálogo de Produtos", Color.FromArgb(217, 119, 6)); _pEstoque = PlaceholderPanel("Controle de Estoque", Color.FromArgb(234, 88, 12)); @@ -72,6 +78,8 @@ namespace UI mainContainer.Controls.Add(_pfornecedoresCadastroPanel); mainContainer.Controls.Add(_ptransportadorasCadastroPanel); mainContainer.Controls.Add(_pservicosCadastroPanel); + mainContainer.Controls.Add(_pUsuarioCadastroPanel); + mainContainer.Controls.Add(_pChamadoCadastroPanel); mainContainer.Controls.Add(_pEstoque); mainContainer.Controls.Add(_pProdutos); mainContainer.Controls.Add(_pOrdens); @@ -114,12 +122,12 @@ namespace UI case 104: ShowPanel(_ptransportadorasCadastroPanel); break; case 105: ShowPanel(_pservicosCadastroPanel); break; case 106: ShowPanel(_pEmpresa); break; - + case 107: ShowPanel(_pUsuarioCadastroPanel); break; case 202: ShowPanel(_pEmpresaConfig); break; case 300: ShowPanel(_pAgendaCadastro); break; case 301: ShowPanel(_pAgendaConsulta); break; - + case 309: ShowPanel(_pChamadoCadastroPanel); break; case 500: ShowPanel(_pboletoCadastroPanel); break; @@ -147,6 +155,8 @@ namespace UI _pfornecedoresCadastroPanel.Visible = (panelToShow == _pfornecedoresCadastroPanel); _ptransportadorasCadastroPanel.Visible = (panelToShow == _ptransportadorasCadastroPanel); _pservicosCadastroPanel.Visible = (panelToShow == _pservicosCadastroPanel); + _pUsuarioCadastroPanel.Visible = (panelToShow == _pUsuarioCadastroPanel); + _pChamadoCadastroPanel.Visible = (panelToShow == _pChamadoCadastroPanel); if (panelToShow.Visible) { panelToShow.BringToFront(); diff --git a/UI/Dashboards/Dashmain/SidebarControl.cs b/UI/Dashboards/Dashmain/SidebarControl.cs index 9bc837a..ffde523 100644 --- a/UI/Dashboards/Dashmain/SidebarControl.cs +++ b/UI/Dashboards/Dashmain/SidebarControl.cs @@ -11,10 +11,10 @@ namespace UI { public class SidebarControl : UserControl { - //Recebendo a conexao - string _cx = DadosDaConexao.ObterConexao(); + // ── Conexão ─────────────────────────────────────────────────────────── + string _cx = DadosDaConexao.ObterConexao(); - // ── Cores do Tema LevelOS ────────────────────────────────────────── + // ── Cores do Tema LevelOS ───────────────────────────────────────────── private static readonly Color NavyDark = Color.FromArgb(15, 30, 60); private static readonly Color NavyMid = Color.FromArgb(26, 45, 80); private static readonly Color AccentBlue = Color.FromArgb(37, 99, 235); @@ -22,12 +22,11 @@ namespace UI private static readonly Color TextMuted = Color.FromArgb(148, 163, 184); private static readonly Color Divider = Color.FromArgb(40, 255, 255, 255); - // ── Estado e Escalonamento (DPI) ─────────────────────────────────── + // ── Estado e Escalonamento (DPI) ────────────────────────────────────── private float _scale = 1.0f; private int _activeIndex = 0; private int _hoverIndex = -1; - // Propriedades Scaled (Ajustam-se ao monitor) private int ScaledWidth => (int)(220 * _scale); private int ScaledLogoH => (int)(55 * _scale); private int ScaledSectionH => (int)(32 * _scale); @@ -36,53 +35,59 @@ namespace UI private int ScaledFooterH => (int)(50 * _scale); private int ScaledIconSize => (int)(16 * _scale); - // ── Submenus ─────────────────────────────────────────────────────── - private ContextMenuStrip _subMenuBanco, _subMenuConfiguracao, - _subMenuAjuda, _subMenuOrdemServico, _subMenuFinanceiro,_subMenuCadastro, _subMenuAgenda; + // ── Submenus ────────────────────────────────────────────────────────── + private ContextMenuStrip _subMenuBanco = null!; + private ContextMenuStrip _subMenuConfiguracao = null!; + private ContextMenuStrip _subMenuAjuda = null!; + private ContextMenuStrip _subMenuOrdemServico = null!; + private ContextMenuStrip _subMenuFinanceiro = null!; + private ContextMenuStrip _subMenuCadastro = null!; + private ContextMenuStrip _subMenuAgenda = null!; - public string UserName = "Levelcode", UserFunction = "Administrador"; + public string UserName = "Levelcode"; + public string UserFunction = "Administrador"; public event EventHandler? NavItemClicked; private readonly List _items = new() { new NavItem("Dashboard", SvgIcon.Grid, "Principal", null), - new NavItem("Cadastro", SvgIcon.UserPlus, null, "3"), + new NavItem("Cadastro", SvgIcon.UserPlus, null, "3"), new NavItem("Ordens de Serviço", SvgIcon.FileText, null, "12"), new NavItem("Agenda", SvgIcon.Calendar, null, null), new NavItem("Produtos", SvgIcon.Package, "Gestão", null), new NavItem("Estoque", SvgIcon.Inventory, null, null), - //new NavItem("Serviços", SvgIcon.Briefcase, null, null), - //new NavItem("Transportadoras", SvgIcon.Truck, null, null), new NavItem("Financeiro", SvgIcon.DollarSign, null, null), new NavItem("Banco de Dados", SvgIcon.Database, "Sistema", null), new NavItem("Configurações", SvgIcon.Settings, null, null), new NavItem("Suporte Técnico", SvgIcon.Support, "Ajuda", null), }; + // ── Backup ──────────────────────────────────────────────────────────── public void backupFull(string conexao) { - var backupService = new DALLBackupService(conexao); - var resultadoFull = backupService.ExecutarBackupFull(); - - if (resultadoFull.Sucesso) - NT_MessageBox.Show($"✅ Backup FULL concluído em {resultadoFull.Duracao.TotalSeconds:F1}s","Backup do banco de dados",MessageBoxButtons.OK, MessageBoxIcon.Information); + var svc = new DALLBackupService(conexao); + var r = svc.ExecutarBackupFull(); + if (r.Sucesso) + NT_MessageBox.Show($"✅ Backup FULL concluído em {r.Duracao.TotalSeconds:F1}s", + "Backup do banco de dados", MessageBoxButtons.OK, MessageBoxIcon.Information); else - NT_MessageBox.Show($"❌ Erro no Backup FULL: {resultadoFull.Erro}","Erro ao tentar executar backup do sistema.",MessageBoxButtons.OK,MessageBoxIcon.Error); - }//Criar backup full + NT_MessageBox.Show($"❌ Erro no Backup FULL: {r.Erro}", + "Erro ao tentar executar backup do sistema.", MessageBoxButtons.OK, MessageBoxIcon.Error); + } public void backupDifrencial(string conexao) { - var backupService = new DALLBackupService(conexao); - var resultadoDiff = backupService.ExecutarBackupDiferencial(); - - if (resultadoDiff.Sucesso) - NT_MessageBox.Show($"✅ Backup DIFERENCIAL concluído em {resultadoDiff.Duracao.TotalSeconds:F1}s","Backup diferencial concluido", MessageBoxButtons.OK, MessageBoxIcon.Information); + var svc = new DALLBackupService(conexao); + var r = svc.ExecutarBackupDiferencial(); + if (r.Sucesso) + NT_MessageBox.Show($"✅ Backup DIFERENCIAL concluído em {r.Duracao.TotalSeconds:F1}s", + "Backup diferencial concluido", MessageBoxButtons.OK, MessageBoxIcon.Information); else - NT_MessageBox.Show($"❌ Erro no Backup DIFERENCIAL: {resultadoDiff.Erro}","Erro ao tentar executar backup diferencial no sistema", MessageBoxButtons.OK, MessageBoxIcon.Error); - }//Criar backup diferencial - - + NT_MessageBox.Show($"❌ Erro no Backup DIFERENCIAL: {r.Erro}", + "Erro ao tentar executar backup diferencial no sistema", MessageBoxButtons.OK, MessageBoxIcon.Error); + } + // ── Construtor ──────────────────────────────────────────────────────── public SidebarControl() { BackColor = NavyDark; @@ -98,106 +103,170 @@ namespace UI SetupSubMenus(); } + // ── Setup de Submenus ───────────────────────────────────────────────── private void SetupSubMenus() { - //Submenu Cadastro + // ── CADASTRO ────────────────────────────────────────────────────── _subMenuCadastro = CreateStyledMenu(); - _subMenuCadastro.Items.Add("👤 Clientes", null, (s, e) => {NavItemClicked?.Invoke(this, 99);}); - _subMenuCadastro.Items.Add("💻 Equipamentos", null, (s, e) => { NavItemClicked?.Invoke(this, 100); }); - _subMenuCadastro.Items.Add("📜 Contratos", null, (s, e) => { NavItemClicked?.Invoke(this, 101); }); - _subMenuCadastro.Items.Add("🏭 Fornecedores", null, (s, e) => { NavItemClicked?.Invoke(this, 102); }); - _subMenuCadastro.Items.Add("👔 Funcionários", null, (s, e) => { NavItemClicked?.Invoke(this, 103); }); - _subMenuCadastro.Items.Add("🚚 Transportadoras", null, (s, e) => { NavItemClicked?.Invoke(this, 104); }); - _subMenuCadastro.Items.Add("🛠️ Serviços", null, (s, e) => { NavItemClicked?.Invoke(this, 105); }); - _subMenuCadastro.Items.Add("🏢 Empresa", null, (s, e) => { NavItemClicked?.Invoke(this, 106); }); - _subMenuCadastro.Items.Add("🔑 Usuários do Sistema", null, (s, e) => { NavItemClicked?.Invoke(this, 107); }); + _subMenuCadastro.Items.Add(CreateItem("👤 Clientes", (s, e) => NavItemClicked?.Invoke(this, 99))); + _subMenuCadastro.Items.Add(CreateItem("💻 Equipamentos", (s, e) => NavItemClicked?.Invoke(this, 100))); + _subMenuCadastro.Items.Add(CreateItem("📜 Contratos", (s, e) => NavItemClicked?.Invoke(this, 101))); + _subMenuCadastro.Items.Add(CreateItem("🏭 Fornecedores", (s, e) => NavItemClicked?.Invoke(this, 102))); + // ── Funcionários com submenu aninhado ───────────────────────────── + var menuFuncionarios = CreateParentItem("👔 Funcionários"); + menuFuncionarios.DropDownItems.Add(CreateItem("➕ Novo funcionário", (s, e) => NavItemClicked?.Invoke(this, 103))); + menuFuncionarios.DropDownItems.Add(CreateItem("🔍 Consultar funcionários", (s, e) => NavItemClicked?.Invoke(this, 108))); + _subMenuCadastro.Items.Add(menuFuncionarios); + // ────────────────────────────────────────────────────────────────── + + _subMenuCadastro.Items.Add(CreateItem("🚚 Transportadoras", (s, e) => NavItemClicked?.Invoke(this, 104))); + _subMenuCadastro.Items.Add(CreateItem("🛠️ Serviços", (s, e) => NavItemClicked?.Invoke(this, 105))); + _subMenuCadastro.Items.Add(CreateItem("🏢 Empresa", (s, e) => NavItemClicked?.Invoke(this, 106))); + _subMenuCadastro.Items.Add(CreateItem("🔑 Usuários do Sistema", (s, e) => NavItemClicked?.Invoke(this, 107))); + + // ── BANCO DE DADOS ──────────────────────────────────────────────── _subMenuBanco = CreateStyledMenu(); - _subMenuBanco.Items.Add("⚙️ Configuração Database", null, (s, e) => showForms()); // Substitua pelo seu Form - _subMenuBanco.Items.Add("💾 Backup de Dados (FULL)", null, (s, e) => backupFull(this._cx)); - _subMenuBanco.Items.Add("⚡ Backup de Dados (DIFF)", null, (s, e) => backupDifrencial(this._cx)); - _subMenuBanco.Items.Add("🔄 Restaurar Banco"); + _subMenuBanco.Items.Add(CreateItem("⚙️ Configuração Database", (s, e) => showForms())); + _subMenuBanco.Items.Add(CreateItem("💾 Backup de Dados (FULL)", (s, e) => backupFull(_cx))); + _subMenuBanco.Items.Add(CreateItem("⚡ Backup de Dados (DIFF)", (s, e) => backupDifrencial(_cx))); + _subMenuBanco.Items.Add(CreateItem("🔄 Restaurar Banco")); - - //submenu Configurações + // ── CONFIGURAÇÕES ───────────────────────────────────────────────── _subMenuConfiguracao = CreateStyledMenu(); - _subMenuConfiguracao.Items.Add("🖼️ Personalização de OS"); - _subMenuConfiguracao.Items.Add("🖥️ Personalização de Sistema"); - _subMenuConfiguracao.Items.Add(" Configuração Empresa", null, (s, e) => { NavItemClicked?.Invoke(this, 202); }); + _subMenuConfiguracao.Items.Add(CreateItem("🖼️ Personalização de OS", (s, e) => NavItemClicked?.Invoke(this, 200))); + _subMenuConfiguracao.Items.Add(CreateItem("🖥️ Personalização de Sistema", (s, e) => NavItemClicked?.Invoke(this, 201))); + _subMenuConfiguracao.Items.Add(CreateItem(" Configuração Empresa", (s, e) => NavItemClicked?.Invoke(this, 202))); _subMenuConfiguracao.Items.Add(new ToolStripSeparator()); - _subMenuConfiguracao.Items.Add("📂 FTP-Cliente"); // Pasta para arquivos - _subMenuConfiguracao.Items.Add("💬 Telegram-Cliente"); // Balão de conversa - _subMenuConfiguracao.Items.Add("📩 SMTP-Cliente"); // Envelope de saída + _subMenuConfiguracao.Items.Add(CreateItem("📂 FTP-Cliente", (s, e) => NavItemClicked?.Invoke(this, 203))); + _subMenuConfiguracao.Items.Add(CreateItem("💬 Telegram-Cliente", (s, e) => NavItemClicked?.Invoke(this, 204))); + _subMenuConfiguracao.Items.Add(CreateItem("📩 SMTP-Cliente", (s, e) => NavItemClicked?.Invoke(this, 205))); _subMenuConfiguracao.Items.Add(new ToolStripSeparator()); - // Automação - _subMenuConfiguracao.Items.Add("⏰ Backups Automáticos"); // Relógio para agendamento - _subMenuConfiguracao.Items.Add("☁️ Backup em Nuvem"); - + _subMenuConfiguracao.Items.Add(CreateItem("⏰ Backups Automáticos", (s, e) => NavItemClicked?.Invoke(this, 206))); + _subMenuConfiguracao.Items.Add(CreateItem("☁️ Backup em Nuvem", (s, e) => NavItemClicked?.Invoke(this, 207))); + // ── AJUDA ───────────────────────────────────────────────────────── _subMenuAjuda = CreateStyledMenu(); - _subMenuAjuda.Items.Add("💬 Atendimento Online"); - _subMenuAjuda.Items.Add("📖 Manual do Sistema"); + _subMenuAjuda.Items.Add(CreateItem("💬 Atendimento Online")); + _subMenuAjuda.Items.Add(CreateItem("📖 Manual do Sistema")); + // ── ORDENS DE SERVIÇO ───────────────────────────────────────────── _subMenuOrdemServico = CreateStyledMenu(); + _subMenuOrdemServico.Items.Add(CreateItem("✚ Abrir nova O.S")); + _subMenuOrdemServico.Items.Add(CreateItem("✎ Alterar O.S")); + _subMenuOrdemServico.Items.Add(CreateItem("🔒 Encerrar O.S")); + _subMenuOrdemServico.Items.Add(CreateItem("🔍 Localizar O.S")); + _subMenuOrdemServico.Items.Add(CreateItem("📋 Orçamento de O.S")); + _subMenuOrdemServico.Items.Add(CreateItem("📜 Histórico de O.S")); + _subMenuOrdemServico.Items.Add(CreateItem("📊 Relatório de O.S")); + _subMenuOrdemServico.Items.Add(CreateItem("🖨 Imprimir")); + var item = CreateItem("⚠️ Chamado Técnico"); item.Click += (s, e) => NavItemClicked?.Invoke(this, 309); + _subMenuOrdemServico.Items.Add(item); + _subMenuOrdemServico.Items.Add(CreateItem("🌐 OS WEB")); + _subMenuOrdemServico.Items.Add(CreateItem("🔓 Reabrir OS")); - _subMenuOrdemServico.Items.Add("✚ Abrir nova O.S", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("✎ Alterar O.S", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("🔒 Encerrar O.S", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("🔍 Localizar O.S", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("📋 Orçamento de O.S", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("📜 Histórico de O.S", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("📊 Relatório de O.S", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("🖨 Imprimir", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("⚠️ Chamado Técnico", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("🌐 OS WEB", null, (s, e) => { /* Lógica */ }); - _subMenuOrdemServico.Items.Add("🔓 Reabrir OS", null, (s, e) => { /* Lógica */ }); - + // ── FINANCEIRO ──────────────────────────────────────────────────── _subMenuFinanceiro = CreateStyledMenu(); + _subMenuFinanceiro.Items.Add(CreateItem("💳 Contas")); + _subMenuFinanceiro.Items.Add(CreateItem("📈 Contas a receber")); + _subMenuFinanceiro.Items.Add(CreateItem("📉 Contas a pagar")); + _subMenuFinanceiro.Items.Add(CreateItem("📉 Boletos/Duplicatas", (s, e) => NavItemClicked?.Invoke(this, 500))); + _subMenuFinanceiro.Items.Add(new ToolStripSeparator()); + _subMenuFinanceiro.Items.Add(CreateItem("🛒 Compras")); + _subMenuFinanceiro.Items.Add(CreateItem("💰 Vendas")); + _subMenuFinanceiro.Items.Add(CreateItem("🧾 Notas Fiscais")); + _subMenuFinanceiro.Items.Add(new ToolStripSeparator()); + _subMenuFinanceiro.Items.Add(CreateItem("📂 Arquivo Contador")); + _subMenuFinanceiro.Items.Add(CreateItem("🏦 Dados Bancários")); + _subMenuFinanceiro.Items.Add(CreateItem("🕒 Histórico Financeiro")); - _subMenuFinanceiro.Items.Add("💳 Contas", null, (s, e) => { /* Lógica */ }); - _subMenuFinanceiro.Items.Add("📈 Contas a receber", null, (s, e) => { /* Lógica */ }); - _subMenuFinanceiro.Items.Add("📉 Contas a pagar", null, (s, e) => { /* Lógica */ }); - _subMenuFinanceiro.Items.Add("📉 Boletos/Duplicatas", null, (s, e) => { NavItemClicked?.Invoke(this, 500); }); - _subMenuFinanceiro.Items.Add(new ToolStripSeparator()); // Linha divisória - _subMenuFinanceiro.Items.Add("🛒 Compras", null, (s, e) => { /* Lógica */ }); - _subMenuFinanceiro.Items.Add("💰 Vendas", null, (s, e) => { /* Lógica */ }); - _subMenuFinanceiro.Items.Add("🧾 Notas Fiscais", null, (s, e) => { /* Lógica */ }); - _subMenuFinanceiro.Items.Add(new ToolStripSeparator()); // Linha divisória - _subMenuFinanceiro.Items.Add("📂 Arquivo Contador", null, (s, e) => { /* Lógica */ }); - _subMenuFinanceiro.Items.Add("🏦 Dados Bancários", null, (s, e) => { /* Lógica */ }); - _subMenuFinanceiro.Items.Add("🕒 Histórico Financeiro", null, (s, e) => { /* Lógica */ }); - - - // private ContextMenuStrip _subMenuAgenda; + // ── AGENDA ──────────────────────────────────────────────────────── _subMenuAgenda = CreateStyledMenu(); - //_subMenuAgenda.Items.Add("➕ Novo compromisso", null, (s, e) => {showForms();}); - _subMenuAgenda.Items.Add("➕ Novo compromisso", null, (s, e) => { NavItemClicked?.Invoke(this, 300); }); - _subMenuAgenda.Items.Add("🔍 Consultar compromissos", null, (s, e) => { NavItemClicked?.Invoke(this, 301); }); - _subMenuAgenda.Items.Add("✏️ Alterar compromisso", null, (s, e) => { /* Lógica de edição */ }); - _subMenuAgenda.Items.Add("🖨️ Imprimir", null, (s, e) => { /* Lógica de relatório */ }); + _subMenuAgenda.Items.Add(CreateItem("➕ Novo compromisso", (s, e) => NavItemClicked?.Invoke(this, 300))); + _subMenuAgenda.Items.Add(CreateItem("🔍 Consultar compromissos", (s, e) => NavItemClicked?.Invoke(this, 301))); + _subMenuAgenda.Items.Add(CreateItem("✏️ Alterar compromisso")); + _subMenuAgenda.Items.Add(CreateItem("🖨️ Imprimir")); + } + + // ── Helpers de criação de itens ─────────────────────────────────────── + + /// Cria um ToolStripMenuItem simples com estilo aplicado. + private ToolStripMenuItem CreateItem(string text, EventHandler? onClick = null) + { + var item = new ToolStripMenuItem(text) + { + BackColor = NavyMid, + ForeColor = TextLight, + Font = new Font("Segoe UI", 10f * _scale) + }; + if (onClick != null) item.Click += onClick; + return item; + } + + /// + /// Cria um ToolStripMenuItem pai (com submenu aninhado). + /// O estilo é aplicado aqui e também propagado para os filhos + /// via evento DropDownOpening. + /// + private ToolStripMenuItem CreateParentItem(string text) + { + var item = new ToolStripMenuItem(text) + { + BackColor = NavyMid, + ForeColor = TextLight, + Font = new Font("Segoe UI", 10f * _scale) + }; + + // Garante estilo no dropdown aninhado quando abrir + item.DropDown.BackColor = NavyMid; + item.DropDown.ForeColor = TextLight; + item.DropDown.Renderer = new DarkMenuRenderer(); + (item.DropDown as ToolStripDropDownMenu)!.ShowImageMargin = false; + RemoverImageMargin(item.DropDown); + + return item; + } + + // ── Factories de menu e form ────────────────────────────────────────── + /// + /// Remove fisicamente a reserva de espaco da margem de icones via reflection. + /// ShowImageMargin = false esconde visualmente mas o .NET ainda reserva o espaco + /// internamente — esse metodo zera o campo privado que controla a largura real. + /// + private static void RemoverImageMargin(ToolStrip menu) + { + try + { + var field = typeof(ToolStripDropDownMenu) + .GetField("imageMarginWidth", + System.Reflection.BindingFlags.NonPublic | + System.Reflection.BindingFlags.Instance); + field?.SetValue(menu, 0); + } + catch { /* silencia */ } } private ContextMenuStrip CreateStyledMenu() { - return new ContextMenuStrip + var menu = new ContextMenuStrip { BackColor = NavyMid, ForeColor = TextLight, ShowImageMargin = false, Font = new Font("Segoe UI", 10f * _scale), - Renderer = new ToolStripProfessionalRenderer(new SubMenuColorTable()) + Renderer = new DarkMenuRenderer() }; + RemoverImageMargin(menu); + return menu; } private void showForms() where T : Form, new() { - using (T form = new T()) - { - form.StartPosition = FormStartPosition.CenterScreen; - form.ShowDialog(); - } + using var form = new T(); + form.StartPosition = FormStartPosition.CenterScreen; + form.ShowDialog(); } - //Abrir agenda - // AgendaForm.cs + + // ── Agenda Form ─────────────────────────────────────────────────────── public class AgendaForm : Form { public AgendaForm() @@ -206,12 +275,11 @@ namespace UI Size = new Size(1150, 780); StartPosition = FormStartPosition.CenterScreen; BackColor = Color.White; - - var panel = new AgendaCadastroPanel(); - Controls.Add(panel); + Controls.Add(new AgendaCadastroPanel()); } - }//abrir agenda de compromissos + } + // ── Paint ───────────────────────────────────────────────────────────── protected override void OnPaint(PaintEventArgs e) { var g = e.Graphics; @@ -233,10 +301,13 @@ namespace UI for (int i = 0; i < _items.Count; i++) { var item = _items[i]; + if (item.Section != null) { y += (int)(10 * _scale); - g.DrawString(item.Section.ToUpper(), fSection, new SolidBrush(Color.FromArgb(120, TextMuted)), ScaledItemPadX + (int)(8 * _scale), y); + g.DrawString(item.Section.ToUpper(), fSection, + new SolidBrush(Color.FromArgb(120, TextMuted)), + ScaledItemPadX + (int)(8 * _scale), y); y += ScaledSectionH; } @@ -248,44 +319,55 @@ namespace UI else if (isHover) FillRoundRect(g, new SolidBrush(Color.FromArgb(20, 255, 255, 255)), itemRect, (int)(6 * _scale)); var color = isActive ? TextLight : Color.FromArgb(200, TextLight); - DrawIcon(g, item.Icon, ScaledItemPadX + (int)(10 * _scale), y + (ScaledItemH - ScaledIconSize) / 2, ScaledIconSize, color); - g.DrawString(item.Label, isActive ? fItemSel : fItem, new SolidBrush(color), ScaledItemPadX + (int)(36 * _scale), y + (ScaledItemH - (int)(16 * _scale)) / 2); + DrawIcon(g, item.Icon, + ScaledItemPadX + (int)(10 * _scale), + y + (ScaledItemH - ScaledIconSize) / 2, + ScaledIconSize, color); + g.DrawString(item.Label, isActive ? fItemSel : fItem, + new SolidBrush(color), + ScaledItemPadX + (int)(36 * _scale), + y + (ScaledItemH - (int)(16 * _scale)) / 2); if (HasSubMenu(item.Label)) - g.DrawString("›", fItem, new SolidBrush(Color.FromArgb(100, TextLight)), Width - (int)(30 * _scale), y + (ScaledItemH - (int)(18 * _scale)) / 2); + g.DrawString("›", fItem, + new SolidBrush(Color.FromArgb(100, TextLight)), + Width - (int)(30 * _scale), + y + (ScaledItemH - (int)(18 * _scale)) / 2); y += ScaledItemH + (int)(2 * _scale); } } - // Adicione "Cadastro" na verificação private bool HasSubMenu(string label) => - label == "Cadastro" || // <-- Adicionado aqui + label == "Cadastro" || label == "Banco de Dados" || label == "Financeiro" || label == "Ordens de Serviço" || label == "Configurações" || label == "Suporte Técnico" || - label == "Agenda" - ; + label == "Agenda"; protected override void OnMouseClick(MouseEventArgs e) { int hit = HitTest(e.Y); - if (hit >= 0) - { - _activeIndex = hit; Invalidate(); - string label = _items[hit].Label; - Point menuPos = new Point(Width + 2, e.Y - (int)(15 * _scale)); + if (hit < 0) return; - if (label == "Banco de Dados") _subMenuBanco.Show(this, menuPos); - else if (label == "Financeiro") _subMenuFinanceiro.Show(this, menuPos); - else if(label == "Agenda") _subMenuAgenda.Show(this, menuPos); - else if (label == "Ordens de Serviço") _subMenuOrdemServico.Show(this, menuPos); - else if (label == "Configurações") _subMenuConfiguracao.Show(this, menuPos); - else if (label == "Suporte Técnico") _subMenuAjuda.Show(this, menuPos); - else if (label == "Cadastro") _subMenuCadastro.Show(this, menuPos); - else NavItemClicked?.Invoke(this, hit); + _activeIndex = hit; + Invalidate(); + + string label = _items[hit].Label; + Point menuPos = new Point(Width + 2, e.Y - (int)(15 * _scale)); + + switch (label) + { + case "Cadastro": _subMenuCadastro.Show(this, menuPos); break; + case "Banco de Dados": _subMenuBanco.Show(this, menuPos); break; + case "Financeiro": _subMenuFinanceiro.Show(this, menuPos); break; + case "Agenda": _subMenuAgenda.Show(this, menuPos); break; + case "Ordens de Serviço": _subMenuOrdemServico.Show(this, menuPos); break; + case "Configurações": _subMenuConfiguracao.Show(this, menuPos); break; + case "Suporte Técnico": _subMenuAjuda.Show(this, menuPos); break; + default: NavItemClicked?.Invoke(this, hit); break; } } @@ -301,9 +383,15 @@ namespace UI return -1; } - protected override void OnMouseMove(MouseEventArgs e) { int hit = HitTest(e.Y); if (hit != _hoverIndex) { _hoverIndex = hit; Invalidate(); } } + protected override void OnMouseMove(MouseEventArgs e) + { + int hit = HitTest(e.Y); + if (hit != _hoverIndex) { _hoverIndex = hit; Invalidate(); } + } + protected override void OnMouseLeave(EventArgs e) { _hoverIndex = -1; Invalidate(); } + // ── Logo e Footer ───────────────────────────────────────────────────── private void DrawLogo(Graphics g) { var iconRect = new Rectangle((int)(16 * _scale), (int)(18 * _scale), (int)(34 * _scale), (int)(34 * _scale)); @@ -326,38 +414,48 @@ namespace UI g.DrawString(UserFunction, new Font("Segoe UI", 9f * _scale), new SolidBrush(TextMuted), 57 * _scale, fy + (30 * _scale)); } - // ── MOTOR DE ÍCONES COMPLETO (GDI+) ──────────────────────────────── + // ── Motor de Ícones (GDI+) ──────────────────────────────────────────── private void DrawIcon(Graphics g, SvgIcon icon, int x, int y, int size, Color color) { using var p = new Pen(color, 1.6f * _scale) { StartCap = LineCap.Round, EndCap = LineCap.Round, LineJoin = LineJoin.Round }; float s = size / 24f; - g.TranslateTransform(x, y); g.ScaleTransform(s, s); + g.TranslateTransform(x, y); + g.ScaleTransform(s, s); switch (icon) { case SvgIcon.Grid: - g.DrawRectangle(p, 3, 3, 7, 7); g.DrawRectangle(p, 14, 3, 7, 7); g.DrawRectangle(p, 3, 14, 7, 7); g.DrawRectangle(p, 14, 14, 7, 7); break; + g.DrawRectangle(p, 3, 3, 7, 7); g.DrawRectangle(p, 14, 3, 7, 7); + g.DrawRectangle(p, 3, 14, 7, 7); g.DrawRectangle(p, 14, 14, 7, 7); break; case SvgIcon.Users: - g.DrawEllipse(p, 5, 3, 8, 8); g.DrawArc(p, 2, 13, 14, 8, 180, 180); g.DrawArc(p, 15, 8, 6, 6, 270, 180); break; + g.DrawEllipse(p, 5, 3, 8, 8); g.DrawArc(p, 2, 13, 14, 8, 180, 180); + g.DrawArc(p, 15, 8, 6, 6, 270, 180); break; case SvgIcon.FileText: - g.DrawLines(p, new PointF[] { new(6, 2), new(6, 22), new(18, 22), new(18, 8), new(14, 2), new(6, 2) }); g.DrawLine(p, 14, 2, 14, 8); g.DrawLine(p, 14, 8, 18, 8); break; + g.DrawLines(p, new PointF[] { new(6, 2), new(6, 22), new(18, 22), new(18, 8), new(14, 2), new(6, 2) }); + g.DrawLine(p, 14, 2, 14, 8); g.DrawLine(p, 14, 8, 18, 8); break; case SvgIcon.Package: - g.DrawLines(p, new PointF[] { new(12, 2), new(2, 7), new(12, 12), new(22, 7), new(12, 2) }); g.DrawLine(p, 2, 7, 2, 17); g.DrawLine(p, 22, 7, 22, 17); g.DrawLine(p, 12, 12, 12, 22); break; + g.DrawLines(p, new PointF[] { new(12, 2), new(2, 7), new(12, 12), new(22, 7), new(12, 2) }); + g.DrawLine(p, 2, 7, 2, 17); g.DrawLine(p, 22, 7, 22, 17); g.DrawLine(p, 12, 12, 12, 22); break; case SvgIcon.DollarSign: g.DrawLine(p, 12, 2, 12, 22); g.DrawArc(p, 7, 5, 10, 7, 110, 250); g.DrawArc(p, 7, 12, 10, 7, 270, 250); break; case SvgIcon.Database: - g.DrawEllipse(p, 4, 3, 16, 6); g.DrawLine(p, 4, 6, 4, 18); g.DrawLine(p, 20, 6, 20, 18); g.DrawArc(p, 4, 15, 16, 6, 0, 180); break; + g.DrawEllipse(p, 4, 3, 16, 6); g.DrawLine(p, 4, 6, 4, 18); + g.DrawLine(p, 20, 6, 20, 18); g.DrawArc(p, 4, 15, 16, 6, 0, 180); break; case SvgIcon.Calendar: - g.DrawRectangle(p, 3, 4, 18, 17); g.DrawLine(p, 3, 9, 21, 9); g.DrawLine(p, 8, 2, 8, 6); g.DrawLine(p, 16, 2, 16, 6); break; + g.DrawRectangle(p, 3, 4, 18, 17); g.DrawLine(p, 3, 9, 21, 9); + g.DrawLine(p, 8, 2, 8, 6); g.DrawLine(p, 16, 2, 16, 6); break; case SvgIcon.Truck: - g.DrawRectangle(p, 1, 5, 13, 11); g.DrawLines(p, new PointF[] { new(14, 16), new(14, 8), new(19, 8), new(23, 12), new(23, 16) }); + g.DrawRectangle(p, 1, 5, 13, 11); + g.DrawLines(p, new PointF[] { new(14, 16), new(14, 8), new(19, 8), new(23, 12), new(23, 16) }); g.DrawEllipse(p, 3, 15, 4, 4); g.DrawEllipse(p, 17, 15, 4, 4); break; case SvgIcon.Factory: - g.DrawRectangle(p, 2, 10, 20, 11); g.DrawLines(p, new PointF[] { new(2, 10), new(2, 5), new(8, 10), new(8, 5), new(14, 10) }); break; + g.DrawRectangle(p, 2, 10, 20, 11); + g.DrawLines(p, new PointF[] { new(2, 10), new(2, 5), new(8, 10), new(8, 5), new(14, 10) }); break; case SvgIcon.Briefcase: g.DrawRectangle(p, 3, 7, 18, 13); g.DrawArc(p, 9, 3, 6, 8, 180, 180); break; case SvgIcon.Support: - g.DrawArc(p, 4, 4, 16, 16, 180, 180); g.DrawRectangle(p, 3, 13, 3, 5); g.DrawRectangle(p, 18, 13, 3, 5); break; + g.DrawArc(p, 4, 4, 16, 16, 180, 180); + g.DrawRectangle(p, 3, 13, 3, 5); g.DrawRectangle(p, 18, 13, 3, 5); break; case SvgIcon.Inventory: g.DrawRectangle(p, 3, 3, 18, 8); g.DrawRectangle(p, 3, 13, 18, 8); break; case SvgIcon.Settings: @@ -365,43 +463,51 @@ namespace UI for (int a = 0; a < 360; a += 45) { float r = a * (float)Math.PI / 180f; - g.DrawLine(p, 12 + (float)Math.Cos(r) * 8, 12 + (float)Math.Sin(r) * 8, 12 + (float)Math.Cos(r) * 11, 12 + (float)Math.Sin(r) * 11); + g.DrawLine(p, 12 + (float)Math.Cos(r) * 8, 12 + (float)Math.Sin(r) * 8, + 12 + (float)Math.Cos(r) * 11, 12 + (float)Math.Sin(r) * 11); } break; - case SvgIcon.User: g.DrawEllipse(p, 8, 2, 8, 8); g.DrawArc(p, 3, 14, 18, 8, 180, 180); break; - case SvgIcon.UserCheck: g.DrawEllipse(p, 8, 3, 8, 8); g.DrawArc(p, 3, 14, 18, 8, 180, 180); g.DrawRectangle(p, 10, 15, 4, 3); break; + case SvgIcon.User: + g.DrawEllipse(p, 8, 2, 8, 8); g.DrawArc(p, 3, 14, 18, 8, 180, 180); break; + case SvgIcon.UserCheck: + g.DrawEllipse(p, 8, 3, 8, 8); g.DrawArc(p, 3, 14, 18, 8, 180, 180); + g.DrawRectangle(p, 10, 15, 4, 3); break; case SvgIcon.UserPlus: - // Desenha o corpo do usuário (círculo e arco) - g.DrawEllipse(p, 4, 4, 8, 8); // Cabeça - g.DrawArc(p, 1, 14, 14, 8, 180, 180); // Ombros - - // Desenha o sinal de "+" ao lado - // Vertical + g.DrawEllipse(p, 4, 4, 8, 8); + g.DrawArc(p, 1, 14, 14, 8, 180, 180); g.DrawLine(p, 19, 7, 19, 15); - // Horizontal - g.DrawLine(p, 15, 11, 23, 11); - break; - - + g.DrawLine(p, 15, 11, 23, 11); break; } + g.ResetTransform(); } - // ── Helpers ── - private static void FillRoundRect(Graphics g, Brush b, Rectangle r, int rad) { using var path = RoundRectPath(r, rad); g.FillPath(b, path); } + // ── Helpers visuais ─────────────────────────────────────────────────── + private static void FillRoundRect(Graphics g, Brush b, Rectangle r, int rad) + { + using var path = RoundRectPath(r, rad); + g.FillPath(b, path); + } + private static GraphicsPath RoundRectPath(Rectangle r, int rad) { - var path = new GraphicsPath(); int d = Math.Max(rad * 2, 1); - path.AddArc(r.X, r.Y, d, d, 180, 90); path.AddArc(r.Right - d, r.Y, d, d, 270, 90); - path.AddArc(r.Right - d, r.Bottom - d, d, d, 0, 90); path.AddArc(r.X, r.Bottom - d, d, d, 90, 90); - path.CloseFigure(); return path; + var path = new GraphicsPath(); + int d = Math.Max(rad * 2, 1); + path.AddArc(r.X, r.Y, d, d, 180, 90); + path.AddArc(r.Right - d, r.Y, d, d, 270, 90); + path.AddArc(r.Right - d, r.Bottom - d, d, d, 0, 90); + path.AddArc(r.X, r.Bottom - d, d, d, 90, 90); + path.CloseFigure(); + return path; } + private static void DrawCenteredString(Graphics g, string t, Font f, Color c, Rectangle r) { var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; g.DrawString(t, f, new SolidBrush(c), r, sf); } + // ── Classes internas ────────────────────────────────────────────────── private class NavItem { public string Label { get; } @@ -410,6 +516,7 @@ namespace UI public string? Badge { get; } public NavItem(string l, SvgIcon i, string? s, string? b) { Label = l; Icon = i; Section = s; Badge = b; } } + private class SubMenuColorTable : ProfessionalColorTable { public override Color ToolStripDropDownBackground => NavyMid; @@ -417,8 +524,51 @@ namespace UI public override Color MenuItemBorder => Color.Transparent; public override Color MenuItemSelectedGradientBegin => AccentBlue; public override Color MenuItemSelectedGradientEnd => AccentBlue; + public override Color ImageMarginGradientBegin => NavyMid; + public override Color ImageMarginGradientMiddle => NavyMid; + public override Color ImageMarginGradientEnd => NavyMid; + } + + /// + /// Renderer que elimina a faixa branca da margem de ícones + /// sobrescrevendo o desenho do ImageMargin para pintar com NavyMid. + /// + private class DarkMenuRenderer : ToolStripProfessionalRenderer + { + public DarkMenuRenderer() : base(new SubMenuColorTable()) { } + + protected override void OnRenderImageMargin(ToolStripRenderEventArgs e) + { + using var brush = new SolidBrush(NavyMid); + e.Graphics.FillRectangle(brush, e.AffectedBounds); + } + + protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e) + { + if (!e.Item.Selected) + { + using var brush = new SolidBrush(NavyMid); + e.Graphics.FillRectangle(brush, new Rectangle(Point.Empty, e.Item.Size)); + } + else + { + using var brush = new SolidBrush(AccentBlue); + e.Graphics.FillRectangle(brush, new Rectangle(Point.Empty, e.Item.Size)); + } + } + + protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e) + { + using var brush = new SolidBrush(NavyMid); + e.Graphics.FillRectangle(brush, e.AffectedBounds); + } } } - public enum SvgIcon { Grid, Users, FileText, Package, DollarSign, User, Settings, Database, Truck, Factory, UserCheck, Briefcase, Support, Inventory, Wallet, ShoppingCart, ShoppingBag, Calendar , UserPlus} -} \ No newline at end of file + public enum SvgIcon + { + Grid, Users, FileText, Package, DollarSign, User, Settings, + Database, Truck, Factory, UserCheck, Briefcase, Support, + Inventory, Wallet, ShoppingCart, ShoppingBag, Calendar, UserPlus + } +} diff --git a/UI/UI.csproj b/UI/UI.csproj index d6968f4..9e39068 100644 --- a/UI/UI.csproj +++ b/UI/UI.csproj @@ -25,4 +25,8 @@ + + + + \ No newline at end of file