Adding folder for forms for cleanup

This commit is contained in:
Spudnut2000
2025-06-26 21:10:19 -05:00
parent 48a2bd21de
commit d0df6b2593
20 changed files with 12 additions and 9 deletions

View File

@@ -0,0 +1,344 @@
using System.ComponentModel;
namespace C969Project;
partial class AddOrUpdateAppointmentForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
cancelButton = new Button();
saveButton = new Button();
label1 = new Label();
label2 = new Label();
titleTextBox = new TextBox();
descriptionTextBox = new TextBox();
label3 = new Label();
locationTextBox = new TextBox();
label4 = new Label();
contactTextBox = new TextBox();
label5 = new Label();
textBoxUrl = new TextBox();
urlTextBox = new Label();
label6 = new Label();
typeComboBox = new ComboBox();
customerComboBox = new ComboBox();
customerLabel = new Label();
startPickerDate = new DateTimePicker();
label7 = new Label();
label8 = new Label();
endPickerDate = new DateTimePicker();
startPickerTime = new DateTimePicker();
endPickerTime = new DateTimePicker();
SuspendLayout();
//
// cancelButton
//
cancelButton.Location = new Point(856, 761);
cancelButton.Name = "cancelButton";
cancelButton.Size = new Size(75, 23);
cancelButton.TabIndex = 0;
cancelButton.Text = "Cancel";
cancelButton.UseVisualStyleBackColor = true;
//
// saveButton
//
saveButton.Location = new Point(775, 761);
saveButton.Name = "saveButton";
saveButton.Size = new Size(75, 23);
saveButton.TabIndex = 1;
saveButton.Text = "Save";
saveButton.UseVisualStyleBackColor = true;
//
// label1
//
label1.Font = new Font("Segoe UI", 12F, FontStyle.Regular, GraphicsUnit.Point, 0);
label1.Location = new Point(12, 9);
label1.Name = "label1";
label1.Size = new Size(159, 23);
label1.TabIndex = 2;
label1.Text = "Update Appointment";
//
// label2
//
label2.Font = new Font("Segoe UI Semibold", 9.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
label2.Location = new Point(12, 69);
label2.Name = "label2";
label2.RightToLeft = RightToLeft.No;
label2.Size = new Size(100, 23);
label2.TabIndex = 3;
label2.Text = "Title";
label2.TextAlign = ContentAlignment.MiddleLeft;
//
// titleTextBox
//
titleTextBox.Location = new Point(12, 95);
titleTextBox.Name = "titleTextBox";
titleTextBox.Size = new Size(520, 23);
titleTextBox.TabIndex = 4;
//
// descriptionTextBox
//
descriptionTextBox.Location = new Point(12, 147);
descriptionTextBox.Multiline = true;
descriptionTextBox.Name = "descriptionTextBox";
descriptionTextBox.Size = new Size(520, 100);
descriptionTextBox.TabIndex = 6;
//
// label3
//
label3.Font = new Font("Segoe UI Semibold", 9.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
label3.Location = new Point(12, 121);
label3.Name = "label3";
label3.RightToLeft = RightToLeft.No;
label3.Size = new Size(100, 23);
label3.TabIndex = 5;
label3.Text = "Description";
label3.TextAlign = ContentAlignment.MiddleLeft;
//
// locationTextBox
//
locationTextBox.Location = new Point(12, 276);
locationTextBox.Name = "locationTextBox";
locationTextBox.Size = new Size(520, 23);
locationTextBox.TabIndex = 8;
//
// label4
//
label4.Font = new Font("Segoe UI Semibold", 9.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
label4.Location = new Point(12, 250);
label4.Name = "label4";
label4.RightToLeft = RightToLeft.No;
label4.Size = new Size(100, 23);
label4.TabIndex = 7;
label4.Text = "Location";
label4.TextAlign = ContentAlignment.MiddleLeft;
//
// contactTextBox
//
contactTextBox.Location = new Point(12, 328);
contactTextBox.Name = "contactTextBox";
contactTextBox.Size = new Size(520, 23);
contactTextBox.TabIndex = 10;
//
// label5
//
label5.Font = new Font("Segoe UI Semibold", 9.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
label5.Location = new Point(12, 302);
label5.Name = "label5";
label5.RightToLeft = RightToLeft.No;
label5.Size = new Size(100, 23);
label5.TabIndex = 9;
label5.Text = "Contact";
label5.TextAlign = ContentAlignment.MiddleLeft;
//
// textBoxUrl
//
textBoxUrl.Location = new Point(12, 380);
textBoxUrl.Name = "textBoxUrl";
textBoxUrl.Size = new Size(520, 23);
textBoxUrl.TabIndex = 12;
//
// urlTextBox
//
urlTextBox.Font = new Font("Segoe UI Semibold", 9.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
urlTextBox.Location = new Point(12, 354);
urlTextBox.Name = "urlTextBox";
urlTextBox.RightToLeft = RightToLeft.No;
urlTextBox.Size = new Size(100, 23);
urlTextBox.TabIndex = 11;
urlTextBox.Text = "Url";
urlTextBox.TextAlign = ContentAlignment.MiddleLeft;
//
// label6
//
label6.Font = new Font("Segoe UI Semibold", 9.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
label6.Location = new Point(12, 406);
label6.Name = "label6";
label6.RightToLeft = RightToLeft.No;
label6.Size = new Size(100, 23);
label6.TabIndex = 13;
label6.Text = "Type";
label6.TextAlign = ContentAlignment.MiddleLeft;
//
// typeComboBox
//
typeComboBox.FormattingEnabled = true;
typeComboBox.Location = new Point(12, 432);
typeComboBox.Name = "typeComboBox";
typeComboBox.Size = new Size(324, 23);
typeComboBox.TabIndex = 14;
//
// customerComboBox
//
customerComboBox.FormattingEnabled = true;
customerComboBox.Location = new Point(12, 484);
customerComboBox.Name = "customerComboBox";
customerComboBox.Size = new Size(324, 23);
customerComboBox.TabIndex = 16;
//
// customerLabel
//
customerLabel.Font = new Font("Segoe UI Semibold", 9.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
customerLabel.Location = new Point(12, 458);
customerLabel.Name = "customerLabel";
customerLabel.RightToLeft = RightToLeft.No;
customerLabel.Size = new Size(100, 23);
customerLabel.TabIndex = 15;
customerLabel.Text = "Customer";
customerLabel.TextAlign = ContentAlignment.MiddleLeft;
//
// startPickerDate
//
startPickerDate.CustomFormat = "dddd MMMM dd @ hh:mm tt";
startPickerDate.Format = DateTimePickerFormat.Short;
startPickerDate.Location = new Point(12, 536);
startPickerDate.Name = "startPickerDate";
startPickerDate.Size = new Size(159, 23);
startPickerDate.TabIndex = 17;
//
// label7
//
label7.Font = new Font("Segoe UI Semibold", 9.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
label7.Location = new Point(12, 510);
label7.Name = "label7";
label7.RightToLeft = RightToLeft.No;
label7.Size = new Size(100, 23);
label7.TabIndex = 18;
label7.Text = "Start Time";
label7.TextAlign = ContentAlignment.MiddleLeft;
//
// label8
//
label8.Font = new Font("Segoe UI Semibold", 9.75F, FontStyle.Bold | FontStyle.Italic, GraphicsUnit.Point, 0);
label8.Location = new Point(12, 562);
label8.Name = "label8";
label8.RightToLeft = RightToLeft.No;
label8.Size = new Size(100, 23);
label8.TabIndex = 20;
label8.Text = "End Time";
label8.TextAlign = ContentAlignment.MiddleLeft;
//
// endPickerDate
//
endPickerDate.CustomFormat = "dddd MMMM dd @ hh:mm tt";
endPickerDate.Format = DateTimePickerFormat.Short;
endPickerDate.Location = new Point(12, 588);
endPickerDate.Name = "endPickerDate";
endPickerDate.Size = new Size(159, 23);
endPickerDate.TabIndex = 19;
//
// startPickerTime
//
startPickerTime.CustomFormat = "dddd MMMM dd @ hh:mm tt";
startPickerTime.Format = DateTimePickerFormat.Time;
startPickerTime.Location = new Point(177, 536);
startPickerTime.Name = "startPickerTime";
startPickerTime.ShowUpDown = true;
startPickerTime.Size = new Size(159, 23);
startPickerTime.TabIndex = 21;
//
// endPickerTime
//
endPickerTime.CustomFormat = "dddd MMMM dd @ hh:mm tt";
endPickerTime.Format = DateTimePickerFormat.Time;
endPickerTime.Location = new Point(177, 588);
endPickerTime.Name = "endPickerTime";
endPickerTime.ShowUpDown = true;
endPickerTime.Size = new Size(159, 23);
endPickerTime.TabIndex = 22;
//
// AddOrUpdateAppointmentForm
//
AutoScaleDimensions = new SizeF(7F, 15F);
AutoScaleMode = AutoScaleMode.Font;
ClientSize = new Size(943, 796);
Controls.Add(endPickerTime);
Controls.Add(startPickerTime);
Controls.Add(label8);
Controls.Add(endPickerDate);
Controls.Add(label7);
Controls.Add(startPickerDate);
Controls.Add(customerComboBox);
Controls.Add(customerLabel);
Controls.Add(typeComboBox);
Controls.Add(label6);
Controls.Add(textBoxUrl);
Controls.Add(urlTextBox);
Controls.Add(contactTextBox);
Controls.Add(label5);
Controls.Add(locationTextBox);
Controls.Add(label4);
Controls.Add(descriptionTextBox);
Controls.Add(label3);
Controls.Add(titleTextBox);
Controls.Add(label2);
Controls.Add(label1);
Controls.Add(saveButton);
Controls.Add(cancelButton);
Name = "AddOrUpdateAppointmentForm";
Text = "Update Appointment";
ResumeLayout(false);
PerformLayout();
}
private System.Windows.Forms.DateTimePicker startPickerDate;
private System.Windows.Forms.DateTimePicker endPickerDate;
private System.Windows.Forms.DateTimePicker dateTimePicker1;
private System.Windows.Forms.DateTimePicker dateTimePicker2;
private System.Windows.Forms.ComboBox customerComboBox;
private System.Windows.Forms.Label customerLabel;
private System.Windows.Forms.DateTimePicker startPickerTime;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.DateTimePicker endPickerTime;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.ComboBox typeComboBox;
private System.Windows.Forms.TextBox locationTextBox;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.TextBox contactTextBox;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox textBoxUrl;
private System.Windows.Forms.Label urlTextBox;
private System.Windows.Forms.TextBox descriptionTextBox;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.TextBox titleTextBox;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Button saveButton;
#endregion
}

View File

@@ -0,0 +1,182 @@
using C969Project.Data;
using C969Project.Data.Models;
namespace C969Project;
public partial class AddOrUpdateAppointmentForm : Form
{
public event EventHandler UpdateAppointmentsList;
private Appointment? _currentAppointment;
private List<string> _appointmentTypes = new ()
{
"Scrum",
"Presentation",
"Other"
};
private List<Customer> _customers = new();
public AddOrUpdateAppointmentForm()
{
InitializeComponent();
RefreshCustomersList();
typeComboBox.DataSource = _appointmentTypes;
saveButton.Click += SaveButton_Click;
cancelButton.Click += (s, e) => Close();
}
private void RefreshCustomersList()
{
customerComboBox.DataSource = null;
_customers.Clear();
_customers.AddRange(DatabaseHelper.RetrieveCustomers());
customerComboBox.DataSource = _customers;
}
public void InitAdd()
{
RefreshCustomersList();
label1.Text = "Add New Appointment";
_currentAppointment = null;
titleTextBox.Text = string.Empty;
descriptionTextBox.Text = string.Empty;
locationTextBox.Text = string.Empty;
contactTextBox.Text = string.Empty;
textBoxUrl.Text = string.Empty;
typeComboBox.SelectedIndex = -1;
customerComboBox.SelectedIndex = -1;
startPickerDate.Value = DateTime.Now.Date;
startPickerTime.Value = DateTime.Now;
endPickerDate.Value = DateTime.Now.Date;
endPickerTime.Value = DateTime.Now.AddHours(1);
ShowDialog();
}
public void InitUpdate(Appointment appointment)
{
RefreshCustomersList();
label1.Text = "Update Appointment";
_currentAppointment = appointment;
titleTextBox.Text = appointment.Title;
descriptionTextBox.Text = appointment.Description;
locationTextBox.Text = appointment.Location;
contactTextBox.Text = appointment.Contact;
textBoxUrl.Text = appointment.Url;
typeComboBox.SelectedItem = appointment.AppointmentType;
customerComboBox.SelectedItem = _customers.FirstOrDefault(c => c.CustomerId == appointment.CustomerId);
startPickerDate.Value = appointment.Start.ToLocalTime().Date;
startPickerTime.Value = appointment.Start.ToLocalTime();
endPickerDate.Value = appointment.End.ToLocalTime().Date;
endPickerTime.Value = appointment.End.ToLocalTime();
ShowDialog();
}
private bool ValidateForm()
{
if (string.IsNullOrWhiteSpace(titleTextBox.Text) ||
string.IsNullOrWhiteSpace(descriptionTextBox.Text) ||
string.IsNullOrWhiteSpace(locationTextBox.Text) ||
string.IsNullOrWhiteSpace(contactTextBox.Text) ||
string.IsNullOrWhiteSpace(textBoxUrl.Text) ||
typeComboBox.SelectedIndex == -1 ||
customerComboBox.SelectedIndex == -1)
{
MessageBox.Show("All fields must be filled out.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
DateTime start = startPickerDate.Value.Date.Add(startPickerTime.Value.TimeOfDay).ToUniversalTime();
DateTime end = endPickerDate.Value.Date.Add(endPickerTime.Value.TimeOfDay).ToUniversalTime();
if (start >= end)
{
MessageBox.Show("Start time must be before end time.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
TimeZoneInfo estZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime startEST = TimeZoneInfo.ConvertTimeFromUtc(start, estZone);
DateTime endEST = TimeZoneInfo.ConvertTimeFromUtc(end, estZone);
if (startEST.Hour < 9 || endEST.Hour > 17 || startEST.DayOfWeek == DayOfWeek.Saturday || startEST.DayOfWeek == DayOfWeek.Sunday)
{
MessageBox.Show("Appointments must be scheduled during business hours (9:00 AM - 5:00 PM EST, Monday-Friday).", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
var appointments = DatabaseHelper.RetrieveAppointments(AppState.CurrentUser.UserId);
foreach (var appt in appointments)
{
if (_currentAppointment == null || appt.AppointmentId != _currentAppointment.AppointmentId)
{
if (start < appt.End && end > appt.Start)
{
MessageBox.Show("Appointment times cannot overlap with existing appointments.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
}
}
return true;
}
private void SaveButton_Click(object? sender, EventArgs e)
{
if (!ValidateForm())
return;
try
{
var selectedCustomer = (Customer)customerComboBox.SelectedItem!;
var appointment = new Appointment
{
AppointmentId = _currentAppointment?.AppointmentId ?? 0,
CustomerId = selectedCustomer.CustomerId,
UserId = AppState.CurrentUser.UserId,
Title = titleTextBox.Text.Trim(),
Description = descriptionTextBox.Text.Trim(),
Location = locationTextBox.Text.Trim(),
Contact = contactTextBox.Text.Trim(),
AppointmentType = typeComboBox.SelectedItem!.ToString()!,
Url = textBoxUrl.Text.Trim(),
Start = startPickerDate.Value.Date.Add(startPickerTime.Value.TimeOfDay).ToUniversalTime(),
End = endPickerDate.Value.Date.Add(endPickerTime.Value.TimeOfDay).ToUniversalTime(),
CreateDate = DateTime.UtcNow,
CreatedBy = AppState.CurrentUser.Username,
LastUpdate = DateTime.UtcNow,
LastUpdateBy = AppState.CurrentUser.Username
};
if (_currentAppointment == null)
{
DatabaseHelper.AddAppointment(appointment);
MessageBox.Show("Appointment added successfully.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
DatabaseHelper.UpdateAppointment(appointment);
MessageBox.Show("Appointment updated successfully.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
DialogResult = DialogResult.OK;
UpdateAppointmentsList?.Invoke(this, EventArgs.Empty);
Close();
}
catch (Exception ex)
{
MessageBox.Show($"An error occurred while saving the appointment:\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}

View File

@@ -0,0 +1,123 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="$this.Locked" type="System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>True</value>
</metadata>
</root>

View File

@@ -0,0 +1,244 @@
using System.ComponentModel;
namespace C969Project;
partial class AddUpdateCustomerForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
label1 = new System.Windows.Forms.Label();
saveButton = new System.Windows.Forms.Button();
cancelButton = new System.Windows.Forms.Button();
label2 = new System.Windows.Forms.Label();
nameTextBox = new System.Windows.Forms.TextBox();
phoneTextBox = new System.Windows.Forms.TextBox();
label3 = new System.Windows.Forms.Label();
addressTextBox = new System.Windows.Forms.TextBox();
label4 = new System.Windows.Forms.Label();
label5 = new System.Windows.Forms.Label();
label6 = new System.Windows.Forms.Label();
cityTextBox = new System.Windows.Forms.TextBox();
label7 = new System.Windows.Forms.Label();
zipTextBox = new System.Windows.Forms.TextBox();
label8 = new System.Windows.Forms.Label();
countryTextBox = new System.Windows.Forms.TextBox();
SuspendLayout();
//
// label1
//
label1.Font = new System.Drawing.Font("Segoe UI", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)0));
label1.Location = new System.Drawing.Point(12, 9);
label1.Name = "label1";
label1.Size = new System.Drawing.Size(776, 23);
label1.TabIndex = 0;
label1.Text = "Add Customer";
label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// saveButton
//
saveButton.Location = new System.Drawing.Point(632, 415);
saveButton.Name = "saveButton";
saveButton.Size = new System.Drawing.Size(75, 23);
saveButton.TabIndex = 1;
saveButton.Text = "Save";
saveButton.UseVisualStyleBackColor = true;
//
// cancelButton
//
cancelButton.Location = new System.Drawing.Point(713, 415);
cancelButton.Name = "cancelButton";
cancelButton.Size = new System.Drawing.Size(75, 23);
cancelButton.TabIndex = 2;
cancelButton.Text = "Cancel";
cancelButton.UseVisualStyleBackColor = true;
//
// label2
//
label2.Font = new System.Drawing.Font("Segoe UI Semibold", 9.75F, ((System.Drawing.FontStyle)(System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic)), System.Drawing.GraphicsUnit.Point, ((byte)0));
label2.Location = new System.Drawing.Point(12, 61);
label2.Name = "label2";
label2.Size = new System.Drawing.Size(332, 23);
label2.TabIndex = 3;
label2.Text = "Name";
label2.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// nameTextBox
//
nameTextBox.Location = new System.Drawing.Point(12, 87);
nameTextBox.Name = "nameTextBox";
nameTextBox.Size = new System.Drawing.Size(332, 23);
nameTextBox.TabIndex = 4;
//
// phoneTextBox
//
phoneTextBox.Location = new System.Drawing.Point(12, 144);
phoneTextBox.Name = "phoneTextBox";
phoneTextBox.Size = new System.Drawing.Size(332, 23);
phoneTextBox.TabIndex = 6;
//
// label3
//
label3.Font = new System.Drawing.Font("Segoe UI Semibold", 9.75F, ((System.Drawing.FontStyle)(System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic)), System.Drawing.GraphicsUnit.Point, ((byte)0));
label3.Location = new System.Drawing.Point(12, 118);
label3.Name = "label3";
label3.Size = new System.Drawing.Size(332, 23);
label3.TabIndex = 5;
label3.Text = "Phone";
label3.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// addressTextBox
//
addressTextBox.Location = new System.Drawing.Point(12, 212);
addressTextBox.Name = "addressTextBox";
addressTextBox.Size = new System.Drawing.Size(218, 23);
addressTextBox.TabIndex = 8;
//
// label4
//
label4.Font = new System.Drawing.Font("Segoe UI Semibold", 9.75F, ((System.Drawing.FontStyle)(System.Drawing.FontStyle.Bold | System.Drawing.FontStyle.Italic)), System.Drawing.GraphicsUnit.Point, ((byte)0));
label4.Location = new System.Drawing.Point(12, 186);
label4.Name = "label4";
label4.Size = new System.Drawing.Size(332, 23);
label4.TabIndex = 7;
label4.Text = "Address";
label4.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// label5
//
label5.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)0));
label5.Location = new System.Drawing.Point(236, 212);
label5.Name = "label5";
label5.Size = new System.Drawing.Size(63, 23);
label5.TabIndex = 9;
label5.Text = "Address";
label5.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// label6
//
label6.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)0));
label6.Location = new System.Drawing.Point(236, 241);
label6.Name = "label6";
label6.Size = new System.Drawing.Size(63, 23);
label6.TabIndex = 11;
label6.Text = "City";
label6.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// cityTextBox
//
cityTextBox.Location = new System.Drawing.Point(12, 241);
cityTextBox.Name = "cityTextBox";
cityTextBox.Size = new System.Drawing.Size(218, 23);
cityTextBox.TabIndex = 10;
//
// label7
//
label7.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)0));
label7.Location = new System.Drawing.Point(236, 270);
label7.Name = "label7";
label7.Size = new System.Drawing.Size(63, 23);
label7.TabIndex = 13;
label7.Text = "Zip code";
label7.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// zipTextBox
//
zipTextBox.Location = new System.Drawing.Point(12, 270);
zipTextBox.Name = "zipTextBox";
zipTextBox.Size = new System.Drawing.Size(218, 23);
zipTextBox.TabIndex = 12;
//
// label8
//
label8.Font = new System.Drawing.Font("Segoe UI", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)0));
label8.Location = new System.Drawing.Point(236, 299);
label8.Name = "label8";
label8.Size = new System.Drawing.Size(63, 23);
label8.TabIndex = 15;
label8.Text = "Country";
label8.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// countryTextBox
//
countryTextBox.Location = new System.Drawing.Point(12, 299);
countryTextBox.Name = "countryTextBox";
countryTextBox.Size = new System.Drawing.Size(218, 23);
countryTextBox.TabIndex = 14;
countryTextBox.Text = "US";
//
// AddUpdateCustomerForm
//
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
BackColor = System.Drawing.SystemColors.Control;
ClientSize = new System.Drawing.Size(800, 450);
Controls.Add(label8);
Controls.Add(countryTextBox);
Controls.Add(label7);
Controls.Add(zipTextBox);
Controls.Add(label6);
Controls.Add(cityTextBox);
Controls.Add(label5);
Controls.Add(addressTextBox);
Controls.Add(label4);
Controls.Add(phoneTextBox);
Controls.Add(label3);
Controls.Add(nameTextBox);
Controls.Add(label2);
Controls.Add(cancelButton);
Controls.Add(saveButton);
Controls.Add(label1);
Location = new System.Drawing.Point(15, 15);
Text = "Add Customer";
ResumeLayout(false);
PerformLayout();
}
private System.Windows.Forms.Label label8;
private System.Windows.Forms.TextBox countryTextBox;
private System.Windows.Forms.Label label6;
private System.Windows.Forms.TextBox cityTextBox;
private System.Windows.Forms.Label label7;
private System.Windows.Forms.TextBox zipTextBox;
private System.Windows.Forms.Label label5;
private System.Windows.Forms.TextBox nameTextBox;
private System.Windows.Forms.TextBox phoneTextBox;
private System.Windows.Forms.Label label3;
private System.Windows.Forms.TextBox addressTextBox;
private System.Windows.Forms.Label label4;
private System.Windows.Forms.Button saveButton;
private System.Windows.Forms.Button cancelButton;
private System.Windows.Forms.Label label2;
private System.Windows.Forms.Label label1;
#endregion
}

View File

@@ -0,0 +1,197 @@
using System;
using System.Windows.Forms;
using C969Project.Data;
using C969Project.Data.Models;
namespace C969Project
{
public partial class AddUpdateCustomerForm : Form
{
private Customer? _currentCustomer;
public event EventHandler UpdateCustomersList;
public AddUpdateCustomerForm()
{
InitializeComponent();
saveButton.Click += SaveButton_Click;
cancelButton.Click += CancelButton_Click;
}
public void InitAdd()
{
Text = "Add Customer";
label1.Text = "Add Customer";
nameTextBox.Text = string.Empty;
addressTextBox.Text = string.Empty;
cityTextBox.Text = string.Empty;
zipTextBox.Text = string.Empty;
phoneTextBox.Text = string.Empty;
_currentCustomer = null;
ShowDialog();
}
public void InitUpdate(Customer customer)
{
Text = "Update Customer";
label1.Text = "Update Customer";
_currentCustomer = customer;
nameTextBox.Text = customer.CustomerName;
var addr = DatabaseHelper.RetrieveAddress(customer.AddressId);
if (addr != null)
{
addressTextBox.Text = addr.Address1;
var city = DatabaseHelper.RetrieveCity(addr.CityId);
if (city != null)
{
cityTextBox.Text = city.CityName;
}
zipTextBox.Text = addr.PostalCode;
phoneTextBox.Text = addr.Phone;
}
ShowDialog();
}
private void SaveButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrWhiteSpace(nameTextBox.Text) ||
string.IsNullOrWhiteSpace(addressTextBox.Text) ||
string.IsNullOrWhiteSpace(cityTextBox.Text) ||
string.IsNullOrWhiteSpace(zipTextBox.Text) ||
string.IsNullOrWhiteSpace(phoneTextBox.Text) ||
string.IsNullOrWhiteSpace(countryTextBox.Text))
{
MessageBox.Show("All fields must be filled out.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
if (!System.Text.RegularExpressions.Regex.IsMatch(phoneTextBox.Text.Trim(), @"^[\d-]+$"))
{
MessageBox.Show("Phone number can only contain digits and dashes.", "Validation Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}
string currentUser = AppState.CurrentUser.Username;
try
{
string countryName = countryTextBox.Text;
int currentCountryId = DatabaseHelper.GetCountryId(countryName);
if (currentCountryId == 0)
{
Country newCountry = new Country
{
CountryName = countryName,
CreateDate = DateTime.UtcNow,
CreatedBy = currentUser,
LastUpdate = DateTime.UtcNow,
LastUpdateBy = currentUser
};
currentCountryId = DatabaseHelper.AddCountry(newCountry);
}
int currentCityId = DatabaseHelper.GetCityId(cityTextBox.Text.Trim(), currentCountryId);
if (currentCityId == 0)
{
City newCity = new City
{
CityName = cityTextBox.Text.Trim(),
CountryID = currentCountryId,
CreateDate = DateTime.UtcNow,
CreatedBy = currentUser,
LastUpdate = DateTime.UtcNow,
LastUpdateBy = currentUser
};
currentCityId = DatabaseHelper.AddCity(newCity);
}
Address addressToSave;
int finalAddressId;
if (Text == "Add Customer")
{
addressToSave = new Address
{
Address1 = addressTextBox.Text.Trim(),
Address2 = "",
CityId = currentCityId,
PostalCode = zipTextBox.Text.Trim(),
Phone = phoneTextBox.Text.Trim(),
CreateDate = DateTime.UtcNow,
CreatedBy = currentUser,
LastUpdate = DateTime.UtcNow,
LastUpdateBy = currentUser
};
finalAddressId = DatabaseHelper.AddAddress(addressToSave);
}
else
{
Address? existingAddress = DatabaseHelper.RetrieveAddress(_currentCustomer.AddressId);
if (existingAddress == null)
{
MessageBox.Show("Could not find existing address for update.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
addressToSave = existingAddress;
addressToSave.Address1 = addressTextBox.Text.Trim();
addressToSave.Address2 = "";
addressToSave.CityId = currentCityId;
addressToSave.PostalCode = zipTextBox.Text.Trim();
addressToSave.Phone = phoneTextBox.Text.Trim();
addressToSave.LastUpdateBy = currentUser;
DatabaseHelper.UpdateAddress(addressToSave);
finalAddressId = addressToSave.Id;
}
Customer customerToSave;
if (Text == "Add Customer")
{
customerToSave = new Customer
{
CustomerName = nameTextBox.Text.Trim(),
AddressId = finalAddressId,
Active = 1,
CreateDate = DateTime.UtcNow,
CreatedBy = currentUser,
LastUpdate = DateTime.UtcNow,
LastUpdateBy = currentUser
};
DatabaseHelper.AddCustomer(customerToSave);
}
else
{
customerToSave = _currentCustomer;
customerToSave.CustomerName = nameTextBox.Text.Trim();
customerToSave.AddressId = finalAddressId;
customerToSave.LastUpdateBy = currentUser;
DatabaseHelper.UpdateCustomer(customerToSave);
}
MessageBox.Show("Customer saved successfully!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
DialogResult = DialogResult.OK;
Close();
}
catch (Exception ex)
{
// TODO: Implement robust exception handling, logging, and user notification as per assignment A2b
MessageBox.Show($"An error occurred while saving the customer: {ex.Message}", "Database Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
UpdateCustomersList?.Invoke(this, EventArgs.Empty);
}
private void CancelButton_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
Close();
}
}
}

View File

@@ -0,0 +1,201 @@
using System.ComponentModel;
namespace C969Project;
partial class AppointmentsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
appointmentDataView = new System.Windows.Forms.DataGridView();
calendar = new System.Windows.Forms.MonthCalendar();
addButton = new System.Windows.Forms.Button();
modifyButton = new System.Windows.Forms.Button();
deleteButton = new System.Windows.Forms.Button();
showAllButton = new System.Windows.Forms.Button();
appointmentDetails = new System.Windows.Forms.GroupBox();
endTimeLabel = new System.Windows.Forms.Label();
startTimeLabel = new System.Windows.Forms.Label();
withLabel = new System.Windows.Forms.Label();
apptTypeLabel = new System.Windows.Forms.Label();
apptTitleLabel = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)appointmentDataView).BeginInit();
appointmentDetails.SuspendLayout();
SuspendLayout();
//
// appointmentDataView
//
appointmentDataView.AllowUserToAddRows = false;
appointmentDataView.AllowUserToDeleteRows = false;
appointmentDataView.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right));
appointmentDataView.Location = new System.Drawing.Point(12, 11);
appointmentDataView.Name = "appointmentDataView";
appointmentDataView.ReadOnly = true;
appointmentDataView.Size = new System.Drawing.Size(739, 523);
appointmentDataView.TabIndex = 0;
//
// calendar
//
calendar.Anchor = ((System.Windows.Forms.AnchorStyles)(System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right));
calendar.Location = new System.Drawing.Point(773, 11);
calendar.Name = "calendar";
calendar.TabIndex = 1;
//
// addButton
//
addButton.Location = new System.Drawing.Point(12, 540);
addButton.Name = "addButton";
addButton.Size = new System.Drawing.Size(75, 23);
addButton.TabIndex = 2;
addButton.Text = "Add";
addButton.UseVisualStyleBackColor = true;
//
// modifyButton
//
modifyButton.Location = new System.Drawing.Point(93, 540);
modifyButton.Name = "modifyButton";
modifyButton.Size = new System.Drawing.Size(75, 23);
modifyButton.TabIndex = 3;
modifyButton.Text = "Modify";
modifyButton.UseVisualStyleBackColor = true;
//
// deleteButton
//
deleteButton.Anchor = ((System.Windows.Forms.AnchorStyles)(System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right));
deleteButton.Location = new System.Drawing.Point(676, 540);
deleteButton.Name = "deleteButton";
deleteButton.Size = new System.Drawing.Size(75, 23);
deleteButton.TabIndex = 4;
deleteButton.Text = "Delete";
deleteButton.UseVisualStyleBackColor = true;
//
// showAllButton
//
showAllButton.Anchor = ((System.Windows.Forms.AnchorStyles)(System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right));
showAllButton.Location = new System.Drawing.Point(773, 185);
showAllButton.Name = "showAllButton";
showAllButton.Size = new System.Drawing.Size(227, 23);
showAllButton.TabIndex = 5;
showAllButton.Text = "Show All Appointments";
showAllButton.UseVisualStyleBackColor = true;
//
// appointmentDetails
//
appointmentDetails.Controls.Add(endTimeLabel);
appointmentDetails.Controls.Add(startTimeLabel);
appointmentDetails.Controls.Add(withLabel);
appointmentDetails.Controls.Add(apptTypeLabel);
appointmentDetails.Controls.Add(apptTitleLabel);
appointmentDetails.Location = new System.Drawing.Point(773, 214);
appointmentDetails.Name = "appointmentDetails";
appointmentDetails.Size = new System.Drawing.Size(223, 320);
appointmentDetails.TabIndex = 6;
appointmentDetails.TabStop = false;
appointmentDetails.Text = "Details";
//
// endTimeLabel
//
endTimeLabel.Location = new System.Drawing.Point(6, 111);
endTimeLabel.Name = "endTimeLabel";
endTimeLabel.Size = new System.Drawing.Size(211, 23);
endTimeLabel.TabIndex = 4;
endTimeLabel.Text = "End: ";
endTimeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// startTimeLabel
//
startTimeLabel.Location = new System.Drawing.Point(6, 88);
startTimeLabel.Name = "startTimeLabel";
startTimeLabel.Size = new System.Drawing.Size(211, 23);
startTimeLabel.TabIndex = 3;
startTimeLabel.Text = "Start: ";
startTimeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// withLabel
//
withLabel.Location = new System.Drawing.Point(6, 65);
withLabel.Name = "withLabel";
withLabel.Size = new System.Drawing.Size(211, 23);
withLabel.TabIndex = 2;
withLabel.Text = "With: ";
withLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// apptTypeLabel
//
apptTypeLabel.Location = new System.Drawing.Point(6, 42);
apptTypeLabel.Name = "apptTypeLabel";
apptTypeLabel.Size = new System.Drawing.Size(211, 23);
apptTypeLabel.TabIndex = 1;
apptTypeLabel.Text = "Type: ";
apptTypeLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// apptTitleLabel
//
apptTitleLabel.Location = new System.Drawing.Point(6, 19);
apptTitleLabel.Name = "apptTitleLabel";
apptTitleLabel.Size = new System.Drawing.Size(211, 23);
apptTitleLabel.TabIndex = 0;
apptTitleLabel.Text = "Title: ";
apptTitleLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
//
// AppointmentsForm
//
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
ClientSize = new System.Drawing.Size(1008, 575);
Controls.Add(appointmentDetails);
Controls.Add(showAllButton);
Controls.Add(deleteButton);
Controls.Add(modifyButton);
Controls.Add(addButton);
Controls.Add(calendar);
Controls.Add(appointmentDataView);
Text = "AppointmentsForm";
((System.ComponentModel.ISupportInitialize)appointmentDataView).EndInit();
appointmentDetails.ResumeLayout(false);
ResumeLayout(false);
}
private System.Windows.Forms.Label apptTypeLabel;
private System.Windows.Forms.Label withLabel;
private System.Windows.Forms.Label startTimeLabel;
private System.Windows.Forms.Label endTimeLabel;
private System.Windows.Forms.Label apptTitleLabel;
private System.Windows.Forms.GroupBox appointmentDetails;
private System.Windows.Forms.Button showAllButton;
private System.Windows.Forms.DataGridView appointmentDataView;
private System.Windows.Forms.MonthCalendar calendar;
private System.Windows.Forms.Button addButton;
private System.Windows.Forms.Button modifyButton;
private System.Windows.Forms.Button deleteButton;
#endregion
}

View File

@@ -0,0 +1,93 @@
using C969Project.Data;
using C969Project.Data.Models;
namespace C969Project;
public partial class AppointmentsForm : Form
{
private List<Appointment> _appointments = new();
private AddOrUpdateAppointmentForm _addOrUpdateAppointmentForm = new();
public AppointmentsForm()
{
InitializeComponent();
UpdateAppointmentsList(null, EventArgs.Empty);
Shown += UpdateAppointmentsList;
_addOrUpdateAppointmentForm.UpdateAppointmentsList += UpdateAppointmentsList;
calendar.DateSelected += ShowAppointmentsFromSelectedDay;
showAllButton.Click += UpdateAppointmentsList;
deleteButton.Click += DeleteButtonOnClick;
addButton.Click += AddButtonOnClick;
modifyButton.Click += ModifyButtonOnClick;
appointmentDataView.SelectionChanged += UpdateAppointmentDetails;
}
private void ModifyButtonOnClick(object? sender, EventArgs e)
{
if (appointmentDataView.CurrentRow?.DataBoundItem is Appointment selectedAppointment)
{
_addOrUpdateAppointmentForm.InitUpdate(selectedAppointment);
}
else
{
MessageBox.Show("Error while trying to modify appointment");
}
}
private void AddButtonOnClick(object? sender, EventArgs e)
{
_addOrUpdateAppointmentForm.InitAdd();
}
private void DeleteButtonOnClick(object? sender, EventArgs e)
{
Appointment? selectedAppointment;
if (appointmentDataView.CurrentRow?.DataBoundItem is Appointment appointment)
{
selectedAppointment = appointment;
}
else
{
MessageBox.Show("Error while trying to delete appointment");
return;
}
var result = MessageBox.Show("Are you sure you want to delete this appointment?", "Delete Appointment?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (result == DialogResult.OK)
{
DatabaseHelper.DeleteAppointment(selectedAppointment);
UpdateAppointmentsList(null, EventArgs.Empty);
}
}
private void UpdateAppointmentsList(object? sender, EventArgs e)
{
appointmentDataView.DataSource = null;
_appointments.Clear();
_appointments.AddRange(DatabaseHelper.RetrieveAppointments(AppState.CurrentUser.UserId));
appointmentDataView.DataSource = _appointments;
}
private void ShowAppointmentsFromSelectedDay(object? sender, EventArgs e)
{
var startDate = calendar.SelectionStart.ToUniversalTime();
var selectedDate = startDate.Date;
List<Appointment>? selectedAppointments = _appointments.Where(a => a.Start.Date == selectedDate).ToList();
appointmentDataView.DataSource = selectedAppointments?.Count > 0 ? selectedAppointments : null;
}
private void UpdateAppointmentDetails(object? sender, EventArgs e)
{
if (appointmentDataView.CurrentRow?.DataBoundItem is Appointment appointment)
{
apptTitleLabel.Text = $"Title: {appointment.Title}";
apptTypeLabel.Text = $"Type: {appointment.AppointmentType}";
withLabel.Text = $"With: {DatabaseHelper.RetrieveCustomer(appointment.CustomerId)?.CustomerName ?? "Unknown"}";
startTimeLabel.Text = $"Start: {appointment.Start.ToLocalTime():MM/dd/yyyy hh:mm tt} {TimeZoneInfo.Local.Id}";
endTimeLabel.Text = $"End: {appointment.End.ToLocalTime():MM/dd/yyyy hh:mm tt} {TimeZoneInfo.Local.Id}";
}
}
}

View File

@@ -0,0 +1,101 @@
using System.ComponentModel;
namespace C969Project;
partial class CustomersForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
CustomersDataGrid = new System.Windows.Forms.DataGridView();
AddButton = new System.Windows.Forms.Button();
ModifyButton = new System.Windows.Forms.Button();
DeleteButton = new System.Windows.Forms.Button();
((System.ComponentModel.ISupportInitialize)CustomersDataGrid).BeginInit();
SuspendLayout();
//
// CustomersDataGrid
//
CustomersDataGrid.AllowUserToAddRows = false;
CustomersDataGrid.AllowUserToDeleteRows = false;
CustomersDataGrid.AllowUserToOrderColumns = true;
CustomersDataGrid.Location = new System.Drawing.Point(12, 12);
CustomersDataGrid.Name = "CustomersDataGrid";
CustomersDataGrid.ReadOnly = true;
CustomersDataGrid.Size = new System.Drawing.Size(873, 430);
CustomersDataGrid.TabIndex = 0;
//
// AddButton
//
AddButton.Location = new System.Drawing.Point(12, 448);
AddButton.Name = "AddButton";
AddButton.Size = new System.Drawing.Size(75, 23);
AddButton.TabIndex = 1;
AddButton.Text = "Add";
AddButton.UseVisualStyleBackColor = true;
//
// ModifyButton
//
ModifyButton.Location = new System.Drawing.Point(93, 448);
ModifyButton.Name = "ModifyButton";
ModifyButton.Size = new System.Drawing.Size(75, 23);
ModifyButton.TabIndex = 2;
ModifyButton.Text = "Modify";
ModifyButton.UseVisualStyleBackColor = true;
//
// DeleteButton
//
DeleteButton.Location = new System.Drawing.Point(810, 448);
DeleteButton.Name = "DeleteButton";
DeleteButton.Size = new System.Drawing.Size(75, 23);
DeleteButton.TabIndex = 3;
DeleteButton.Text = "Delete";
DeleteButton.UseVisualStyleBackColor = true;
//
// RecordsForm
//
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
ClientSize = new System.Drawing.Size(897, 569);
Controls.Add(DeleteButton);
Controls.Add(ModifyButton);
Controls.Add(AddButton);
Controls.Add(CustomersDataGrid);
Text = "Records";
((System.ComponentModel.ISupportInitialize)CustomersDataGrid).EndInit();
ResumeLayout(false);
}
private System.Windows.Forms.Button ModifyButton;
private System.Windows.Forms.Button DeleteButton;
private System.Windows.Forms.Button AddButton;
private System.Windows.Forms.DataGridView CustomersDataGrid;
#endregion
}

View File

@@ -0,0 +1,58 @@
using C969Project.Data;
using C969Project.Data.Models;
namespace C969Project;
public partial class CustomersForm : Form
{
private List<Customer>? _customers;
private AddUpdateCustomerForm _form = new();
public CustomersForm()
{
InitializeComponent();
UpdateCustomersList(null, EventArgs.Empty);
Shown += UpdateCustomersList;
_form.UpdateCustomersList += UpdateCustomersList;
AddButton.Click += (sender, args) =>
{
_form.InitAdd();
};
ModifyButton.Click += (sender, args) =>
{
if (_customers is null) return;
var selectedCustomer = _customers[CustomersDataGrid.CurrentCell.RowIndex];
_form.InitUpdate(selectedCustomer);
};
DeleteButton.Click += (sender, args) =>
{
if (CustomersDataGrid.CurrentCell is null || CustomersDataGrid.CurrentCell.RowIndex > _customers?.Count)
{
MessageBox.Show("Please select a customer to delete");
return;
}
var selectedCustomer = _customers?[CustomersDataGrid.CurrentCell.RowIndex];
var result = MessageBox.Show("Are you sure you want to delete this record?", "Delete Record", MessageBoxButtons.OKCancel, MessageBoxIcon.Question);
if (result == DialogResult.OK)
{
_customers.Remove(selectedCustomer);
DatabaseHelper.DeleteCustomer(selectedCustomer);
UpdateCustomersList(null, EventArgs.Empty);
}
};
}
public void UpdateCustomersList(object? sender, EventArgs args)
{
if (_customers != null && _customers.Count > 0) _customers.Clear();
_customers = DatabaseHelper.RetrieveCustomers();
CustomersDataGrid.DataSource = _customers;
}
}

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="$this.Locked" type="System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e">
<value>True</value>
</metadata>
</root>

View File

@@ -0,0 +1,97 @@
using System.ComponentModel;
namespace C969Project;
partial class DashboardForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
CustomersButton = new System.Windows.Forms.Button();
AppointmentsButton = new System.Windows.Forms.Button();
label1 = new System.Windows.Forms.Label();
ReportsButton = new System.Windows.Forms.Button();
SuspendLayout();
//
// CustomersButton
//
CustomersButton.Location = new System.Drawing.Point(339, 185);
CustomersButton.Name = "CustomersButton";
CustomersButton.Size = new System.Drawing.Size(100, 100);
CustomersButton.TabIndex = 0;
CustomersButton.Text = "Customers";
CustomersButton.UseVisualStyleBackColor = true;
//
// AppointmentsButton
//
AppointmentsButton.Location = new System.Drawing.Point(445, 185);
AppointmentsButton.Name = "AppointmentsButton";
AppointmentsButton.Size = new System.Drawing.Size(100, 100);
AppointmentsButton.TabIndex = 1;
AppointmentsButton.Text = "Appointments";
AppointmentsButton.UseVisualStyleBackColor = true;
//
// label1
//
label1.Font = new System.Drawing.Font("Segoe UI", 15F);
label1.Location = new System.Drawing.Point(332, 116);
label1.Name = "label1";
label1.Size = new System.Drawing.Size(113, 40);
label1.TabIndex = 4;
label1.Text = "Dashboard";
label1.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// ReportsButton
//
ReportsButton.Location = new System.Drawing.Point(233, 185);
ReportsButton.Name = "ReportsButton";
ReportsButton.Size = new System.Drawing.Size(100, 100);
ReportsButton.TabIndex = 2;
ReportsButton.Text = "Reports";
ReportsButton.UseVisualStyleBackColor = true;
//
// DashboardForm
//
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
ClientSize = new System.Drawing.Size(800, 450);
Controls.Add(label1);
Controls.Add(CustomersButton);
Controls.Add(AppointmentsButton);
Controls.Add(ReportsButton);
Text = "DashboardForm";
ResumeLayout(false);
}
private System.Windows.Forms.Label label1;
private System.Windows.Forms.Button CustomersButton;
private System.Windows.Forms.Button AppointmentsButton;
private System.Windows.Forms.Button ReportsButton;
#endregion
}

View File

@@ -0,0 +1,29 @@
namespace C969Project;
public partial class DashboardForm : Form
{
private CustomersForm _customersForm = new();
private AppointmentsForm _appointmentsForm = new();
private ReportsForm _reportsForm = new();
public DashboardForm()
{
InitializeComponent();
CustomersButton.Click += (sender, args) =>
{
_customersForm.ShowDialog();
_customersForm.UpdateCustomersList(null, EventArgs.Empty);
};
AppointmentsButton.Click += (sender, args) =>
{
_appointmentsForm.ShowDialog();
};
ReportsButton.Click += (sender, args) =>
{
_reportsForm.ShowDialog();
};
}
}

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="$this.Locked" type="System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e">
<value>True</value>
</metadata>
</root>

107
C969Project/Forms/LoginForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,107 @@
namespace C969Project
{
partial class LoginForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
usernameTextBox = new System.Windows.Forms.TextBox();
passwordTextBox = new System.Windows.Forms.TextBox();
loginButton = new System.Windows.Forms.Button();
panel1 = new System.Windows.Forms.Panel();
loginLabel = new System.Windows.Forms.Label();
panel1.SuspendLayout();
SuspendLayout();
//
// usernameTextBox
//
usernameTextBox.Location = new System.Drawing.Point(241, 147);
usernameTextBox.Name = "usernameTextBox";
usernameTextBox.PlaceholderText = "Username";
usernameTextBox.Size = new System.Drawing.Size(228, 23);
usernameTextBox.TabIndex = 1;
//
// passwordTextBox
//
passwordTextBox.Location = new System.Drawing.Point(241, 205);
passwordTextBox.Name = "passwordTextBox";
passwordTextBox.PlaceholderText = "Password";
passwordTextBox.Size = new System.Drawing.Size(228, 23);
passwordTextBox.TabIndex = 2;
//
// loginButton
//
loginButton.Location = new System.Drawing.Point(241, 259);
loginButton.Name = "loginButton";
loginButton.Size = new System.Drawing.Size(228, 23);
loginButton.TabIndex = 3;
loginButton.Text = "Login";
loginButton.UseVisualStyleBackColor = true;
//
// panel1
//
panel1.Controls.Add(loginLabel);
panel1.Controls.Add(loginButton);
panel1.Controls.Add(passwordTextBox);
panel1.Controls.Add(usernameTextBox);
panel1.Location = new System.Drawing.Point(12, 12);
panel1.Name = "panel1";
panel1.Size = new System.Drawing.Size(776, 426);
panel1.TabIndex = 0;
//
// loginLabel
//
loginLabel.Font = new System.Drawing.Font("Segoe UI", 10F);
loginLabel.Location = new System.Drawing.Point(241, 99);
loginLabel.Name = "loginLabel";
loginLabel.Size = new System.Drawing.Size(228, 40);
loginLabel.TabIndex = 4;
loginLabel.Text = "Login";
loginLabel.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
//
// LoginForm
//
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
ClientSize = new System.Drawing.Size(800, 450);
Controls.Add(panel1);
Text = "Login";
panel1.ResumeLayout(false);
panel1.PerformLayout();
ResumeLayout(false);
}
private System.Windows.Forms.Label loginLabel;
private System.Windows.Forms.TextBox usernameTextBox;
private System.Windows.Forms.TextBox passwordTextBox;
private System.Windows.Forms.Button loginButton;
private System.Windows.Forms.Panel panel1;
#endregion
}
}

View File

@@ -0,0 +1,94 @@
using C969Project.Data;
using C969Project.Data.Models;
namespace C969Project
{
public partial class LoginForm : Form
{
public LoginForm()
{
InitializeComponent();
loginLabel.Text = Localization.GetLocalization("login_text");
usernameTextBox.PlaceholderText = Localization.GetLocalization("username_text");
passwordTextBox.PlaceholderText = Localization.GetLocalization("password_text");
loginButton.Text = Localization.GetLocalization("login_text");
loginButton.Enabled = false;
usernameTextBox.TextChanged += (sender, args) => {UpdateLoginButtonState();};
passwordTextBox.TextChanged += (sender, args) => {UpdateLoginButtonState();};
loginButton.Click += LoginButtonOnClick;
}
private void LoginButtonOnClick(object? sender, EventArgs e)
{
var usr = DatabaseHelper.Login(usernameTextBox.Text, passwordTextBox.Text);
if (usr is null)
{
MessageBox.Show(Localization.GetLocalization("login_error_message"), "", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
LogHistory(usr);
Console.WriteLine($"Login successful, {usr.Username}");
AppState.CurrentUser = usr;
CheckForAppointments();
var dash = new DashboardForm();
dash.FormClosing += (o, args) => { Close(); };
dash.Show();
Hide();
}
private void CheckForAppointments()
{
if (AppState.CurrentUser is null)
{
MessageBox.Show("A problem occured retrieving appointments.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
var appointments = DatabaseHelper.RetrieveAppointments(AppState.CurrentUser.UserId);
DateTime nowUtc = DateTime.UtcNow;
DateTime fifteenMinutesFromNowUtc = nowUtc.AddMinutes(15);
var upcoming = appointments
.Where(a => a.Start >= nowUtc && a.Start <= fifteenMinutesFromNowUtc)
.OrderBy(a => a.Start)
.ToList();
if (upcoming.Any())
{
var appt = upcoming.First();
DateTime localStart = appt.Start.ToLocalTime();
MessageBox.Show(
$"You have an upcoming {appt.AppointmentType} appointment '{appt.Title}' at {localStart}.",
"Upcoming Appointment",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
private void UpdateLoginButtonState()
{
if (string.IsNullOrEmpty(usernameTextBox.Text) || string.IsNullOrEmpty(passwordTextBox.Text))
{
loginButton.Enabled = false;
}
else
{
loginButton.Enabled = true;
}
}
private void LogHistory(User user)
{
string text = $"{DateTime.UtcNow} UTC : {user.Username}";
using StreamWriter sw = new StreamWriter("Login_History.txt", true);
sw.WriteLine(text);
}
}
}

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="$this.Locked" type="System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e">
<value>True</value>
</metadata>
</root>

195
C969Project/Forms/ReportsForm.Designer.cs generated Normal file
View File

@@ -0,0 +1,195 @@
using System.ComponentModel;
namespace C969Project;
partial class ReportsForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
tabControl1 = new System.Windows.Forms.TabControl();
apptByMothTabPage = new System.Windows.Forms.TabPage();
refreshButton1 = new System.Windows.Forms.Button();
apptByMonthDataGrid = new System.Windows.Forms.DataGridView();
userSchedulesTabPage = new System.Windows.Forms.TabPage();
userScheduleDataGrid = new System.Windows.Forms.DataGridView();
userComboBox = new System.Windows.Forms.ComboBox();
refreshButton2 = new System.Windows.Forms.Button();
customersByCityTabPage = new System.Windows.Forms.TabPage();
refreshButton3 = new System.Windows.Forms.Button();
customersByCityDataGrid = new System.Windows.Forms.DataGridView();
tabControl1.SuspendLayout();
apptByMothTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)apptByMonthDataGrid).BeginInit();
userSchedulesTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)userScheduleDataGrid).BeginInit();
customersByCityTabPage.SuspendLayout();
((System.ComponentModel.ISupportInitialize)customersByCityDataGrid).BeginInit();
SuspendLayout();
//
// tabControl1
//
tabControl1.Controls.Add(apptByMothTabPage);
tabControl1.Controls.Add(userSchedulesTabPage);
tabControl1.Controls.Add(customersByCityTabPage);
tabControl1.Location = new System.Drawing.Point(12, 12);
tabControl1.Name = "tabControl1";
tabControl1.SelectedIndex = 0;
tabControl1.Size = new System.Drawing.Size(776, 426);
tabControl1.TabIndex = 0;
//
// apptByMothTabPage
//
apptByMothTabPage.Controls.Add(refreshButton1);
apptByMothTabPage.Controls.Add(apptByMonthDataGrid);
apptByMothTabPage.Location = new System.Drawing.Point(4, 24);
apptByMothTabPage.Name = "apptByMothTabPage";
apptByMothTabPage.Padding = new System.Windows.Forms.Padding(3);
apptByMothTabPage.Size = new System.Drawing.Size(768, 398);
apptByMothTabPage.TabIndex = 0;
apptByMothTabPage.Text = "Appts By Month";
apptByMothTabPage.UseVisualStyleBackColor = true;
//
// refreshButton1
//
refreshButton1.Location = new System.Drawing.Point(672, 369);
refreshButton1.Name = "refreshButton1";
refreshButton1.Size = new System.Drawing.Size(90, 23);
refreshButton1.TabIndex = 2;
refreshButton1.Text = "Refresh";
refreshButton1.UseVisualStyleBackColor = true;
//
// apptByMonthDataGrid
//
apptByMonthDataGrid.Location = new System.Drawing.Point(6, 6);
apptByMonthDataGrid.Name = "apptByMonthDataGrid";
apptByMonthDataGrid.ReadOnly = true;
apptByMonthDataGrid.Size = new System.Drawing.Size(756, 357);
apptByMonthDataGrid.TabIndex = 1;
//
// userSchedulesTabPage
//
userSchedulesTabPage.Controls.Add(userScheduleDataGrid);
userSchedulesTabPage.Controls.Add(userComboBox);
userSchedulesTabPage.Controls.Add(refreshButton2);
userSchedulesTabPage.Location = new System.Drawing.Point(4, 24);
userSchedulesTabPage.Name = "userSchedulesTabPage";
userSchedulesTabPage.Padding = new System.Windows.Forms.Padding(3);
userSchedulesTabPage.Size = new System.Drawing.Size(768, 398);
userSchedulesTabPage.TabIndex = 1;
userSchedulesTabPage.Text = "User Schedules";
userSchedulesTabPage.UseVisualStyleBackColor = true;
//
// userScheduleDataGrid
//
userScheduleDataGrid.Location = new System.Drawing.Point(6, 35);
userScheduleDataGrid.Name = "userScheduleDataGrid";
userScheduleDataGrid.Size = new System.Drawing.Size(756, 357);
userScheduleDataGrid.TabIndex = 5;
//
// userComboBox
//
userComboBox.FormattingEnabled = true;
userComboBox.Location = new System.Drawing.Point(6, 6);
userComboBox.Name = "userComboBox";
userComboBox.Size = new System.Drawing.Size(660, 23);
userComboBox.TabIndex = 4;
//
// refreshButton2
//
refreshButton2.Location = new System.Drawing.Point(672, 6);
refreshButton2.Name = "refreshButton2";
refreshButton2.Size = new System.Drawing.Size(90, 23);
refreshButton2.TabIndex = 3;
refreshButton2.Text = "Refresh";
refreshButton2.UseVisualStyleBackColor = true;
//
// customersByCityTabPage
//
customersByCityTabPage.Controls.Add(refreshButton3);
customersByCityTabPage.Controls.Add(customersByCityDataGrid);
customersByCityTabPage.Location = new System.Drawing.Point(4, 24);
customersByCityTabPage.Name = "customersByCityTabPage";
customersByCityTabPage.Size = new System.Drawing.Size(768, 398);
customersByCityTabPage.TabIndex = 2;
customersByCityTabPage.Text = "Customers By City";
customersByCityTabPage.UseVisualStyleBackColor = true;
//
// refreshButton3
//
refreshButton3.Location = new System.Drawing.Point(675, 372);
refreshButton3.Name = "refreshButton3";
refreshButton3.Size = new System.Drawing.Size(90, 23);
refreshButton3.TabIndex = 3;
refreshButton3.Text = "Refresh";
refreshButton3.UseVisualStyleBackColor = true;
//
// customersByCityDataGrid
//
customersByCityDataGrid.Location = new System.Drawing.Point(3, 3);
customersByCityDataGrid.Name = "customersByCityDataGrid";
customersByCityDataGrid.ReadOnly = true;
customersByCityDataGrid.Size = new System.Drawing.Size(762, 363);
customersByCityDataGrid.TabIndex = 2;
//
// ReportsForm
//
AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
ClientSize = new System.Drawing.Size(800, 450);
Controls.Add(tabControl1);
Text = "ReportsForm";
tabControl1.ResumeLayout(false);
apptByMothTabPage.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)apptByMonthDataGrid).EndInit();
userSchedulesTabPage.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)userScheduleDataGrid).EndInit();
customersByCityTabPage.ResumeLayout(false);
((System.ComponentModel.ISupportInitialize)customersByCityDataGrid).EndInit();
ResumeLayout(false);
}
private System.Windows.Forms.DataGridView customersByCityDataGrid;
private System.Windows.Forms.Button refreshButton3;
private System.Windows.Forms.DataGridView userScheduleDataGrid;
private System.Windows.Forms.ComboBox userComboBox;
private System.Windows.Forms.Button refreshButton2;
private System.Windows.Forms.Button refreshButton1;
private System.Windows.Forms.TabPage customersByCityTabPage;
private System.Windows.Forms.DataGridView apptByMonthDataGrid;
private System.Windows.Forms.TabControl tabControl1;
private System.Windows.Forms.TabPage apptByMothTabPage;
private System.Windows.Forms.TabPage userSchedulesTabPage;
#endregion
}

View File

@@ -0,0 +1,172 @@
using C969Project.Data;
using C969Project.Data.Models;
namespace C969Project;
public partial class ReportsForm : Form
{
private string[] _months =
[
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
private string[] _appointmentTypes =
[
"Scrum", "Presentation", "Other"
];
public ReportsForm()
{
InitializeComponent();
ApptTypeByMonth_GenerateReport();
refreshButton1.Click += (sender, args) => { ApptTypeByMonth_GenerateReport(); };
UserSchedule_UpdateUsers();
userComboBox.SelectedIndexChanged += (sender, args) => { UserSchedule_GenerateReport(); };
userComboBox.SelectedIndex = -1;
refreshButton2.Click += (sender, args) =>
{
UserSchedule_UpdateUsers();
UserSchedule_GenerateReport();
};
CustomersByCity_GenerateReport();
refreshButton3.Click += (sender, args) => { CustomersByCity_GenerateReport(); };
}
#region Apptointments types by Month
private void ApptTypeByMonth_GenerateReport()
{
apptByMonthDataGrid.DataSource = null;
List<AppointmentTypeByMonth> appointmentTypes = new();
var appointments = DatabaseHelper.RetrieveAppointments();
foreach (var month in _months)
{
foreach (var type in _appointmentTypes)
{
int count = appointments.Count(a => a.Start.ToString("MMMM") == month && a.AppointmentType == type);
appointmentTypes.Add(new AppointmentTypeByMonth(month, type, count));
}
}
apptByMonthDataGrid.DataSource = appointmentTypes;
}
private class AppointmentTypeByMonth
{
public string Month { get; set; }
public string AppointmentType { get; set; }
public int Count { get; set; }
public AppointmentTypeByMonth(string month, string appointmentType, int count)
{
Month = month;
AppointmentType = appointmentType;
Count = count;
}
}
#endregion
#region User Schedule
private void UserSchedule_GenerateReport()
{
userScheduleDataGrid.DataSource = null;
User? selectedUser = (User?)userComboBox.SelectedItem;
List<UserSchedule> userSchedules = new();
var appointments = DatabaseHelper.RetrieveAppointments();
var usersAppointments = appointments
.FindAll(a => a.UserId == selectedUser.UserId)
.ToList();
if (usersAppointments.Count == 0)
{
MessageBox.Show("No appointments found for the selected user.", "No Appointments", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
foreach (var appointment in usersAppointments)
{
userSchedules.Add(new UserSchedule(
selectedUser.Username,
appointment.Title,
appointment.AppointmentType,
appointment.Start.ToLocalTime().ToString("MM/dd/yyyy hh:mm ") + TimeZoneInfo.Local.Id,
appointment.End.ToLocalTime().ToString("MM/dd/yyyy hh:mm ") + TimeZoneInfo.Local.Id
));
}
userScheduleDataGrid.DataSource = userSchedules;
}
private void UserSchedule_UpdateUsers()
{
userComboBox.DataSource = null;
userComboBox.DataSource = DatabaseHelper.RetrieveUsers();
userComboBox.SelectedIndex = -1;
}
private class UserSchedule
{
public string Username { get; set; }
public string AppointmentName { get; set; }
public string AppointmentType { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public UserSchedule(string username, string appointmentName, string appointmentType, string startDate, string endDate)
{
Username = username;
AppointmentName = appointmentType;
AppointmentType = appointmentType;
StartDate = startDate;
EndDate = endDate;
}
}
#endregion
#region Number of Users by City
private void CustomersByCity_GenerateReport()
{
customersByCityDataGrid.DataSource = null;
var customers = DatabaseHelper.RetrieveCustomers();
var cityCounts = customers
.Select(c =>
{
var addr = DatabaseHelper.RetrieveAddress(c.AddressId);
var city = addr != null ? DatabaseHelper.RetrieveCity(addr.CityId) : null;
return city?.CityName;
})
.Where(cityName => !string.IsNullOrEmpty(cityName))
.GroupBy(cityName => cityName)
.Select(g => new CustomersByCity(g.Key, g.Count()))
.ToList();
customersByCityDataGrid.DataSource = cityCounts;
}
private class CustomersByCity
{
public string? City { get; set; }
public int Count { get; set; }
public CustomersByCity(string? city, int count)
{
City = city;
Count = count;
}
}
#endregion
}

View File

@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="$this.Locked" type="System.Boolean, System.Private.CoreLib, Version=8.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e">
<value>True</value>
</metadata>
</root>