using CPM; using MLL; using System; using System.Drawing; using System.Windows.Forms; namespace UI { public partial class OrdensCadastroPanel : UserControl { //Variaveis auxiliares private string nomeCliente = "Nicolas Felipe G. dos santos"; // ── CORES ────────────────────────────────────────────────────────────── private readonly Color CorPreta = Color.FromArgb(20, 20, 20); private readonly Color CorVerde = Color.FromArgb(22, 163, 74); private readonly Color CorVerdeHover = Color.FromArgb(16, 120, 55); private readonly Color CorVermelha = Color.FromArgb(220, 38, 38); private readonly Color CorVermelhaHov = Color.FromArgb(170, 20, 20); private readonly Color CorAzul = Color.FromArgb(37, 99, 235); private readonly Color CorCinzaClaro = Color.FromArgb(245, 245, 245); private readonly Color CorCinzaBorda = Color.FromArgb(200, 200, 200); private readonly Color CorTexto = Color.FromArgb(30, 41, 59); private readonly Color CorFocoBorda = Color.FromArgb(37, 99, 235); private readonly Color CorLaranja = Color.FromArgb(253, 186, 116); private readonly Color CorBranca = Color.FromArgb(255, 255, 255); // ── CAMPOS ───────────────────────────────────────────────────────────── private Label lblNumOS; private Label lblCliente; private Label lblEndereco; private Label lblTelefone; private Label lblCodVal; private DateTimePicker dtpEntrada; private DateTimePicker dtpPronto; private DateTimePicker dtpSaida; private ComboBox cmbSituacao; private Label lblGarantia; private LV_TEXTBOX1 txtAdiantamento; private Label lblVMao; private Label lblVPecas; private Label lblVDesloca; private Label lblVTerceiro; private Label lblVOutros; private Label lblVTotal; private LV_TEXTBOX1 txtModelo; private LV_TEXTBOX1 txtMarca; private LV_TEXTBOX1 txtOperadora; private LV_TEXTBOX1 txtSerial; private LV_TEXTBOX1 txtPatrimonio; private TextBox txtAcessorios; private TextBox txtDefeito; private TextBox txtObsAparelho; private DataGridView dgvServicos; private DataGridView dgvPecas; private TextBox txtLaudo; private TextBox txtObsServico; private ComboBox cmbTecnico; private ComboBox cmbPrioridade; private TabControl tabs; private ModeloOrdens _os; public event Action? OnVoltar; // ══════════════════════════════════════════════════════════════════════ // CONSTRUTOR // ══════════════════════════════════════════════════════════════════════ public OrdensCadastroPanel() { _os = new ModeloOrdens(); this.Dock = DockStyle.Fill; this.BackColor = Color.White; MontarInterface(); } private void InitializeComponent() { } public void CarregarOS(ModeloOrdens os) { _os = os; PreencherCampos(); } // ══════════════════════════════════════════════════════════════════════ // MONTAGEM PRINCIPAL // ══════════════════════════════════════════════════════════════════════ private void MontarInterface() { // Usamos posicionamento manual com Anchor/Dock + eventos Resize // para controle preciso igual ao print. // 1) HEADER (topo fixo, 56px) var pnlHeader = CriarHeader(); pnlHeader.Dock = DockStyle.Top; pnlHeader.Height = 56; // 2) RODAPÉ (base fixa, 46px) var pnlRodape = CriarRodape(); pnlRodape.Dock = DockStyle.Bottom; pnlRodape.Height = 46; // 3) ÁREA CENTRAL (Fill) — contém cliente + meio + abas var pnlCentral = new Panel { Dock = DockStyle.Fill, BackColor = Color.White }; // 3a) PAINEL CLIENTE (topo da área central, 72px) var pnlCliente = CriarPainelCliente(); pnlCliente.Dock = DockStyle.Top; pnlCliente.Height = 72; // 3b) PAINEL MEIO (datas + situação + financeiro, 115px) var pnlMeio = CriarPainelMeio(); pnlMeio.Dock = DockStyle.Top; pnlMeio.Height = 115; // 3c) ABAS (Fill restante) var tabCtrl = CriarAbas(); // Adiciona em ordem inversa (DockStyle.Top empilha de cima pra baixo) pnlCentral.Controls.Add(tabCtrl); // Fill — vai primeiro pnlCentral.Controls.Add(pnlMeio); // Top pnlCentral.Controls.Add(pnlCliente); // Top // Adiciona ao UserControl this.Controls.Add(pnlCentral); this.Controls.Add(pnlRodape); this.Controls.Add(pnlHeader); } // ══════════════════════════════════════════════════════════════════════ // HEADER // ══════════════════════════════════════════════════════════════════════ private Panel CriarHeader() { var pnl = new Panel { BackColor = CorPreta }; lblNumOS = new Label { Text = "O.S. nº —", Font = new Font("Segoe UI", 18f, FontStyle.Bold), ForeColor = CorVermelha, Location = new Point(16, 10), AutoSize = true }; pnl.Controls.Add(lblNumOS); var btnGravar = LvBtn("✔ Gravar OS", CorVerde, CorVerdeHover, CorVerdeHover, 130, 36, br: 6); var btnCancelar = LvBtn("✖ Cancelar", CorVermelha, CorVermelhaHov, CorVermelhaHov, 120, 36, br: 6); btnGravar.Click += (s, e) => Salvar(); btnCancelar.Click += (s, e) => OnVoltar?.Invoke(); pnl.Resize += (s, e) => { btnCancelar.Location = new Point(pnl.Width - 128, 10); btnGravar.Location = new Point(pnl.Width - 266, 10); }; pnl.Controls.Add(btnGravar); pnl.Controls.Add(btnCancelar); return pnl; } // ══════════════════════════════════════════════════════════════════════ // PAINEL CLIENTE // ══════════════════════════════════════════════════════════════════════ private Panel CriarPainelCliente() { var pnl = new Panel { BackColor = Color.White, Padding = new Padding(10, 6, 10, 4) }; pnl.Paint += (s, e) => { // Linha inferior separadora using var pen = new Pen(CorCinzaBorda); e.Graphics.DrawLine(pen, 0, pnl.Height - 1, pnl.Width, pnl.Height - 1); }; // Linha 1 — "Cliente:" + nome pnl.Controls.Add(Lbl("Cliente:", 10, 6, 60, bold: true, fs: 9f)); lblCliente = new Label { ////Text = "—", Text = this.nomeCliente, Font = new Font("Segoe UI", 9.5f, FontStyle.Bold), ForeColor = CorTexto, Location = new Point(72, 6), AutoSize = true }; pnl.Controls.Add(lblCliente); // "Cod.:" ancorado à direita var lblRotCod = Lbl("Cod.:", 0, 6, 36, fs: 8.5f); lblCodVal = Lbl("—", 0, 6, 60, fs: 8.5f); lblRotCod.Anchor = AnchorStyles.Top | AnchorStyles.Right; lblCodVal.Anchor = AnchorStyles.Top | AnchorStyles.Right; pnl.Resize += (s, e) => { lblRotCod.Location = new Point(pnl.Width - 98, 6); lblCodVal.Location = new Point(pnl.Width - 60, 6); }; pnl.Controls.Add(lblRotCod); pnl.Controls.Add(lblCodVal); // Linha 2 — Endereço pnl.Controls.Add(Lbl("Endereço:", 10, 28, 68, bold: true, fs: 8.5f)); lblEndereco = new Label { Text = "—", Font = new Font("Segoe UI", 8.5f), ForeColor = CorAzul, Location = new Point(80, 28), AutoSize = true }; pnl.Controls.Add(lblEndereco); // Linha 3 — Telefones pnl.Controls.Add(Lbl("Telefones:", 10, 50, 70, bold: true, fs: 8.5f)); lblTelefone = new Label { Text = "—", Font = new Font("Segoe UI", 8.5f), ForeColor = CorAzul, Location = new Point(82, 50), AutoSize = true }; pnl.Controls.Add(lblTelefone); return pnl; } // ══════════════════════════════════════════════════════════════════════ // PAINEL MEIO — datas à esquerda | financeiro à direita // ══════════════════════════════════════════════════════════════════════ private Panel CriarPainelMeio() { var pnl = new Panel { BackColor = Color.White }; pnl.Paint += (s, e) => { using var pen = new Pen(CorCinzaBorda); e.Graphics.DrawLine(pen, 0, pnl.Height - 1, pnl.Width, pnl.Height - 1); }; // ── FINANCEIRO (direita, largura fixa 270) ───────────────────────── var pnlFin = CriarPainelFinanceiro(); pnlFin.Anchor = AnchorStyles.Top | AnchorStyles.Right | AnchorStyles.Bottom; pnl.Resize += (s, e) => { pnlFin.Location = new Point(pnl.Width - 272, 0); pnlFin.Size = new Size(272, pnl.Height); }; pnl.Controls.Add(pnlFin); // ── DATAS + SITUAÇÃO (esquerda) ──────────────────────────────────── int lx = 10, lw = 62, tw = 148, th = 22; // Entrada pnl.Controls.Add(Lbl("Entrada", lx, 12, lw, bold: true)); dtpEntrada = DTP(pnl, lx + lw, 10, tw, th); // Pronto pnl.Controls.Add(Lbl("Pronto", lx, 38, lw, bold: true)); dtpPronto = DTP(pnl, lx + lw, 36, tw, th); // Saída pnl.Controls.Add(Lbl("Saída", lx, 64, lw, bold: true)); dtpSaida = DTP(pnl, lx + lw, 62, tw, th); // Situação da OS int sx = 240; pnl.Controls.Add(Lbl("Situação da OS", sx, 4, 130, bold: true)); cmbSituacao = new ComboBox { Location = new Point(sx, 22), Size = new Size(220, 26), DropDownStyle = ComboBoxStyle.DropDownList, Font = new Font("Segoe UI", 9f), FlatStyle = FlatStyle.Flat }; cmbSituacao.Items.AddRange(new object[] { "Aguardando avaliação do técnico", "Em Orçamento", "Orçamento Aprovado", "Em Reparo", "Pronto", "Entregue", "Cancelado" }); cmbSituacao.SelectedIndex = 0; pnl.Controls.Add(cmbSituacao); // Garantia até lblGarantia = new Label { Text = "Garantia até —", Font = new Font("Segoe UI", 9f, FontStyle.Bold), ForeColor = CorVermelha, Location = new Point(sx, 54), AutoSize = true }; pnl.Controls.Add(lblGarantia); // Botão Histórico var btnHist = LvBtn("Histórico", CorCinzaClaro, Color.FromArgb(180, 180, 180), Color.FromArgb(150, 150, 150), 88, 24, br: 4, bs: 1, bc: CorCinzaBorda); btnHist.ForeColor = CorTexto; btnHist.Location = new Point(sx, 80); pnl.Controls.Add(btnHist); return pnl; } // ── PAINEL FINANCEIRO ────────────────────────────────────────────────── private Panel CriarPainelFinanceiro() { var pnl = new Panel { BackColor = Color.White }; pnl.Paint += (s, e) => { using var pen = new Pen(CorCinzaBorda); e.Graphics.DrawLine(pen, 0, 0, 0, pnl.Height); // borda esquerda }; int lx = 10, vx = 160, vw = 100, rh = 17; int[] yy = { 4, 22, 40, 58, 76, 94 }; // Adiantamento pnl.Controls.Add(Lbl("Adiantamento", lx, yy[0] + 1, 110)); txtAdiantamento = new LV_TEXTBOX1 { Location = new Point(vx, yy[0]), Size = new Size(vw, 20), BorderColor = CorCinzaBorda, BorderFocusColor = CorFocoBorda, BorderSize = 2, Text = "0,00" }; pnl.Controls.Add(txtAdiantamento); // Valores somente leitura lblVMao = LblV(pnl, "Mão-de-obra", lx, yy[1], vx, vw, rh); lblVPecas = LblV(pnl, "Peças", lx, yy[2], vx, vw, rh); lblVDesloca = LblV(pnl, "Deslocamento", lx, yy[3], vx, vw, rh); lblVTerceiro = LblV(pnl, "Serviço terceiros", lx, yy[4], vx, vw, rh); lblVOutros = LblV(pnl, "Outros", lx, yy[5], vx, vw, rh); // Botão <> var btnGar = LvBtn("<>", CorVermelha, CorVermelhaHov, CorVermelhaHov, 108, 20, br: 3); btnGar.Font = new Font("Segoe UI", 7.5f, FontStyle.Bold); btnGar.Location = new Point(lx, 78); pnl.Controls.Add(btnGar); // Total — linha inferior destacada lblVTotal = new Label { Text = "R$ 0,00", Font = new Font("Segoe UI", 11f, FontStyle.Bold), ForeColor = CorVermelha, Dock = DockStyle.Bottom, Height = 26, TextAlign = ContentAlignment.MiddleRight, Padding = new Padding(0, 0, 6, 0), BackColor = Color.FromArgb(255, 240, 240) }; pnl.Controls.Add(lblVTotal); return pnl; } // ══════════════════════════════════════════════════════════════════════ // ABAS // ══════════════════════════════════════════════════════════════════════ private TabControl CriarAbas() { tabs = new TabControl { Dock = DockStyle.Fill, Font = new Font("Segoe UI", 9f), DrawMode = TabDrawMode.OwnerDrawFixed, ItemSize = new Size(0, 28), Padding = new Point(12, 4) }; tabs.DrawItem += (s, e) => { var pg = tabs.TabPages[e.Index]; bool sel = (e.Index == tabs.SelectedIndex); var rect = e.Bounds; using var bg = new SolidBrush(sel ? CorVermelha : CorCinzaClaro); e.Graphics.FillRectangle(bg, rect); if (!sel) { using var pen = new Pen(CorCinzaBorda); e.Graphics.DrawRectangle(pen, rect.X, rect.Y, rect.Width - 1, rect.Height - 1); } var sf = new StringFormat { Alignment = StringAlignment.Center, LineAlignment = StringAlignment.Center }; using var fg = new SolidBrush(sel ? Color.White : CorTexto); e.Graphics.DrawString(pg.Text, new Font("Segoe UI", 9f, sel ? FontStyle.Bold : FontStyle.Regular), fg, rect, sf); }; var pgAparelho = new TabPage("Aparelho") { BackColor = Color.White }; var pgMaoObra = new TabPage("Mão de obra/Serviços") { BackColor = Color.White }; var pgPecas = new TabPage("Peças utilizadas") { BackColor = Color.White }; var pgLaudo = new TabPage("Obs/Laudo técnico") { BackColor = Color.White }; var pgMisc = new TabPage("Miscelânea") { BackColor = Color.White }; ConfigAbaAparelho(pgAparelho); ConfigAbaMaoObra(pgMaoObra); ConfigAbaPecas(pgPecas); ConfigAbaLaudo(pgLaudo); ConfigAbaMisc(pgMisc); tabs.TabPages.AddRange(new[] { pgAparelho, pgMaoObra, pgPecas, pgLaudo, pgMisc }); return tabs; } // ── Aba Aparelho ─────────────────────────────────────────────────────── private void ConfigAbaAparelho(TabPage page) { page.Padding = new Padding(6, 4, 6, 4); // Usamos posicionamento manual + Anchor para evitar TableLayoutPanel // (que causava o problema dos campos desaparecendo) // ── Linha 1: Modelo | Marca ── var lblModelo = Lbl("Modelo", 0, 0, 100); txtModelo = LvTxt(page, 0, 16, 420, 26); var lblMarca = Lbl("Marca", 430, 0, 100); txtMarca = new LV_TEXTBOX1 { BorderColor = CorCinzaBorda, BorderFocusColor = CorFocoBorda, BorderSize = 2, Font = new Font("Segoe UI", 9.5f), Location = new Point(430, 16), Size = new Size(200, 26) // ajustado via Resize }; txtMarca.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; // ── Linha 2: Operadora | Serial | Nº Patrimônio ── var lblOper = Lbl("Operadora", 0, 52, 100); txtOperadora = LvTxt(page, 0, 68, 420, 26); var lblSer = Lbl("Serial", 430, 52, 100); txtSerial = LvTxt(page, 430, 68, 200, 26); var lblPat = Lbl("Nº Patrimônio", 640, 52, 120); txtPatrimonio = new LV_TEXTBOX1 { BorderColor = CorCinzaBorda, BorderFocusColor = CorFocoBorda, BorderSize = 2, Font = new Font("Segoe UI", 9.5f), Location = new Point(640, 68), Size = new Size(200, 26) }; txtPatrimonio.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; // ── Linha 3: Acessórios | Defeito/Reclamação ── var lblAces = Lbl("Acessórios", 0, 106, 120); var lblDef = Lbl("Defeito/Reclamação", 430, 106, 200); txtAcessorios = new TextBox { Multiline = true, ScrollBars = ScrollBars.Vertical, BorderStyle = BorderStyle.FixedSingle, Font = new Font("Segoe UI", 9.5f), Location = new Point(0, 122), Size = new Size(422, 140) }; txtDefeito = new TextBox { Multiline = true, ScrollBars = ScrollBars.Vertical, BorderStyle = BorderStyle.FixedSingle, Font = new Font("Segoe UI", 9.5f), Location = new Point(430, 122), Size = new Size(500, 140) // ajustado via Resize }; txtDefeito.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right; // ── Linha 4: Observações (laranja) ── var lblObs = Lbl("Observações", 0, 272, 120); txtObsAparelho = new TextBox { Multiline = true, ScrollBars = ScrollBars.Vertical, BorderStyle = BorderStyle.FixedSingle, Font = new Font("Segoe UI", 9.5f), BackColor = CorLaranja, Location = new Point(0, 288), Size = new Size(930, 120) // ajustado via Resize }; txtObsAparelho.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom; page.Controls.AddRange(new Control[] { lblModelo, txtModelo, lblMarca, txtMarca, lblOper, txtOperadora, lblSer, txtSerial, lblPat, txtPatrimonio, lblAces, txtAcessorios, lblDef, txtDefeito, lblObs, txtObsAparelho }); // Reposiciona controles ancorados à direita no resize page.Resize += (s, e) => { int w = page.ClientSize.Width - 12; txtMarca.Size = new Size(w - 430, 26); txtPatrimonio.Size = new Size(w - 640, 26); txtDefeito.Size = new Size(w - 430, 140); txtObsAparelho.Size = new Size(w, txtObsAparelho.Height); }; } // ── Aba Mão de Obra ──────────────────────────────────────────────────── private void ConfigAbaMaoObra(TabPage page) { dgvServicos = Grid(); dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Serviço", FillWeight = 40 }); dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Técnico", FillWeight = 20 }); dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Início", FillWeight = 15 }); dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Fim", FillWeight = 15 }); dgvServicos.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Valor", FillWeight = 10 }); page.Controls.Add(dgvServicos); } // ── Aba Peças ────────────────────────────────────────────────────────── private void ConfigAbaPecas(TabPage page) { dgvPecas = Grid(); dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Código", FillWeight = 12 }); dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Descrição", FillWeight = 38 }); dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Qtd", FillWeight = 10 }); dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "V. Unit.", FillWeight = 15 }); dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Total", FillWeight = 15 }); dgvPecas.Columns.Add(new DataGridViewTextBoxColumn { HeaderText = "Técnico", FillWeight = 10 }); page.Controls.Add(dgvPecas); } // ── Aba Laudo ────────────────────────────────────────────────────────── private void ConfigAbaLaudo(TabPage page) { page.Padding = new Padding(6, 4, 6, 4); var lblLaudo = Lbl("Laudo Técnico / Serviço Realizado", 0, 0, 300); txtLaudo = new TextBox { Multiline = true, ScrollBars = ScrollBars.Vertical, BorderStyle = BorderStyle.FixedSingle, Font = new Font("Segoe UI", 9.5f), Location = new Point(0, 16), Size = new Size(900, 160), Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right }; var lblObs = Lbl("Observações Adicionais do Serviço", 0, 186, 300); txtObsServico = new TextBox { Multiline = true, ScrollBars = ScrollBars.Vertical, BorderStyle = BorderStyle.FixedSingle, Font = new Font("Segoe UI", 9.5f), Location = new Point(0, 202), Size = new Size(900, 120), Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Bottom }; page.Controls.AddRange(new Control[] { lblLaudo, txtLaudo, lblObs, txtObsServico }); page.Resize += (s, e) => { int w = page.ClientSize.Width - 12; txtLaudo.Width = w; txtObsServico.Width = w; }; } // ── Aba Miscelânea ───────────────────────────────────────────────────── private void ConfigAbaMisc(TabPage page) { page.Controls.Add(Lbl("Campos adicionais serão configurados aqui.", 10, 12, 400)); } // ══════════════════════════════════════════════════════════════════════ // RODAPÉ // ══════════════════════════════════════════════════════════════════════ private Panel CriarRodape() { var pnl = new Panel { BackColor = CorCinzaClaro }; pnl.Paint += (s, e) => { using var pen = new Pen(CorCinzaBorda); e.Graphics.DrawLine(pen, 0, 0, pnl.Width, 0); }; // Técnico Responsável pnl.Controls.Add(Lbl("Técnico Responsável", 10, 2, 140, bold: true, fs: 8.5f)); cmbTecnico = new ComboBox { Location = new Point(10, 18), Size = new Size(200, 24), DropDownStyle = ComboBoxStyle.DropDownList, Font = new Font("Segoe UI", 9f), FlatStyle = FlatStyle.Flat }; cmbTecnico.Items.Add("Não definido"); cmbTecnico.SelectedIndex = 0; pnl.Controls.Add(cmbTecnico); // Prioridade pnl.Controls.Add(Lbl("Prioridade", 220, 2, 80, bold: true, fs: 8.5f)); cmbPrioridade = new ComboBox { Location = new Point(220, 18), Size = new Size(120, 24), DropDownStyle = ComboBoxStyle.DropDownList, Font = new Font("Segoe UI", 9f), FlatStyle = FlatStyle.Flat }; cmbPrioridade.Items.AddRange(new object[] { "Normal", "Alta", "Urgente" }); cmbPrioridade.SelectedIndex = 0; pnl.Controls.Add(cmbPrioridade); // Botão Fotos/Docs var btnFotos = LvBtn("📷 Fotos/Docs", CorCinzaClaro, Color.FromArgb(180, 180, 180), CorCinzaBorda, 128, 28, br: 4, bs: 1, bc: CorCinzaBorda); btnFotos.ForeColor = CorTexto; btnFotos.Anchor = AnchorStyles.Top | AnchorStyles.Right; pnl.Resize += (s, e) => btnFotos.Location = new Point(pnl.Width - 136, 8); pnl.Controls.Add(btnFotos); return pnl; } // ══════════════════════════════════════════════════════════════════════ // PREENCHIMENTO // ══════════════════════════════════════════════════════════════════════ private void PreencherCampos() { if (_os == null) return; lblNumOS.Text = $"O.S. nº {_os.CODIGO ?? "—"}"; lblCliente.Text = _os.COD_CLIENTE ?? "—"; lblCodVal.Text = _os.ID_ORDENS.ToString(); txtModelo.Text = _os.MODELO ?? ""; txtMarca.Text = _os.MARCA ?? ""; txtSerial.Text = _os.SERIE ?? ""; txtAcessorios.Text = _os.ACESSORIO ?? ""; txtDefeito.Text = _os.DEFEITO ?? ""; txtObsAparelho.Text = _os.OBS_APARELHO ?? ""; txtLaudo.Text = _os.LAUDO ?? ""; txtObsServico.Text = _os.OBS_SERVICO ?? ""; lblVMao.Text = Fmt(_os.V_MAO); lblVPecas.Text = Fmt(_os.V_PECAS); lblVDesloca.Text = Fmt(_os.V_DESLOCA); lblVTerceiro.Text = Fmt(_os.V_TERCEIRO); lblVOutros.Text = Fmt(_os.V_OUTROS); if (!string.IsNullOrEmpty(_os.SITUACAO)) { int i = cmbSituacao.Items.IndexOf(_os.SITUACAO); if (i >= 0) cmbSituacao.SelectedIndex = i; } if (DateTime.TryParse(_os.ENTRADA, out var de)) dtpEntrada.Value = de; if (DateTime.TryParse(_os.PRONTO, out var dp)) dtpPronto.Value = dp; if (DateTime.TryParse(_os.SAIDA, out var ds)) dtpSaida.Value = ds; if (!string.IsNullOrEmpty(_os.GARANTIA)) lblGarantia.Text = $"Garantia até {_os.GARANTIA}"; AtualizarTotal(); } private void AtualizarTotal() { decimal total = Prx(_os?.V_MAO) + Prx(_os?.V_PECAS) + Prx(_os?.V_DESLOCA) + Prx(_os?.V_TERCEIRO) + Prx(_os?.V_OUTROS); lblVTotal.Text = $"R$ {total:N2}"; } // ══════════════════════════════════════════════════════════════════════ // SALVAR // ══════════════════════════════════════════════════════════════════════ private void Salvar() { try { _os ??= new ModeloOrdens(); _os.MODELO = txtModelo.Text; _os.MARCA = txtMarca.Text; _os.SERIE = txtSerial.Text; _os.ACESSORIO = txtAcessorios.Text; _os.DEFEITO = txtDefeito.Text; _os.OBS_APARELHO = txtObsAparelho.Text; _os.LAUDO = txtLaudo.Text; _os.OBS_SERVICO = txtObsServico.Text; _os.SITUACAO = cmbSituacao.SelectedItem?.ToString(); _os.ENTRADA = dtpEntrada.Value.ToString("dd/MM/yy HH:mm"); _os.PRONTO = dtpPronto.Value.ToString("dd/MM/yy HH:mm"); _os.SAIDA = dtpSaida.Value.ToString("dd/MM/yy HH:mm"); MessageBox.Show("Ordem de Serviço salva com sucesso!", "LevelOS", MessageBoxButtons.OK, MessageBoxIcon.Information); OnVoltar?.Invoke(); } catch (Exception ex) { MessageBox.Show($"Erro ao salvar: {ex.Message}", "Erro", MessageBoxButtons.OK, MessageBoxIcon.Error); } } // ══════════════════════════════════════════════════════════════════════ // FACTORY HELPERS // ══════════════════════════════════════════════════════════════════════ /// LV_BUTTON configurado. private LV_BUTTON LvBtn(string texto, Color bg, Color hover, Color click, int w, int h, int br = 0, int bs = 0, Color bc = default) { var btn = new LV_BUTTON { Text = texto, Size = new Size(w, h), BackColor = bg, HoverColor = hover, ClickColor = click, ForeColor = Color.White, Font = new Font("Segoe UI", 9f, FontStyle.Bold), BorderRadius = br, BorderSize = bs, Cursor = Cursors.Hand }; if (bc != default) btn.BorderColor = bc; return btn; } /// LV_TEXTBOX1 adicionado ao parent. private LV_TEXTBOX1 LvTxt(Control parent, int x, int y, int w, int h) { var tb = new LV_TEXTBOX1 { Location = new Point(x, y), Size = new Size(w, h), BorderColor = CorCinzaBorda, BorderFocusColor = CorFocoBorda, BorderSize = 2, Font = new Font("Segoe UI", 9.5f) }; parent.Controls.Add(tb); return tb; } /// Label de valor (painel financeiro). private Label LblV(Panel parent, string rotulo, int lx, int ly, int vx, int vw, int rh) { parent.Controls.Add(Lbl(rotulo, lx, ly + 1, 120)); var lbl = new Label { Text = "R$ 0,00", Font = new Font("Segoe UI", 8.5f), ForeColor = CorTexto, Location = new Point(vx, ly), Size = new Size(vw, rh), TextAlign = ContentAlignment.MiddleRight }; parent.Controls.Add(lbl); return lbl; } /// DataGridView padronizado. private DataGridView Grid() { var dgv = new DataGridView { Dock = DockStyle.Fill, BackgroundColor = Color.White, BorderStyle = BorderStyle.None, AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill, EnableHeadersVisualStyles = false, AllowUserToAddRows = true, RowHeadersVisible = false, SelectionMode = DataGridViewSelectionMode.FullRowSelect, GridColor = CorCinzaBorda, Font = new Font("Segoe UI", 9f) }; dgv.ColumnHeadersDefaultCellStyle.BackColor = CorCinzaClaro; dgv.ColumnHeadersDefaultCellStyle.ForeColor = CorTexto; dgv.ColumnHeadersDefaultCellStyle.Font = new Font("Segoe UI", 9f, FontStyle.Bold); dgv.ColumnHeadersHeight = 28; dgv.AlternatingRowsDefaultCellStyle.BackColor = Color.FromArgb(250, 250, 255); return dgv; } /// DateTimePicker padronizado. private DateTimePicker DTP(Control parent, int x, int y, int w, int h) { var dtp = new DateTimePicker { Location = new Point(x, y), Size = new Size(w, h), Format = DateTimePickerFormat.Custom, CustomFormat = "dd/MM/yy HH:mm", Font = new Font("Segoe UI", 9f) }; parent.Controls.Add(dtp); return dtp; } /// Label simples. private Label Lbl(string texto, int x, int y, int w, bool bold = false, float fs = 8.5f) { return new Label { Text = texto, Location = new Point(x, y), Size = new Size(w, 16), Font = new Font("Segoe UI", fs, bold ? FontStyle.Bold : FontStyle.Regular), ForeColor = CorTexto, AutoSize = false }; } private string Fmt(string? v) => decimal.TryParse(v, out var d) ? $"R$ {d:N2}" : "R$ 0,00"; private decimal Prx(string? v) => decimal.TryParse(v, out var d) ? d : 0m; } }