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

837 lines
37 KiB
C#

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 <<GARANTIA>>
var btnGar = LvBtn("<<GARANTIA>>", 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
// ══════════════════════════════════════════════════════════════════════
/// <summary>LV_BUTTON configurado.</summary>
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;
}
/// <summary>LV_TEXTBOX1 adicionado ao parent.</summary>
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;
}
/// <summary>Label de valor (painel financeiro).</summary>
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;
}
/// <summary>DataGridView padronizado.</summary>
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;
}
/// <summary>DateTimePicker padronizado.</summary>
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;
}
/// <summary>Label simples.</summary>
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;
}
}