using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace C968Project.Views { public partial class AddModifyProductScreen : Form { private ScreenOption _screenOption; private Product? _currentProduct; private bool _isNameValid = false; private bool _isInventoryValid = false; private bool _isPriceValid = false; private bool _isMinValid = false; private bool _isMaxValid = false; private int _validatedMin = 0; private int _validatedMax = 0; public AddModifyProductScreen(ScreenOption screenOption, Product? product = null) { InitializeComponent(); this._screenOption = screenOption; _currentProduct = product; if (_screenOption is ScreenOption.ADD) { screenLabel.Text = "Add Product"; _currentProduct = new(); associatedPartsDataGridView.DataSource = _currentProduct.AssociatedParts; } if (_screenOption is ScreenOption.MODIFY) { screenLabel.Text = "Modify Product"; PopulateProductData(_currentProduct); } allPartsDataGridView.DataSource = Program.Inventory.Parts; ValidateInputs(); } private void PopulateProductData(Product product) { idTextBox.Text = product.ProductId.ToString(); nameTextBox.Text = product.Name; inventoryTextBox.Text = product.InStock.ToString(); priceTextBox.Text = product.Price.ToString(); minTextBox.Text = product.Min.ToString(); maxTextBox.Text = product.Max.ToString(); associatedPartsDataGridView.DataSource = product.AssociatedParts; } private Product CreateProduct(int productId) { Product product = new(); product.ProductId = productId; product.Name = nameTextBox.Text; product.InStock = int.Parse(inventoryTextBox.Text); product.Price = float.Parse(priceTextBox.Text); product.Min = int.Parse(minTextBox.Text); product.Max = int.Parse(maxTextBox.Text); var dataGridViewData = associatedPartsDataGridView.DataSource; if (dataGridViewData != null) { if (dataGridViewData is BindingList partsList) { product.AssociatedParts = partsList; } else { MessageBox.Show("Error generating Associated Parts: DataGridView DataSource is not of type BindingList somehow. Defaulting to an empty list.", "Data Type Error", MessageBoxButtons.OK, MessageBoxIcon.Error); product.AssociatedParts = new(); } } else { product.AssociatedParts = new(); } return product; } private void AddProduct() { int newId = Program.CreateNewProductId(); Program.Inventory.AddProduct(CreateProduct(newId)); } private void ModifyProduct() { int productIndex = 0; if (_currentProduct != null && Program.Inventory.Products.Contains(_currentProduct)) { productIndex = Program.Inventory.Products.IndexOf(_currentProduct); } else { MessageBox.Show("Error modifying product: Could not find product index", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } var oldProduct = Program.Inventory.Products[productIndex]; var oldProductId = oldProduct.ProductId; var modifiedProduct = CreateProduct(oldProductId); Program.Inventory.Products[productIndex] = modifiedProduct; } private void saveButton_Click(object sender, EventArgs e) { if (ValidateInputs()) { if (_screenOption is ScreenOption.ADD) { AddProduct(); Close(); } if (_screenOption is ScreenOption.MODIFY) { ModifyProduct(); Close(); } } } private void cancelButton_Click(object sender, EventArgs e) { Close(); } private void addButton_Click(object sender, EventArgs e) { if (allPartsDataGridView.CurrentCell is null) { MessageBox.Show("No part selected", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } Part part = Program.Inventory.LookupPart(allPartsDataGridView.CurrentCell.RowIndex); if (part is null) return; if (_currentProduct.AssociatedParts.Contains(part)) { MessageBox.Show("Part already added", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } _currentProduct.AddAssociatedPart(part); } private void deleteButton_Click(object sender, EventArgs e) { if (associatedPartsDataGridView.CurrentCell is null) { MessageBox.Show("No part selected", "", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } if (!Helpers.ConfirmDelete()) return; Part part = _currentProduct.LookupAssociatedPart(associatedPartsDataGridView.CurrentCell.RowIndex); if (part is null || !_currentProduct.AssociatedParts.Contains(part)) { MessageBox.Show("Error finding associated part from selection", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning); return; } _currentProduct.RemoveAssociatedPart(_currentProduct.AssociatedParts.IndexOf(part)); } private void nameTextBox_TextChanged(object sender, EventArgs e) { ValidateName(); } private void ValidateName() { if (nameTextBox.Text == string.Empty) { errorProvider1.SetError(nameTextBox, "Please enter a product name"); _isNameValid = false; } else { errorProvider1.SetError(nameTextBox, ""); _isNameValid = true; } Helpers.SetTextBoxValidationState(nameTextBox, _isNameValid); } private void inventoryTextBox_TextChanged(object sender, EventArgs e) { ValidateInventory(); } private void ValidateInventory() { int inventory = 0; if (inventoryTextBox.Text != string.Empty && int.TryParse(inventoryTextBox.Text, out inventory)) { if (_isMinValid && _isMaxValid) { if (inventory > _validatedMax) { errorProvider1.SetError(inventoryTextBox, $"Must be less than Max: {_validatedMax}"); _isInventoryValid = false; } else if (inventory < _validatedMin) { errorProvider1.SetError(inventoryTextBox, $"Must be greater than Min: {_validatedMin}"); _isInventoryValid = false; } else { errorProvider1.SetError(inventoryTextBox, ""); _isInventoryValid = true; } } else { errorProvider1.SetError(inventoryTextBox, $"Min and Max values must be set"); _isInventoryValid = false; } } else { _isInventoryValid = false; errorProvider1.SetError(inventoryTextBox, "Field must contain an integer value"); } Helpers.SetTextBoxValidationState(inventoryTextBox, _isInventoryValid); } private void priceTextBox_TextChanged(object sender, EventArgs e) { ValidatePrice(); } private void ValidatePrice() { float price = 0f; if (priceTextBox.Text != string.Empty && float.TryParse(priceTextBox.Text, out price)) { _isPriceValid = true; errorProvider1.SetError(priceTextBox, ""); } else { _isPriceValid = false; errorProvider1.SetError(priceTextBox, "Field must contain a floating point number"); } Helpers.SetTextBoxValidationState(priceTextBox, _isPriceValid); } private void maxTextBox_TextChanged(object sender, EventArgs e) { ValidateMax(); } private void ValidateMax() { int max = 0; if (maxTextBox.Text != string.Empty && int.TryParse(maxTextBox.Text, out max)) { _isMaxValid = true; errorProvider1.SetError(maxTextBox, ""); _validatedMax = max; } else { _isMaxValid = false; errorProvider1.SetError(maxTextBox, "Field must contain an integer value"); } ValidateInventory(); Helpers.SetTextBoxValidationState(maxTextBox, _isMaxValid); } private void minTextBox_TextChanged(object sender, EventArgs e) { ValidateMin(); } private void ValidateMin() { int min = 0; if (minTextBox.Text != string.Empty && int.TryParse(minTextBox.Text, out min)) { _isMinValid = true; errorProvider1.SetError(minTextBox, ""); _validatedMin = min; } else { _isMinValid = false; errorProvider1.SetError(minTextBox, "Field must contain an integer value"); } ValidateInventory(); Helpers.SetTextBoxValidationState(minTextBox, _isMinValid); } private bool ValidateInputs() { ValidateName(); ValidateInventory(); ValidatePrice(); ValidateMin(); ValidateMax(); return _isNameValid && _isInventoryValid && _isPriceValid && _isMinValid && _isMaxValid; } } }