Continued development
This commit is contained in:
parent
289657a7d5
commit
691a999bae
|
|
@ -225,44 +225,6 @@ namespace trakker.Data
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/// <summary>
|
|
||||||
/// Executes arbitrary, ad-hoc SQL against the database inside a transaction.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="sql">A SQL statement to execute. The caller is responsible for
|
|
||||||
/// ensuring the SQL is safe and properly parameterized to avoid SQL injection.</param>
|
|
||||||
/// <remarks>
|
|
||||||
/// This method is intended for one-off maintenance or administrative commands.
|
|
||||||
/// It does not return any result; if a scalar value is produced by the SQL,
|
|
||||||
/// the current implementation captures it but does not expose it to the caller.
|
|
||||||
/// </remarks>
|
|
||||||
public void Adhoc(string sql)
|
|
||||||
{
|
|
||||||
using var conn = OpenConnection();
|
|
||||||
using var tx = conn.BeginTransaction();
|
|
||||||
|
|
||||||
int? result = 0;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
using (var cmd = conn.CreateCommand())
|
|
||||||
{
|
|
||||||
cmd.Transaction = tx;
|
|
||||||
cmd.CommandText = sql;
|
|
||||||
cmd.ExecuteNonQuery();
|
|
||||||
}
|
|
||||||
|
|
||||||
using var idCmd = conn.CreateCommand();
|
|
||||||
idCmd.Transaction = tx;
|
|
||||||
result = (int?)idCmd.ExecuteScalar() ;
|
|
||||||
|
|
||||||
tx.Commit();
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
tx.Rollback();
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,5 +25,44 @@ namespace trakker.Data
|
||||||
conn.Open();
|
conn.Open();
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes arbitrary, ad-hoc SQL against the database inside a transaction.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sql">A SQL statement to execute. The caller is responsible for
|
||||||
|
/// ensuring the SQL is safe and properly parameterized to avoid SQL injection.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// This method is intended for one-off maintenance or administrative commands.
|
||||||
|
/// It does not return any result; if a scalar value is produced by the SQL,
|
||||||
|
/// the current implementation captures it but does not expose it to the caller.
|
||||||
|
/// </remarks>
|
||||||
|
public void Adhoc(string sql)
|
||||||
|
{
|
||||||
|
using var conn = OpenConnection();
|
||||||
|
using var tx = conn.BeginTransaction();
|
||||||
|
|
||||||
|
int? result = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var cmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
cmd.Transaction = tx;
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
using var idCmd = conn.CreateCommand();
|
||||||
|
idCmd.Transaction = tx;
|
||||||
|
result = (int?)idCmd.ExecuteScalar() ;
|
||||||
|
|
||||||
|
tx.Commit();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
tx.Rollback();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,232 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using trakker.Models;
|
||||||
|
|
||||||
|
namespace trakker.Data
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Provides data access methods for the <see cref="Models.Project"/> entity.
|
||||||
|
/// This class encapsulates database operations such as upsert, delete and ad-hoc
|
||||||
|
/// SQL execution for projects. It inherits from <see cref="DataAccess"/> which
|
||||||
|
/// provides connection management.
|
||||||
|
/// </summary>
|
||||||
|
internal class ProjectData(string connectionString) : DataAccess(connectionString)
|
||||||
|
{
|
||||||
|
public BindingList<Project> Get(string? projectId = null)
|
||||||
|
{
|
||||||
|
var results = new BindingList<Project>();
|
||||||
|
|
||||||
|
string whereClause = "1 = 1";
|
||||||
|
if (projectId != null)
|
||||||
|
{
|
||||||
|
whereClause = "p.project_id = $project_id";
|
||||||
|
}
|
||||||
|
|
||||||
|
string sql = $@"
|
||||||
|
SELECT
|
||||||
|
p.project_id,
|
||||||
|
p.client_id,
|
||||||
|
p.project_code,
|
||||||
|
c.name AS client_name,
|
||||||
|
p.name AS project_name,
|
||||||
|
p.description,
|
||||||
|
p.start_date,
|
||||||
|
p.end_date,
|
||||||
|
p.budget,
|
||||||
|
p.status,
|
||||||
|
p.hourly_rate,
|
||||||
|
p.notes,
|
||||||
|
p.created_at,
|
||||||
|
p.updated_at
|
||||||
|
FROM projects p
|
||||||
|
LEFT JOIN clients c ON p.client_id = c.client_id
|
||||||
|
WHERE p.status = 'active'
|
||||||
|
AND {whereClause}
|
||||||
|
ORDER BY p.start_date DESC, p.name ASC;
|
||||||
|
;
|
||||||
|
";
|
||||||
|
|
||||||
|
using var conn = OpenConnection();
|
||||||
|
using var cmd = conn.CreateCommand();
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
|
||||||
|
if (projectId != null)
|
||||||
|
{
|
||||||
|
cmd.Parameters.AddWithValue("$project_id", projectId);
|
||||||
|
}
|
||||||
|
using var reader = cmd.ExecuteReader();
|
||||||
|
|
||||||
|
var _var1 = reader.GetOrdinal("project_id");
|
||||||
|
var _var2 = reader.GetOrdinal("client_id");
|
||||||
|
var _var3 = reader.GetOrdinal("project_code");
|
||||||
|
var _var4 = reader.GetOrdinal("client_name");
|
||||||
|
var _var5 = reader.GetOrdinal("project_name");
|
||||||
|
var _var6 = reader.GetOrdinal("description");
|
||||||
|
var _var7 = reader.GetOrdinal("start_date");
|
||||||
|
var _var8 = reader.GetOrdinal("end_date");
|
||||||
|
var _var9 = reader.GetOrdinal("budget");
|
||||||
|
var _var10 = reader.GetOrdinal("status");
|
||||||
|
var _var11 = reader.GetOrdinal("hourly_rate");
|
||||||
|
var _var12 = reader.GetOrdinal("notes");
|
||||||
|
var _var13 = reader.GetOrdinal("created_at");
|
||||||
|
var _var14 = reader.GetOrdinal("updated_at");
|
||||||
|
|
||||||
|
while (reader.Read())
|
||||||
|
{
|
||||||
|
results.Add(new Project
|
||||||
|
{
|
||||||
|
ProjectId = reader.GetString(_var1),
|
||||||
|
ClientId = reader.GetString(_var2),
|
||||||
|
ProjectCode = reader.GetString(_var3),
|
||||||
|
ClientName = reader.GetString(_var4),
|
||||||
|
ProjectName = reader.GetString(_var5),
|
||||||
|
Description = reader.GetString(_var6),
|
||||||
|
StartDate = reader.IsDBNull(_var7) ? null : reader.GetDateTime(_var7),
|
||||||
|
EndDate = reader.IsDBNull(_var8) ? null : reader.GetDateTime(_var8),
|
||||||
|
Budget = reader.GetDecimal(_var9),
|
||||||
|
Status = reader.GetString(_var10),
|
||||||
|
HourlyRate = reader.GetDecimal(_var11),
|
||||||
|
Notes = reader.GetString(_var12),
|
||||||
|
CreatedAt = reader.GetDateTime(_var13),
|
||||||
|
UpdatedAt = reader.GetDateTime(_var14),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Inserts a new project record or updates an existing one (upsert) using
|
||||||
|
/// the provided <paramref name="project"/> model. This method executes
|
||||||
|
/// a single SQL statement inside a transaction and will commit on
|
||||||
|
/// success or roll back on failure.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="project">The <see cref="Client"/> model to insert or update. Must not be null.</param>
|
||||||
|
/// <remarks>
|
||||||
|
/// The SQL statement uses an ON CONFLICT clause to perform the update when a
|
||||||
|
/// matching <c>project_id</c> already exists. Parameter names correspond to the
|
||||||
|
/// project model property names.
|
||||||
|
/// </remarks>
|
||||||
|
public void Upsert(Project project)
|
||||||
|
{
|
||||||
|
const string sql = @"
|
||||||
|
INSERT INTO projects (
|
||||||
|
project_id,
|
||||||
|
client_id,
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
start_date,
|
||||||
|
end_date,
|
||||||
|
budget,
|
||||||
|
status,
|
||||||
|
hourly_rate,
|
||||||
|
notes
|
||||||
|
)
|
||||||
|
VALUES (
|
||||||
|
$project_id,
|
||||||
|
$client_id,
|
||||||
|
$name,
|
||||||
|
$description,
|
||||||
|
$start_date,
|
||||||
|
$end_date,
|
||||||
|
$budget,
|
||||||
|
$status,
|
||||||
|
$hourly_rate,
|
||||||
|
$notes
|
||||||
|
)
|
||||||
|
ON CONFLICT (project_id) DO UPDATE SET
|
||||||
|
client_id = excluded.client_id,
|
||||||
|
name = excluded.name,
|
||||||
|
description = excluded.description,
|
||||||
|
start_date = excluded.start_date,
|
||||||
|
end_date = excluded.end_date,
|
||||||
|
budget = excluded.budget,
|
||||||
|
status = excluded.status,
|
||||||
|
hourly_rate = excluded.hourly_rate,
|
||||||
|
notes = excluded.notes,
|
||||||
|
updated_at = CURRENT_TIMESTAMP;
|
||||||
|
";
|
||||||
|
|
||||||
|
using var conn = OpenConnection();
|
||||||
|
using var tx = conn.BeginTransaction();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var cmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
cmd.Transaction = tx;
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
cmd.Parameters.AddWithValue("$project_id", project.ProjectId);
|
||||||
|
cmd.Parameters.AddWithValue("$client_id", project.ClientId);
|
||||||
|
cmd.Parameters.AddWithValue("$name", project.ProjectName);
|
||||||
|
cmd.Parameters.AddWithValue("$description", project.Description);
|
||||||
|
cmd.Parameters.AddWithValue("$start_date", project.StartDate);
|
||||||
|
cmd.Parameters.AddWithValue("$end_date", project.EndDate);
|
||||||
|
cmd.Parameters.AddWithValue("$budget", project.Budget);
|
||||||
|
cmd.Parameters.AddWithValue("$status", project.Status);
|
||||||
|
cmd.Parameters.AddWithValue("$hourly_rate", project.HourlyRate);
|
||||||
|
cmd.Parameters.AddWithValue("$notes", project.Notes);
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.Commit();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
tx.Rollback();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Deletes the project with the specified <paramref name="projectId"/> from the
|
||||||
|
/// database.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="projectId">The identifier of the project to delete.</param>
|
||||||
|
/// <returns>An optional integer representing any scalar value returned by the
|
||||||
|
/// command executed after deletion (if applicable). May be null.</returns>
|
||||||
|
/// <remarks>
|
||||||
|
/// The method executes within a transaction. The current implementation attempts
|
||||||
|
/// to read a scalar value after the delete; that value depends on surrounding
|
||||||
|
/// database triggers or commands and may be null.
|
||||||
|
/// </remarks>
|
||||||
|
public int? Delete(string projectId)
|
||||||
|
{
|
||||||
|
const string sql = @"
|
||||||
|
DELETE FROM
|
||||||
|
projects
|
||||||
|
WHERE
|
||||||
|
project_id = $project_id
|
||||||
|
;
|
||||||
|
";
|
||||||
|
|
||||||
|
using var conn = OpenConnection();
|
||||||
|
using var tx = conn.BeginTransaction();
|
||||||
|
|
||||||
|
int? result = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using (var cmd = conn.CreateCommand())
|
||||||
|
{
|
||||||
|
cmd.Transaction = tx;
|
||||||
|
cmd.CommandText = sql;
|
||||||
|
cmd.Parameters.AddWithValue("$project_id", projectId);
|
||||||
|
cmd.ExecuteNonQuery();
|
||||||
|
}
|
||||||
|
|
||||||
|
using var idCmd = conn.CreateCommand();
|
||||||
|
idCmd.Transaction = tx;
|
||||||
|
result = (int?)idCmd.ExecuteScalar() ;
|
||||||
|
|
||||||
|
tx.Commit();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
tx.Rollback();
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -34,16 +34,20 @@
|
||||||
MainForm_StatusStrip = new StatusStrip();
|
MainForm_StatusStrip = new StatusStrip();
|
||||||
tabControlMainForm = new TabControl();
|
tabControlMainForm = new TabControl();
|
||||||
MainForm_TabPage1 = new TabPage();
|
MainForm_TabPage1 = new TabPage();
|
||||||
button1 = new Button();
|
|
||||||
MainForm_TabPage2 = new TabPage();
|
MainForm_TabPage2 = new TabPage();
|
||||||
tableLayoutPanel1Tab2 = new TableLayoutPanel();
|
tableLayoutPanelClients1 = new TableLayoutPanel();
|
||||||
dataGridViewClients = new DataGridView();
|
dataGridViewClients = new DataGridView();
|
||||||
|
MainForm_TabPage3 = new TabPage();
|
||||||
|
tableLayoutPanelProjects1 = new TableLayoutPanel();
|
||||||
|
dataGridViewProjects = new DataGridView();
|
||||||
MainForm_MenuStrip.SuspendLayout();
|
MainForm_MenuStrip.SuspendLayout();
|
||||||
tabControlMainForm.SuspendLayout();
|
tabControlMainForm.SuspendLayout();
|
||||||
MainForm_TabPage1.SuspendLayout();
|
|
||||||
MainForm_TabPage2.SuspendLayout();
|
MainForm_TabPage2.SuspendLayout();
|
||||||
tableLayoutPanel1Tab2.SuspendLayout();
|
tableLayoutPanelClients1.SuspendLayout();
|
||||||
((System.ComponentModel.ISupportInitialize)dataGridViewClients).BeginInit();
|
((System.ComponentModel.ISupportInitialize)dataGridViewClients).BeginInit();
|
||||||
|
MainForm_TabPage3.SuspendLayout();
|
||||||
|
tableLayoutPanelProjects1.SuspendLayout();
|
||||||
|
((System.ComponentModel.ISupportInitialize)dataGridViewProjects).BeginInit();
|
||||||
SuspendLayout();
|
SuspendLayout();
|
||||||
//
|
//
|
||||||
// MainForm_MenuStrip
|
// MainForm_MenuStrip
|
||||||
|
|
@ -52,7 +56,7 @@
|
||||||
MainForm_MenuStrip.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem });
|
MainForm_MenuStrip.Items.AddRange(new ToolStripItem[] { fileToolStripMenuItem });
|
||||||
MainForm_MenuStrip.Location = new Point(0, 0);
|
MainForm_MenuStrip.Location = new Point(0, 0);
|
||||||
MainForm_MenuStrip.Name = "MainForm_MenuStrip";
|
MainForm_MenuStrip.Name = "MainForm_MenuStrip";
|
||||||
MainForm_MenuStrip.Size = new Size(1343, 40);
|
MainForm_MenuStrip.Size = new Size(1878, 40);
|
||||||
MainForm_MenuStrip.TabIndex = 0;
|
MainForm_MenuStrip.TabIndex = 0;
|
||||||
MainForm_MenuStrip.Text = "menuStrip1";
|
MainForm_MenuStrip.Text = "menuStrip1";
|
||||||
//
|
//
|
||||||
|
|
@ -73,9 +77,9 @@
|
||||||
// MainForm_StatusStrip
|
// MainForm_StatusStrip
|
||||||
//
|
//
|
||||||
MainForm_StatusStrip.ImageScalingSize = new Size(32, 32);
|
MainForm_StatusStrip.ImageScalingSize = new Size(32, 32);
|
||||||
MainForm_StatusStrip.Location = new Point(0, 983);
|
MainForm_StatusStrip.Location = new Point(0, 1060);
|
||||||
MainForm_StatusStrip.Name = "MainForm_StatusStrip";
|
MainForm_StatusStrip.Name = "MainForm_StatusStrip";
|
||||||
MainForm_StatusStrip.Size = new Size(1343, 22);
|
MainForm_StatusStrip.Size = new Size(1878, 22);
|
||||||
MainForm_StatusStrip.TabIndex = 1;
|
MainForm_StatusStrip.TabIndex = 1;
|
||||||
MainForm_StatusStrip.Text = "MainForm_StatusStrip";
|
MainForm_StatusStrip.Text = "MainForm_StatusStrip";
|
||||||
//
|
//
|
||||||
|
|
@ -83,37 +87,27 @@
|
||||||
//
|
//
|
||||||
tabControlMainForm.Controls.Add(MainForm_TabPage1);
|
tabControlMainForm.Controls.Add(MainForm_TabPage1);
|
||||||
tabControlMainForm.Controls.Add(MainForm_TabPage2);
|
tabControlMainForm.Controls.Add(MainForm_TabPage2);
|
||||||
|
tabControlMainForm.Controls.Add(MainForm_TabPage3);
|
||||||
tabControlMainForm.Dock = DockStyle.Fill;
|
tabControlMainForm.Dock = DockStyle.Fill;
|
||||||
tabControlMainForm.Location = new Point(0, 40);
|
tabControlMainForm.Location = new Point(0, 40);
|
||||||
tabControlMainForm.Name = "tabControlMainForm";
|
tabControlMainForm.Name = "tabControlMainForm";
|
||||||
tabControlMainForm.SelectedIndex = 0;
|
tabControlMainForm.SelectedIndex = 0;
|
||||||
tabControlMainForm.Size = new Size(1343, 943);
|
tabControlMainForm.Size = new Size(1878, 1020);
|
||||||
tabControlMainForm.TabIndex = 2;
|
tabControlMainForm.TabIndex = 2;
|
||||||
//
|
//
|
||||||
// MainForm_TabPage1
|
// MainForm_TabPage1
|
||||||
//
|
//
|
||||||
MainForm_TabPage1.Controls.Add(button1);
|
|
||||||
MainForm_TabPage1.Location = new Point(8, 46);
|
MainForm_TabPage1.Location = new Point(8, 46);
|
||||||
MainForm_TabPage1.Name = "MainForm_TabPage1";
|
MainForm_TabPage1.Name = "MainForm_TabPage1";
|
||||||
MainForm_TabPage1.Padding = new Padding(3);
|
MainForm_TabPage1.Padding = new Padding(3);
|
||||||
MainForm_TabPage1.Size = new Size(1327, 889);
|
MainForm_TabPage1.Size = new Size(1862, 966);
|
||||||
MainForm_TabPage1.TabIndex = 0;
|
MainForm_TabPage1.TabIndex = 0;
|
||||||
MainForm_TabPage1.Text = "Tab 1";
|
MainForm_TabPage1.Text = "Tab 1";
|
||||||
MainForm_TabPage1.UseVisualStyleBackColor = true;
|
MainForm_TabPage1.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// button1
|
|
||||||
//
|
|
||||||
button1.Location = new Point(39, 47);
|
|
||||||
button1.Name = "button1";
|
|
||||||
button1.Size = new Size(150, 46);
|
|
||||||
button1.TabIndex = 0;
|
|
||||||
button1.Text = "button1";
|
|
||||||
button1.UseVisualStyleBackColor = true;
|
|
||||||
button1.Click += button1_Click;
|
|
||||||
//
|
|
||||||
// MainForm_TabPage2
|
// MainForm_TabPage2
|
||||||
//
|
//
|
||||||
MainForm_TabPage2.Controls.Add(tableLayoutPanel1Tab2);
|
MainForm_TabPage2.Controls.Add(tableLayoutPanelClients1);
|
||||||
MainForm_TabPage2.Location = new Point(8, 46);
|
MainForm_TabPage2.Location = new Point(8, 46);
|
||||||
MainForm_TabPage2.Name = "MainForm_TabPage2";
|
MainForm_TabPage2.Name = "MainForm_TabPage2";
|
||||||
MainForm_TabPage2.Padding = new Padding(3);
|
MainForm_TabPage2.Padding = new Padding(3);
|
||||||
|
|
@ -122,20 +116,20 @@
|
||||||
MainForm_TabPage2.Text = "Tab 2";
|
MainForm_TabPage2.Text = "Tab 2";
|
||||||
MainForm_TabPage2.UseVisualStyleBackColor = true;
|
MainForm_TabPage2.UseVisualStyleBackColor = true;
|
||||||
//
|
//
|
||||||
// tableLayoutPanel1Tab2
|
// tableLayoutPanelClients1
|
||||||
//
|
//
|
||||||
tableLayoutPanel1Tab2.ColumnCount = 1;
|
tableLayoutPanelClients1.ColumnCount = 1;
|
||||||
tableLayoutPanel1Tab2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
tableLayoutPanelClients1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||||
tableLayoutPanel1Tab2.Controls.Add(dataGridViewClients, 0, 1);
|
tableLayoutPanelClients1.Controls.Add(dataGridViewClients, 0, 1);
|
||||||
tableLayoutPanel1Tab2.Dock = DockStyle.Fill;
|
tableLayoutPanelClients1.Dock = DockStyle.Fill;
|
||||||
tableLayoutPanel1Tab2.Location = new Point(3, 3);
|
tableLayoutPanelClients1.Location = new Point(3, 3);
|
||||||
tableLayoutPanel1Tab2.Name = "tableLayoutPanel1Tab2";
|
tableLayoutPanelClients1.Name = "tableLayoutPanelClients1";
|
||||||
tableLayoutPanel1Tab2.RowCount = 3;
|
tableLayoutPanelClients1.RowCount = 3;
|
||||||
tableLayoutPanel1Tab2.RowStyles.Add(new RowStyle(SizeType.Absolute, 1F));
|
tableLayoutPanelClients1.RowStyles.Add(new RowStyle(SizeType.Absolute, 1F));
|
||||||
tableLayoutPanel1Tab2.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
tableLayoutPanelClients1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||||
tableLayoutPanel1Tab2.RowStyles.Add(new RowStyle(SizeType.Absolute, 200F));
|
tableLayoutPanelClients1.RowStyles.Add(new RowStyle(SizeType.Absolute, 200F));
|
||||||
tableLayoutPanel1Tab2.Size = new Size(1321, 883);
|
tableLayoutPanelClients1.Size = new Size(1321, 883);
|
||||||
tableLayoutPanel1Tab2.TabIndex = 0;
|
tableLayoutPanelClients1.TabIndex = 0;
|
||||||
//
|
//
|
||||||
// dataGridViewClients
|
// dataGridViewClients
|
||||||
//
|
//
|
||||||
|
|
@ -150,11 +144,49 @@
|
||||||
dataGridViewClients.Size = new Size(1315, 676);
|
dataGridViewClients.Size = new Size(1315, 676);
|
||||||
dataGridViewClients.TabIndex = 0;
|
dataGridViewClients.TabIndex = 0;
|
||||||
//
|
//
|
||||||
|
// MainForm_TabPage3
|
||||||
|
//
|
||||||
|
MainForm_TabPage3.Controls.Add(tableLayoutPanelProjects1);
|
||||||
|
MainForm_TabPage3.Location = new Point(8, 46);
|
||||||
|
MainForm_TabPage3.Name = "MainForm_TabPage3";
|
||||||
|
MainForm_TabPage3.Size = new Size(1327, 889);
|
||||||
|
MainForm_TabPage3.TabIndex = 2;
|
||||||
|
MainForm_TabPage3.Text = "Tab 3";
|
||||||
|
MainForm_TabPage3.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// tableLayoutPanelProjects1
|
||||||
|
//
|
||||||
|
tableLayoutPanelProjects1.ColumnCount = 1;
|
||||||
|
tableLayoutPanelProjects1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanelProjects1.Controls.Add(dataGridViewProjects, 0, 1);
|
||||||
|
tableLayoutPanelProjects1.Dock = DockStyle.Fill;
|
||||||
|
tableLayoutPanelProjects1.Location = new Point(0, 0);
|
||||||
|
tableLayoutPanelProjects1.Name = "tableLayoutPanelProjects1";
|
||||||
|
tableLayoutPanelProjects1.RowCount = 3;
|
||||||
|
tableLayoutPanelProjects1.RowStyles.Add(new RowStyle(SizeType.Absolute, 1F));
|
||||||
|
tableLayoutPanelProjects1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanelProjects1.RowStyles.Add(new RowStyle(SizeType.Absolute, 200F));
|
||||||
|
tableLayoutPanelProjects1.Size = new Size(1327, 889);
|
||||||
|
tableLayoutPanelProjects1.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// dataGridViewProjects
|
||||||
|
//
|
||||||
|
dataGridViewProjects.AllowUserToAddRows = false;
|
||||||
|
dataGridViewProjects.AllowUserToDeleteRows = false;
|
||||||
|
dataGridViewProjects.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
|
||||||
|
dataGridViewProjects.Dock = DockStyle.Fill;
|
||||||
|
dataGridViewProjects.Location = new Point(3, 4);
|
||||||
|
dataGridViewProjects.Name = "dataGridViewProjects";
|
||||||
|
dataGridViewProjects.ReadOnly = true;
|
||||||
|
dataGridViewProjects.RowHeadersWidth = 82;
|
||||||
|
dataGridViewProjects.Size = new Size(1321, 682);
|
||||||
|
dataGridViewProjects.TabIndex = 0;
|
||||||
|
//
|
||||||
// MainForm
|
// MainForm
|
||||||
//
|
//
|
||||||
AutoScaleDimensions = new SizeF(13F, 32F);
|
AutoScaleDimensions = new SizeF(13F, 32F);
|
||||||
AutoScaleMode = AutoScaleMode.Font;
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
ClientSize = new Size(1343, 1005);
|
ClientSize = new Size(1878, 1082);
|
||||||
Controls.Add(tabControlMainForm);
|
Controls.Add(tabControlMainForm);
|
||||||
Controls.Add(MainForm_StatusStrip);
|
Controls.Add(MainForm_StatusStrip);
|
||||||
Controls.Add(MainForm_MenuStrip);
|
Controls.Add(MainForm_MenuStrip);
|
||||||
|
|
@ -164,10 +196,12 @@
|
||||||
MainForm_MenuStrip.ResumeLayout(false);
|
MainForm_MenuStrip.ResumeLayout(false);
|
||||||
MainForm_MenuStrip.PerformLayout();
|
MainForm_MenuStrip.PerformLayout();
|
||||||
tabControlMainForm.ResumeLayout(false);
|
tabControlMainForm.ResumeLayout(false);
|
||||||
MainForm_TabPage1.ResumeLayout(false);
|
|
||||||
MainForm_TabPage2.ResumeLayout(false);
|
MainForm_TabPage2.ResumeLayout(false);
|
||||||
tableLayoutPanel1Tab2.ResumeLayout(false);
|
tableLayoutPanelClients1.ResumeLayout(false);
|
||||||
((System.ComponentModel.ISupportInitialize)dataGridViewClients).EndInit();
|
((System.ComponentModel.ISupportInitialize)dataGridViewClients).EndInit();
|
||||||
|
MainForm_TabPage3.ResumeLayout(false);
|
||||||
|
tableLayoutPanelProjects1.ResumeLayout(false);
|
||||||
|
((System.ComponentModel.ISupportInitialize)dataGridViewProjects).EndInit();
|
||||||
ResumeLayout(false);
|
ResumeLayout(false);
|
||||||
PerformLayout();
|
PerformLayout();
|
||||||
}
|
}
|
||||||
|
|
@ -181,8 +215,10 @@
|
||||||
private TabPage MainForm_TabPage2;
|
private TabPage MainForm_TabPage2;
|
||||||
private ToolStripMenuItem fileToolStripMenuItem;
|
private ToolStripMenuItem fileToolStripMenuItem;
|
||||||
private ToolStripMenuItem MainForm_Exit_MenuItem;
|
private ToolStripMenuItem MainForm_Exit_MenuItem;
|
||||||
private Button button1;
|
private TableLayoutPanel tableLayoutPanelClients1;
|
||||||
private TableLayoutPanel tableLayoutPanel1Tab2;
|
|
||||||
private DataGridView dataGridViewClients;
|
private DataGridView dataGridViewClients;
|
||||||
|
private TabPage MainForm_TabPage3;
|
||||||
|
private TableLayoutPanel tableLayoutPanelProjects1;
|
||||||
|
private DataGridView dataGridViewProjects;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ namespace trakker
|
||||||
|
|
||||||
tabControlMainForm.TabPages[0].Text = " Home ";
|
tabControlMainForm.TabPages[0].Text = " Home ";
|
||||||
tabControlMainForm.TabPages[1].Text = " Clients ";
|
tabControlMainForm.TabPages[1].Text = " Clients ";
|
||||||
|
tabControlMainForm.TabPages[2].Text = " Projects ";
|
||||||
|
|
||||||
_ctrl = new Services.MainCtrl(this, connectionString);
|
_ctrl = new Services.MainCtrl(this, connectionString);
|
||||||
}
|
}
|
||||||
|
|
@ -58,11 +59,11 @@ namespace trakker
|
||||||
dataGridViewClients.AutoGenerateColumns = false;
|
dataGridViewClients.AutoGenerateColumns = false;
|
||||||
dataGridViewClients.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
|
dataGridViewClients.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
|
||||||
dataGridViewClients.BackgroundColor = Color.White;
|
dataGridViewClients.BackgroundColor = Color.White;
|
||||||
dataGridViewClients.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
|
||||||
dataGridViewClients.RowHeadersVisible = false;
|
|
||||||
dataGridViewClients.ColumnHeadersVisible = true;
|
dataGridViewClients.ColumnHeadersVisible = true;
|
||||||
dataGridViewClients.MultiSelect = false;
|
|
||||||
dataGridViewClients.DataSource = clients;
|
dataGridViewClients.DataSource = clients;
|
||||||
|
dataGridViewClients.MultiSelect = false;
|
||||||
|
dataGridViewClients.RowHeadersVisible = false;
|
||||||
|
dataGridViewClients.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||||
|
|
||||||
dataGridViewClients.Columns.Clear();
|
dataGridViewClients.Columns.Clear();
|
||||||
{
|
{
|
||||||
|
|
@ -146,23 +147,160 @@ namespace trakker
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
public void FillDataGridViewProjects(BindingSource projects)
|
||||||
private void button1_Click(object sender, EventArgs e)
|
|
||||||
{
|
{
|
||||||
var dialog = new ClientForm(new Client());
|
dataGridViewProjects.DataSource = projects;
|
||||||
|
}
|
||||||
|
public void InitDataGridViewProjects()
|
||||||
|
{
|
||||||
|
dataGridViewProjects.AllowUserToAddRows = true;
|
||||||
|
dataGridViewProjects.AllowUserToDeleteRows = true;
|
||||||
|
dataGridViewProjects.AutoGenerateColumns = false;
|
||||||
|
dataGridViewProjects.BackgroundColor = Color.White;
|
||||||
|
dataGridViewProjects.ColumnHeadersVisible = true;
|
||||||
|
dataGridViewProjects.MultiSelect = false;
|
||||||
|
dataGridViewProjects.RowHeadersVisible = false;
|
||||||
|
dataGridViewProjects.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||||
|
|
||||||
|
dataGridViewProjects.Columns.Clear();
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.None,
|
||||||
|
DataPropertyName = "ProjectName",
|
||||||
|
Name = "Project Name",
|
||||||
|
Visible = true,
|
||||||
|
Width = 350,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "ClientName",
|
||||||
|
Name = "Client Name",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "StartDate",
|
||||||
|
DefaultCellStyle = { Format = "MM/dd/yyyy" },
|
||||||
|
Name = "Start Date",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "EndDate",
|
||||||
|
DefaultCellStyle = { Format = "MM/dd/yyyy" },
|
||||||
|
Name = "End Date",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "HourlyRate",
|
||||||
|
Name = "Hourly Rate",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
textColumn.DefaultCellStyle.Format = "$#,##0.00";
|
||||||
|
textColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
|
||||||
|
textColumn.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight;
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "Budget",
|
||||||
|
Name = "Budget",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
textColumn.DefaultCellStyle.Format = "$#,##0.00";
|
||||||
|
textColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
|
||||||
|
textColumn.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight;
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "Status",
|
||||||
|
Name = "Status",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataGridViewProjects.DoubleClick += (s, e) =>
|
||||||
|
{
|
||||||
|
if (dataGridViewProjects.SelectedRows.Count > 0)
|
||||||
|
{
|
||||||
|
var selectedProject = dataGridViewProjects.SelectedRows[0].DataBoundItem as Project;
|
||||||
|
if (selectedProject != null)
|
||||||
|
{
|
||||||
|
var dialog = new ProjectForm(selectedProject, _ctrl.GetClients());
|
||||||
if (dialog.ShowDialog(this) == DialogResult.OK)
|
if (dialog.ShowDialog(this) == DialogResult.OK)
|
||||||
{
|
{
|
||||||
Client client = dialog.Client;
|
Project project = dialog.Project;
|
||||||
ClientData clientData = new ClientData(connectionString);
|
ProjectData projectData = new ProjectData(connectionString);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
clientData.Upsert(client);
|
projectData.Upsert(project);
|
||||||
|
_ctrl.LoadProjects(); // Reload projects to update the DataGridView with any changes
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
MessageBox.Show($"Error saving client: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
MessageBox.Show($"Error saving project: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dataGridViewClients.SelectionChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (dataGridViewClients.SelectedRows.Count > 0)
|
||||||
|
{
|
||||||
|
var selectedClient = dataGridViewClients.SelectedRows[0].DataBoundItem as Client;
|
||||||
|
if (selectedClient != null)
|
||||||
|
{
|
||||||
|
// Handle the selected client as needed
|
||||||
|
// MessageBox.Show($"Selected Client: {selectedClient.AddressStreet}", "Client Selected", MessageBoxButtons.OK, MessageBoxIcon.Information );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//private void button1_Click(object sender, EventArgs e)
|
||||||
|
//{
|
||||||
|
// var dialog = new ClientForm(new Client());
|
||||||
|
// if (dialog.ShowDialog(this) == DialogResult.OK)
|
||||||
|
// {
|
||||||
|
// Client client = dialog.Client;
|
||||||
|
// ClientData clientData = new ClientData(connectionString);
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// clientData.Upsert(client);
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// MessageBox.Show($"Error saving client: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,435 @@
|
||||||
|
namespace trakker.Forms
|
||||||
|
{
|
||||||
|
partial class ProjectForm
|
||||||
|
{
|
||||||
|
/// <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()
|
||||||
|
{
|
||||||
|
groupBoxNewClient = new GroupBox();
|
||||||
|
tableLayoutPanel1 = new TableLayoutPanel();
|
||||||
|
tableLayoutPanel2 = new TableLayoutPanel();
|
||||||
|
labelClient = new Label();
|
||||||
|
labelName = new Label();
|
||||||
|
labelDescription = new Label();
|
||||||
|
labelStartDate = new Label();
|
||||||
|
labelHourlyRate = new Label();
|
||||||
|
textBoxName = new TextBox();
|
||||||
|
comboBoxClient = new ComboBox();
|
||||||
|
tableLayoutPanel6 = new TableLayoutPanel();
|
||||||
|
dateTimePickerStartDate = new DateTimePicker();
|
||||||
|
dateTimePickerEndDate = new DateTimePicker();
|
||||||
|
labelEndDate = new Label();
|
||||||
|
richTextBoxDescription = new RichTextBox();
|
||||||
|
tableLayoutPanel4 = new TableLayoutPanel();
|
||||||
|
labelBudget = new Label();
|
||||||
|
labelStatus = new Label();
|
||||||
|
comboBoxStatus = new ComboBox();
|
||||||
|
textBoxHourlyRate = new TextBox();
|
||||||
|
textBoxBudget = new TextBox();
|
||||||
|
groupBoxNotes = new GroupBox();
|
||||||
|
richTextBoxNotes = new RichTextBox();
|
||||||
|
tableLayoutPanel3 = new TableLayoutPanel();
|
||||||
|
buttonOkay = new Button();
|
||||||
|
buttonCancel = new Button();
|
||||||
|
labelCreatedUpdatedDT = new Label();
|
||||||
|
groupBoxNewClient.SuspendLayout();
|
||||||
|
tableLayoutPanel1.SuspendLayout();
|
||||||
|
tableLayoutPanel2.SuspendLayout();
|
||||||
|
tableLayoutPanel6.SuspendLayout();
|
||||||
|
tableLayoutPanel4.SuspendLayout();
|
||||||
|
groupBoxNotes.SuspendLayout();
|
||||||
|
tableLayoutPanel3.SuspendLayout();
|
||||||
|
SuspendLayout();
|
||||||
|
//
|
||||||
|
// groupBoxNewClient
|
||||||
|
//
|
||||||
|
groupBoxNewClient.Controls.Add(tableLayoutPanel1);
|
||||||
|
groupBoxNewClient.Dock = DockStyle.Fill;
|
||||||
|
groupBoxNewClient.Location = new Point(0, 0);
|
||||||
|
groupBoxNewClient.Name = "groupBoxNewClient";
|
||||||
|
groupBoxNewClient.Size = new Size(1144, 660);
|
||||||
|
groupBoxNewClient.TabIndex = 1;
|
||||||
|
groupBoxNewClient.TabStop = false;
|
||||||
|
groupBoxNewClient.Text = "New Client";
|
||||||
|
//
|
||||||
|
// tableLayoutPanel1
|
||||||
|
//
|
||||||
|
tableLayoutPanel1.ColumnCount = 1;
|
||||||
|
tableLayoutPanel1.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanel1.Controls.Add(tableLayoutPanel2, 0, 0);
|
||||||
|
tableLayoutPanel1.Controls.Add(groupBoxNotes, 0, 1);
|
||||||
|
tableLayoutPanel1.Controls.Add(tableLayoutPanel3, 0, 2);
|
||||||
|
tableLayoutPanel1.Dock = DockStyle.Fill;
|
||||||
|
tableLayoutPanel1.Location = new Point(3, 35);
|
||||||
|
tableLayoutPanel1.Name = "tableLayoutPanel1";
|
||||||
|
tableLayoutPanel1.RowCount = 3;
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 242F));
|
||||||
|
tableLayoutPanel1.RowStyles.Add(new RowStyle(SizeType.Absolute, 75F));
|
||||||
|
tableLayoutPanel1.Size = new Size(1138, 622);
|
||||||
|
tableLayoutPanel1.TabIndex = 0;
|
||||||
|
//
|
||||||
|
// tableLayoutPanel2
|
||||||
|
//
|
||||||
|
tableLayoutPanel2.ColumnCount = 2;
|
||||||
|
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 150F));
|
||||||
|
tableLayoutPanel2.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanel2.Controls.Add(labelClient, 0, 0);
|
||||||
|
tableLayoutPanel2.Controls.Add(labelName, 0, 1);
|
||||||
|
tableLayoutPanel2.Controls.Add(labelDescription, 0, 2);
|
||||||
|
tableLayoutPanel2.Controls.Add(labelStartDate, 0, 3);
|
||||||
|
tableLayoutPanel2.Controls.Add(labelHourlyRate, 0, 4);
|
||||||
|
tableLayoutPanel2.Controls.Add(textBoxName, 1, 1);
|
||||||
|
tableLayoutPanel2.Controls.Add(comboBoxClient, 1, 0);
|
||||||
|
tableLayoutPanel2.Controls.Add(tableLayoutPanel6, 1, 3);
|
||||||
|
tableLayoutPanel2.Controls.Add(richTextBoxDescription, 1, 2);
|
||||||
|
tableLayoutPanel2.Controls.Add(tableLayoutPanel4, 1, 4);
|
||||||
|
tableLayoutPanel2.Dock = DockStyle.Fill;
|
||||||
|
tableLayoutPanel2.Location = new Point(3, 3);
|
||||||
|
tableLayoutPanel2.Name = "tableLayoutPanel2";
|
||||||
|
tableLayoutPanel2.RowCount = 5;
|
||||||
|
tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
|
||||||
|
tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
|
||||||
|
tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 100F));
|
||||||
|
tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
|
||||||
|
tableLayoutPanel2.RowStyles.Add(new RowStyle(SizeType.Absolute, 50F));
|
||||||
|
tableLayoutPanel2.Size = new Size(1132, 299);
|
||||||
|
tableLayoutPanel2.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// labelClient
|
||||||
|
//
|
||||||
|
labelClient.AutoSize = true;
|
||||||
|
labelClient.Dock = DockStyle.Fill;
|
||||||
|
labelClient.Location = new Point(3, 0);
|
||||||
|
labelClient.Name = "labelClient";
|
||||||
|
labelClient.Size = new Size(144, 50);
|
||||||
|
labelClient.TabIndex = 0;
|
||||||
|
labelClient.Text = "Client *";
|
||||||
|
//
|
||||||
|
// labelName
|
||||||
|
//
|
||||||
|
labelName.AutoSize = true;
|
||||||
|
labelName.Dock = DockStyle.Fill;
|
||||||
|
labelName.Location = new Point(3, 50);
|
||||||
|
labelName.Name = "labelName";
|
||||||
|
labelName.Size = new Size(144, 50);
|
||||||
|
labelName.TabIndex = 0;
|
||||||
|
labelName.Text = "Name *";
|
||||||
|
//
|
||||||
|
// labelDescription
|
||||||
|
//
|
||||||
|
labelDescription.AutoSize = true;
|
||||||
|
labelDescription.Dock = DockStyle.Fill;
|
||||||
|
labelDescription.Location = new Point(3, 100);
|
||||||
|
labelDescription.Name = "labelDescription";
|
||||||
|
labelDescription.Size = new Size(144, 100);
|
||||||
|
labelDescription.TabIndex = 0;
|
||||||
|
labelDescription.Text = "Description";
|
||||||
|
//
|
||||||
|
// labelStartDate
|
||||||
|
//
|
||||||
|
labelStartDate.AutoSize = true;
|
||||||
|
labelStartDate.Dock = DockStyle.Fill;
|
||||||
|
labelStartDate.Location = new Point(3, 200);
|
||||||
|
labelStartDate.Name = "labelStartDate";
|
||||||
|
labelStartDate.Size = new Size(144, 50);
|
||||||
|
labelStartDate.TabIndex = 0;
|
||||||
|
labelStartDate.Text = "Start Date";
|
||||||
|
//
|
||||||
|
// labelHourlyRate
|
||||||
|
//
|
||||||
|
labelHourlyRate.AutoSize = true;
|
||||||
|
labelHourlyRate.Dock = DockStyle.Fill;
|
||||||
|
labelHourlyRate.Location = new Point(3, 250);
|
||||||
|
labelHourlyRate.Name = "labelHourlyRate";
|
||||||
|
labelHourlyRate.Size = new Size(144, 50);
|
||||||
|
labelHourlyRate.TabIndex = 0;
|
||||||
|
labelHourlyRate.Text = "Hourly Rate";
|
||||||
|
//
|
||||||
|
// textBoxName
|
||||||
|
//
|
||||||
|
textBoxName.Dock = DockStyle.Left;
|
||||||
|
textBoxName.Location = new Point(153, 53);
|
||||||
|
textBoxName.Name = "textBoxName";
|
||||||
|
textBoxName.PlaceholderText = "Project X";
|
||||||
|
textBoxName.Size = new Size(913, 39);
|
||||||
|
textBoxName.TabIndex = 2;
|
||||||
|
textBoxName.Validating += textBoxName_Validating;
|
||||||
|
//
|
||||||
|
// comboBoxClient
|
||||||
|
//
|
||||||
|
comboBoxClient.Dock = DockStyle.Fill;
|
||||||
|
comboBoxClient.FlatStyle = FlatStyle.Flat;
|
||||||
|
comboBoxClient.FormattingEnabled = true;
|
||||||
|
comboBoxClient.Location = new Point(153, 3);
|
||||||
|
comboBoxClient.Name = "comboBoxClient";
|
||||||
|
comboBoxClient.Size = new Size(976, 40);
|
||||||
|
comboBoxClient.TabIndex = 1;
|
||||||
|
//
|
||||||
|
// tableLayoutPanel6
|
||||||
|
//
|
||||||
|
tableLayoutPanel6.ColumnCount = 3;
|
||||||
|
tableLayoutPanel6.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
|
||||||
|
tableLayoutPanel6.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
|
||||||
|
tableLayoutPanel6.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 40F));
|
||||||
|
tableLayoutPanel6.Controls.Add(dateTimePickerStartDate, 0, 0);
|
||||||
|
tableLayoutPanel6.Controls.Add(dateTimePickerEndDate, 2, 0);
|
||||||
|
tableLayoutPanel6.Controls.Add(labelEndDate, 1, 0);
|
||||||
|
tableLayoutPanel6.Dock = DockStyle.Fill;
|
||||||
|
tableLayoutPanel6.Location = new Point(153, 203);
|
||||||
|
tableLayoutPanel6.Name = "tableLayoutPanel6";
|
||||||
|
tableLayoutPanel6.RowCount = 1;
|
||||||
|
tableLayoutPanel6.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanel6.Size = new Size(976, 44);
|
||||||
|
tableLayoutPanel6.TabIndex = 7;
|
||||||
|
//
|
||||||
|
// dateTimePickerStartDate
|
||||||
|
//
|
||||||
|
dateTimePickerStartDate.Format = DateTimePickerFormat.Short;
|
||||||
|
dateTimePickerStartDate.Location = new Point(3, 3);
|
||||||
|
dateTimePickerStartDate.Name = "dateTimePickerStartDate";
|
||||||
|
dateTimePickerStartDate.Size = new Size(384, 39);
|
||||||
|
dateTimePickerStartDate.TabIndex = 0;
|
||||||
|
dateTimePickerStartDate.TabStop = false;
|
||||||
|
//
|
||||||
|
// dateTimePickerEndDate
|
||||||
|
//
|
||||||
|
dateTimePickerEndDate.Format = DateTimePickerFormat.Short;
|
||||||
|
dateTimePickerEndDate.Location = new Point(588, 3);
|
||||||
|
dateTimePickerEndDate.Name = "dateTimePickerEndDate";
|
||||||
|
dateTimePickerEndDate.Size = new Size(385, 39);
|
||||||
|
dateTimePickerEndDate.TabIndex = 1;
|
||||||
|
dateTimePickerEndDate.TabStop = false;
|
||||||
|
//
|
||||||
|
// labelEndDate
|
||||||
|
//
|
||||||
|
labelEndDate.AutoSize = true;
|
||||||
|
labelEndDate.Dock = DockStyle.Fill;
|
||||||
|
labelEndDate.Location = new Point(393, 0);
|
||||||
|
labelEndDate.Name = "labelEndDate";
|
||||||
|
labelEndDate.Size = new Size(189, 44);
|
||||||
|
labelEndDate.TabIndex = 2;
|
||||||
|
labelEndDate.Text = "End Date";
|
||||||
|
labelEndDate.TextAlign = ContentAlignment.TopCenter;
|
||||||
|
//
|
||||||
|
// richTextBoxDescription
|
||||||
|
//
|
||||||
|
richTextBoxDescription.Dock = DockStyle.Fill;
|
||||||
|
richTextBoxDescription.Location = new Point(153, 103);
|
||||||
|
richTextBoxDescription.Name = "richTextBoxDescription";
|
||||||
|
richTextBoxDescription.Size = new Size(976, 94);
|
||||||
|
richTextBoxDescription.TabIndex = 3;
|
||||||
|
richTextBoxDescription.Text = "";
|
||||||
|
//
|
||||||
|
// tableLayoutPanel4
|
||||||
|
//
|
||||||
|
tableLayoutPanel4.ColumnCount = 5;
|
||||||
|
tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
|
||||||
|
tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
|
||||||
|
tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
|
||||||
|
tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
|
||||||
|
tableLayoutPanel4.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 20F));
|
||||||
|
tableLayoutPanel4.Controls.Add(labelBudget, 1, 0);
|
||||||
|
tableLayoutPanel4.Controls.Add(labelStatus, 3, 0);
|
||||||
|
tableLayoutPanel4.Controls.Add(comboBoxStatus, 4, 0);
|
||||||
|
tableLayoutPanel4.Controls.Add(textBoxHourlyRate, 0, 0);
|
||||||
|
tableLayoutPanel4.Controls.Add(textBoxBudget, 2, 0);
|
||||||
|
tableLayoutPanel4.Dock = DockStyle.Fill;
|
||||||
|
tableLayoutPanel4.Location = new Point(153, 253);
|
||||||
|
tableLayoutPanel4.Name = "tableLayoutPanel4";
|
||||||
|
tableLayoutPanel4.RowCount = 1;
|
||||||
|
tableLayoutPanel4.RowStyles.Add(new RowStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanel4.Size = new Size(976, 44);
|
||||||
|
tableLayoutPanel4.TabIndex = 9;
|
||||||
|
//
|
||||||
|
// labelBudget
|
||||||
|
//
|
||||||
|
labelBudget.AutoSize = true;
|
||||||
|
labelBudget.Dock = DockStyle.Fill;
|
||||||
|
labelBudget.Location = new Point(198, 0);
|
||||||
|
labelBudget.Name = "labelBudget";
|
||||||
|
labelBudget.Size = new Size(189, 44);
|
||||||
|
labelBudget.TabIndex = 0;
|
||||||
|
labelBudget.Text = "Budget";
|
||||||
|
labelBudget.TextAlign = ContentAlignment.TopCenter;
|
||||||
|
//
|
||||||
|
// labelStatus
|
||||||
|
//
|
||||||
|
labelStatus.AutoSize = true;
|
||||||
|
labelStatus.Dock = DockStyle.Fill;
|
||||||
|
labelStatus.Location = new Point(588, 0);
|
||||||
|
labelStatus.Name = "labelStatus";
|
||||||
|
labelStatus.Size = new Size(189, 44);
|
||||||
|
labelStatus.TabIndex = 1;
|
||||||
|
labelStatus.Text = "Status";
|
||||||
|
labelStatus.TextAlign = ContentAlignment.TopCenter;
|
||||||
|
//
|
||||||
|
// comboBoxStatus
|
||||||
|
//
|
||||||
|
comboBoxStatus.FlatStyle = FlatStyle.Flat;
|
||||||
|
comboBoxStatus.FormattingEnabled = true;
|
||||||
|
comboBoxStatus.Location = new Point(783, 3);
|
||||||
|
comboBoxStatus.Name = "comboBoxStatus";
|
||||||
|
comboBoxStatus.Size = new Size(190, 40);
|
||||||
|
comboBoxStatus.TabIndex = 6;
|
||||||
|
//
|
||||||
|
// textBoxHourlyRate
|
||||||
|
//
|
||||||
|
textBoxHourlyRate.Location = new Point(3, 3);
|
||||||
|
textBoxHourlyRate.Name = "textBoxHourlyRate";
|
||||||
|
textBoxHourlyRate.Size = new Size(189, 39);
|
||||||
|
textBoxHourlyRate.TabIndex = 7;
|
||||||
|
//
|
||||||
|
// textBoxBudget
|
||||||
|
//
|
||||||
|
textBoxBudget.Location = new Point(393, 3);
|
||||||
|
textBoxBudget.Name = "textBoxBudget";
|
||||||
|
textBoxBudget.Size = new Size(189, 39);
|
||||||
|
textBoxBudget.TabIndex = 8;
|
||||||
|
//
|
||||||
|
// groupBoxNotes
|
||||||
|
//
|
||||||
|
groupBoxNotes.Controls.Add(richTextBoxNotes);
|
||||||
|
groupBoxNotes.Dock = DockStyle.Fill;
|
||||||
|
groupBoxNotes.Location = new Point(3, 308);
|
||||||
|
groupBoxNotes.Name = "groupBoxNotes";
|
||||||
|
groupBoxNotes.Size = new Size(1132, 236);
|
||||||
|
groupBoxNotes.TabIndex = 0;
|
||||||
|
groupBoxNotes.TabStop = false;
|
||||||
|
groupBoxNotes.Text = "Notes";
|
||||||
|
//
|
||||||
|
// richTextBoxNotes
|
||||||
|
//
|
||||||
|
richTextBoxNotes.Dock = DockStyle.Fill;
|
||||||
|
richTextBoxNotes.Location = new Point(3, 35);
|
||||||
|
richTextBoxNotes.Name = "richTextBoxNotes";
|
||||||
|
richTextBoxNotes.Size = new Size(1126, 198);
|
||||||
|
richTextBoxNotes.TabIndex = 7;
|
||||||
|
richTextBoxNotes.Text = "";
|
||||||
|
//
|
||||||
|
// tableLayoutPanel3
|
||||||
|
//
|
||||||
|
tableLayoutPanel3.ColumnCount = 3;
|
||||||
|
tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 100F));
|
||||||
|
tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 200F));
|
||||||
|
tableLayoutPanel3.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, 200F));
|
||||||
|
tableLayoutPanel3.Controls.Add(buttonOkay, 1, 0);
|
||||||
|
tableLayoutPanel3.Controls.Add(buttonCancel, 2, 0);
|
||||||
|
tableLayoutPanel3.Controls.Add(labelCreatedUpdatedDT, 0, 0);
|
||||||
|
tableLayoutPanel3.Dock = DockStyle.Fill;
|
||||||
|
tableLayoutPanel3.Location = new Point(3, 550);
|
||||||
|
tableLayoutPanel3.Name = "tableLayoutPanel3";
|
||||||
|
tableLayoutPanel3.RowCount = 1;
|
||||||
|
tableLayoutPanel3.RowStyles.Add(new RowStyle(SizeType.Absolute, 75F));
|
||||||
|
tableLayoutPanel3.Size = new Size(1132, 69);
|
||||||
|
tableLayoutPanel3.TabIndex = 2;
|
||||||
|
//
|
||||||
|
// buttonOkay
|
||||||
|
//
|
||||||
|
buttonOkay.Dock = DockStyle.Fill;
|
||||||
|
buttonOkay.Location = new Point(735, 3);
|
||||||
|
buttonOkay.Margin = new Padding(3, 3, 3, 15);
|
||||||
|
buttonOkay.Name = "buttonOkay";
|
||||||
|
buttonOkay.Size = new Size(194, 57);
|
||||||
|
buttonOkay.TabIndex = 8;
|
||||||
|
buttonOkay.Text = "Okay";
|
||||||
|
buttonOkay.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// buttonCancel
|
||||||
|
//
|
||||||
|
buttonCancel.Dock = DockStyle.Fill;
|
||||||
|
buttonCancel.Location = new Point(935, 3);
|
||||||
|
buttonCancel.Margin = new Padding(3, 3, 3, 15);
|
||||||
|
buttonCancel.Name = "buttonCancel";
|
||||||
|
buttonCancel.Size = new Size(194, 57);
|
||||||
|
buttonCancel.TabIndex = 99;
|
||||||
|
buttonCancel.TabStop = false;
|
||||||
|
buttonCancel.Text = "Cancel";
|
||||||
|
buttonCancel.UseVisualStyleBackColor = true;
|
||||||
|
//
|
||||||
|
// labelCreatedUpdatedDT
|
||||||
|
//
|
||||||
|
labelCreatedUpdatedDT.AutoSize = true;
|
||||||
|
labelCreatedUpdatedDT.Dock = DockStyle.Fill;
|
||||||
|
labelCreatedUpdatedDT.Location = new Point(3, 0);
|
||||||
|
labelCreatedUpdatedDT.Name = "labelCreatedUpdatedDT";
|
||||||
|
labelCreatedUpdatedDT.Size = new Size(726, 75);
|
||||||
|
labelCreatedUpdatedDT.TabIndex = 2;
|
||||||
|
labelCreatedUpdatedDT.Text = "Created: yyyy-mm-dd, Updated: yyyy-mm-dd";
|
||||||
|
//
|
||||||
|
// ProjectForm
|
||||||
|
//
|
||||||
|
AutoScaleDimensions = new SizeF(13F, 32F);
|
||||||
|
AutoScaleMode = AutoScaleMode.Font;
|
||||||
|
ClientSize = new Size(1144, 660);
|
||||||
|
Controls.Add(groupBoxNewClient);
|
||||||
|
Name = "ProjectForm";
|
||||||
|
Text = "ProjectForm";
|
||||||
|
groupBoxNewClient.ResumeLayout(false);
|
||||||
|
tableLayoutPanel1.ResumeLayout(false);
|
||||||
|
tableLayoutPanel2.ResumeLayout(false);
|
||||||
|
tableLayoutPanel2.PerformLayout();
|
||||||
|
tableLayoutPanel6.ResumeLayout(false);
|
||||||
|
tableLayoutPanel6.PerformLayout();
|
||||||
|
tableLayoutPanel4.ResumeLayout(false);
|
||||||
|
tableLayoutPanel4.PerformLayout();
|
||||||
|
groupBoxNotes.ResumeLayout(false);
|
||||||
|
tableLayoutPanel3.ResumeLayout(false);
|
||||||
|
tableLayoutPanel3.PerformLayout();
|
||||||
|
ResumeLayout(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private GroupBox groupBoxNewClient;
|
||||||
|
private TableLayoutPanel tableLayoutPanel1;
|
||||||
|
private TableLayoutPanel tableLayoutPanel2;
|
||||||
|
private Label labelClient;
|
||||||
|
private Label labelName;
|
||||||
|
private Label labelDescription;
|
||||||
|
private Label labelStartDate;
|
||||||
|
private Label labelHourlyRate;
|
||||||
|
private TextBox textBoxName;
|
||||||
|
private GroupBox groupBoxNotes;
|
||||||
|
private RichTextBox richTextBoxNotes;
|
||||||
|
private TableLayoutPanel tableLayoutPanel3;
|
||||||
|
private Button buttonOkay;
|
||||||
|
private Button buttonCancel;
|
||||||
|
private Label labelCreatedUpdatedDT;
|
||||||
|
private ComboBox comboBoxClient;
|
||||||
|
private TableLayoutPanel tableLayoutPanel6;
|
||||||
|
private DateTimePicker dateTimePickerStartDate;
|
||||||
|
private DateTimePicker dateTimePickerEndDate;
|
||||||
|
private Label labelEndDate;
|
||||||
|
private RichTextBox richTextBoxDescription;
|
||||||
|
private TableLayoutPanel tableLayoutPanel4;
|
||||||
|
private Label labelBudget;
|
||||||
|
private Label labelStatus;
|
||||||
|
private ComboBox comboBoxStatus;
|
||||||
|
private TextBox textBoxHourlyRate;
|
||||||
|
private TextBox textBoxBudget;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
using System.ComponentModel;
|
||||||
|
using trakker.Models;
|
||||||
|
|
||||||
|
namespace trakker.Forms
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Form used to view and edit a <see cref="Project"/> model. Fields on the form
|
||||||
|
/// are data-bound to the provided project instance and basic validation is
|
||||||
|
/// performed on required fields.
|
||||||
|
/// </summary>
|
||||||
|
public partial class ProjectForm : Form
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The project instance being edited by this form.
|
||||||
|
/// </summary>
|
||||||
|
private readonly Project _project;
|
||||||
|
|
||||||
|
private BindingList<Client>? _clients;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Binding source that connects the project model to the form controls.
|
||||||
|
/// </summary>
|
||||||
|
private BindingSource bindingSource = new BindingSource();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Error provider used to display validation errors next to input controls.
|
||||||
|
/// </summary>
|
||||||
|
private ErrorProvider errorProvider = new ErrorProvider();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="ProjectForm"/> class bound to
|
||||||
|
/// the provided <paramref name="project"/>. Sets up data bindings for all
|
||||||
|
/// visible input controls and configures dialog button behavior.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="project">The <see cref="Project"/> instance to edit. Must not be null.</param>
|
||||||
|
/// <param name="clients">The list of <see cref="Client"/> instances to select from. Must not be null.</param>
|
||||||
|
public ProjectForm(Project project, BindingList<Client> clients)
|
||||||
|
{
|
||||||
|
_project = project;
|
||||||
|
_clients = clients;
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
comboBoxClient.DataSource = _clients;
|
||||||
|
comboBoxClient.DisplayMember = "Name";
|
||||||
|
comboBoxClient.ValueMember = "ClientId";
|
||||||
|
|
||||||
|
dateTimePickerStartDate.Format = DateTimePickerFormat.Custom;
|
||||||
|
dateTimePickerStartDate.CustomFormat = "yyyy-MM-dd";
|
||||||
|
dateTimePickerEndDate.Format = DateTimePickerFormat.Custom;
|
||||||
|
dateTimePickerEndDate.CustomFormat = "yyyy-MM-dd";
|
||||||
|
|
||||||
|
// Bind model properties to controls so the UI reflects and updates the model.
|
||||||
|
bindingSource.DataSource = _project;
|
||||||
|
comboBoxClient.DataBindings.Add("SelectedValue", bindingSource, "ClientId", true);
|
||||||
|
textBoxName.DataBindings.Add("Text", bindingSource, "ProjectName", true);
|
||||||
|
richTextBoxDescription.DataBindings.Add("Text", bindingSource, "Description", true);
|
||||||
|
dateTimePickerStartDate.DataBindings.Add("Value", bindingSource, "StartDate", true);
|
||||||
|
dateTimePickerEndDate.DataBindings.Add("Value", bindingSource, "EndDate", true);
|
||||||
|
textBoxHourlyRate.DataBindings.Add("Text", bindingSource, "HourlyRate", true);
|
||||||
|
textBoxBudget.DataBindings.Add("Text", bindingSource, "Budget", true);
|
||||||
|
comboBoxStatus.DataBindings.Add("ValueMember", bindingSource, "Status", true);
|
||||||
|
richTextBoxNotes.DataBindings.Add("Text", bindingSource, "Notes", true);
|
||||||
|
|
||||||
|
// Configure dialog buttons and window behavior.
|
||||||
|
buttonOkay.DialogResult = DialogResult.OK;
|
||||||
|
buttonCancel.DialogResult = DialogResult.Cancel;
|
||||||
|
this.CancelButton = buttonCancel;
|
||||||
|
this.StartPosition = FormStartPosition.CenterParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the <see cref="Project"/> instance edited by the form.
|
||||||
|
/// </summary>
|
||||||
|
public Project Project { get => _project; private set { } }
|
||||||
|
|
||||||
|
public BindingList<Client>? Clients { get => _clients; set { _clients = value; } }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates the Name field. If the name is empty or whitespace, an error is set
|
||||||
|
/// on the <see cref="errorProvider"/> and the event is canceled to prevent the
|
||||||
|
/// form from closing.
|
||||||
|
/// </summary>
|
||||||
|
private void textBoxName_Validating(object sender, System.ComponentModel.CancelEventArgs e)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(textBoxName.Text))
|
||||||
|
{
|
||||||
|
errorProvider.SetError(textBoxName, "Name is required.");
|
||||||
|
errorProvider.SetIconAlignment(textBoxName, ErrorIconAlignment.MiddleRight);
|
||||||
|
errorProvider.SetIconPadding(textBoxName, 2);
|
||||||
|
e.Cancel = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
errorProvider.SetError(textBoxName, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Validates the Email field. If the email is empty or whitespace, an error is set
|
||||||
|
/// on the <see cref="errorProvider"/> and the event is canceled to prevent the
|
||||||
|
/// form from closing. Note: this validation only checks presence, not format.
|
||||||
|
/// </summary>
|
||||||
|
private void textBoxEmail_Validating(object sender, System.ComponentModel.CancelEventArgs e)
|
||||||
|
{
|
||||||
|
//if (string.IsNullOrWhiteSpace(textBoxEmail.Text))
|
||||||
|
//{
|
||||||
|
// errorProvider.SetError(textBoxEmail, "Email is required.");
|
||||||
|
// errorProvider.SetIconAlignment(textBoxEmail, ErrorIconAlignment.MiddleRight);
|
||||||
|
// errorProvider.SetIconPadding(textBoxEmail, 2);
|
||||||
|
// e.Cancel = true;
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// errorProvider.SetError(textBoxEmail, "");
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
<?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=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
<resheader name="writer">
|
||||||
|
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||||
|
</resheader>
|
||||||
|
</root>
|
||||||
|
|
@ -11,5 +11,7 @@ namespace trakker.Interfaces
|
||||||
internal interface IMainForm
|
internal interface IMainForm
|
||||||
{
|
{
|
||||||
void InitDataGridViewClients(BindingList<Client> clients);
|
void InitDataGridViewClients(BindingList<Client> clients);
|
||||||
|
void InitDataGridViewProjects();
|
||||||
|
void FillDataGridViewProjects(BindingSource projects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,31 @@
|
||||||
using System;
|
|
||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
|
|
||||||
namespace trakker.Models
|
namespace trakker.Models
|
||||||
{
|
{
|
||||||
public class Project
|
public class Project
|
||||||
{
|
{
|
||||||
[Key]
|
|
||||||
public string ProjectId { get; set; } = string.Empty;
|
public string ProjectId { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Required]
|
|
||||||
public string ClientId { get; set; } = string.Empty;
|
public string ClientId { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Required]
|
public string ProjectCode { get; set; } = string.Empty;
|
||||||
[MaxLength(200)]
|
|
||||||
public string Name { get; set; } = string.Empty;
|
|
||||||
|
|
||||||
[MaxLength(1000)]
|
public string ClientName { get; set; } = string.Empty;
|
||||||
public string? Description { get; set; }
|
|
||||||
|
|
||||||
public DateOnly? StartDate { get; set; }
|
public string ProjectName { get; set; } = string.Empty;
|
||||||
|
|
||||||
public DateOnly? EndDate { get; set; }
|
public string? Description { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public DateTime? StartDate { get; set; }
|
||||||
|
|
||||||
|
public DateTime? EndDate { get; set; }
|
||||||
|
|
||||||
[Range(0, double.MaxValue)]
|
|
||||||
public decimal Budget { get; set; } = 0;
|
public decimal Budget { get; set; } = 0;
|
||||||
|
|
||||||
public ProjectStatus Status { get; set; } = ProjectStatus.Active;
|
public string Status { get; set; } = string.Empty;
|
||||||
|
|
||||||
[Range(0, double.MaxValue)]
|
|
||||||
public decimal? HourlyRate { get; set; }
|
public decimal? HourlyRate { get; set; }
|
||||||
|
|
||||||
[MaxLength(2000)]
|
public string? Notes { get; set; } = string.Empty;
|
||||||
public string? Notes { get; set; }
|
|
||||||
|
|
||||||
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,13 +20,36 @@ namespace trakker.Services
|
||||||
_connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
|
_connectionString = connectionString ?? throw new ArgumentNullException(nameof(connectionString));
|
||||||
|
|
||||||
LoadClients();
|
LoadClients();
|
||||||
|
|
||||||
|
_view.InitDataGridViewProjects();
|
||||||
|
LoadProjects();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BindingList<Client> GetClients()
|
||||||
|
{
|
||||||
|
var dbo = new Data.ClientData(_connectionString);
|
||||||
|
return dbo.Get();
|
||||||
}
|
}
|
||||||
internal void LoadClients()
|
internal void LoadClients()
|
||||||
{
|
{
|
||||||
// Implement logic to load clients from the database using _connectionString
|
var clients = GetClients();
|
||||||
var dbo = new Data.ClientData(_connectionString);
|
|
||||||
var clients = dbo.Get();
|
|
||||||
_view.InitDataGridViewClients(clients);
|
_view.InitDataGridViewClients(clients);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BindingList<Project> GetProjects()
|
||||||
|
{
|
||||||
|
var dbo = new Data.ProjectData(_connectionString);
|
||||||
|
return dbo.Get();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void LoadProjects()
|
||||||
|
{
|
||||||
|
var projects = GetProjects();
|
||||||
|
foreach (var project in projects)
|
||||||
|
{
|
||||||
|
var x = project.Status;
|
||||||
|
}
|
||||||
|
_view.FillDataGridViewProjects(new BindingSource { DataSource = projects });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,285 @@
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using trakker.Data;
|
||||||
|
using trakker.Forms;
|
||||||
|
using trakker.Interfaces;
|
||||||
|
using trakker.Models;
|
||||||
|
using trakker.Services;
|
||||||
|
|
||||||
|
namespace trakker
|
||||||
|
{
|
||||||
|
public partial class MainForm : Form, IMainForm
|
||||||
|
{
|
||||||
|
//private readonly string _dbversion = "[N.N.N]";
|
||||||
|
private string connectionString = string.Empty;
|
||||||
|
readonly MainCtrl _ctrl;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="MainForm"/> class.
|
||||||
|
/// Sets up the form's controls and event handlers by calling
|
||||||
|
/// <see cref="InitializeComponent"/> which is generated by the designer.
|
||||||
|
/// </summary>
|
||||||
|
public MainForm()
|
||||||
|
{
|
||||||
|
InitializeComponent();
|
||||||
|
|
||||||
|
// build connection string that will be used for database connections
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
var dbPath = Path.Combine(AppContext.BaseDirectory, "trakker.db");
|
||||||
|
connectionString = new SqliteConnectionStringBuilder
|
||||||
|
{
|
||||||
|
DataSource = dbPath,
|
||||||
|
Mode = SqliteOpenMode.ReadWriteCreate,
|
||||||
|
Cache = SqliteCacheMode.Shared
|
||||||
|
}.ToString();
|
||||||
|
|
||||||
|
tabControlMainForm.TabPages[0].Text = " Home ";
|
||||||
|
tabControlMainForm.TabPages[1].Text = " Clients ";
|
||||||
|
tabControlMainForm.TabPages[2].Text = " Projects ";
|
||||||
|
|
||||||
|
_ctrl = new Services.MainCtrl(this, connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handles the Click event of the Exit menu item. When invoked, this
|
||||||
|
/// method terminates the application.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sender">The source of the event.</param>
|
||||||
|
/// <param name="e">Event data associated with the click event.</param>
|
||||||
|
private void MainForm_Exit_MenuItem_Click(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
Application.Exit();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void InitDataGridViewClients(BindingList<Client> clients)
|
||||||
|
{
|
||||||
|
dataGridViewClients.AllowUserToAddRows = true;
|
||||||
|
dataGridViewClients.AllowUserToDeleteRows = true;
|
||||||
|
dataGridViewClients.AutoGenerateColumns = false;
|
||||||
|
dataGridViewClients.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
|
||||||
|
dataGridViewClients.BackgroundColor = Color.White;
|
||||||
|
dataGridViewClients.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||||
|
dataGridViewClients.RowHeadersVisible = false;
|
||||||
|
dataGridViewClients.ColumnHeadersVisible = true;
|
||||||
|
dataGridViewClients.MultiSelect = false;
|
||||||
|
dataGridViewClients.DataSource = clients;
|
||||||
|
|
||||||
|
dataGridViewClients.Columns.Clear();
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "Name",
|
||||||
|
Name = "Name",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewClients.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "Company",
|
||||||
|
Name = "Company",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewClients.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "Email",
|
||||||
|
Name = "Email",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewClients.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "Phone",
|
||||||
|
Name = "Phone",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewClients.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataGridViewClients.DoubleClick += (s, e) =>
|
||||||
|
{
|
||||||
|
if (dataGridViewClients.SelectedRows.Count > 0)
|
||||||
|
{
|
||||||
|
var selectedClient = dataGridViewClients.SelectedRows[0].DataBoundItem as Client;
|
||||||
|
if (selectedClient != null)
|
||||||
|
{
|
||||||
|
var dialog = new ClientForm(selectedClient);
|
||||||
|
if (dialog.ShowDialog(this) == DialogResult.OK)
|
||||||
|
{
|
||||||
|
Client client = dialog.Client;
|
||||||
|
ClientData clientData = new ClientData(connectionString);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
clientData.Upsert(client);
|
||||||
|
dataGridViewClients.Refresh(); // Refresh the DataGridView to reflect changes
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
MessageBox.Show($"Error saving client: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dataGridViewClients.SelectionChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (dataGridViewClients.SelectedRows.Count > 0)
|
||||||
|
{
|
||||||
|
var selectedClient = dataGridViewClients.SelectedRows[0].DataBoundItem as Client;
|
||||||
|
if (selectedClient != null)
|
||||||
|
{
|
||||||
|
// Handle the selected client as needed
|
||||||
|
// MessageBox.Show($"Selected Client: {selectedClient.AddressStreet}", "Client Selected", MessageBoxButtons.OK, MessageBoxIcon.Information );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
public void InitDataGridViewProjects(BindingList<Project> projects)
|
||||||
|
{
|
||||||
|
dataGridViewProjects.AllowUserToAddRows = true;
|
||||||
|
dataGridViewProjects.AllowUserToDeleteRows = true;
|
||||||
|
dataGridViewProjects.AutoGenerateColumns = false;
|
||||||
|
dataGridViewProjects.BackgroundColor = Color.White;
|
||||||
|
dataGridViewProjects.SelectionMode = DataGridViewSelectionMode.FullRowSelect;
|
||||||
|
dataGridViewProjects.RowHeadersVisible = false;
|
||||||
|
dataGridViewProjects.ColumnHeadersVisible = true;
|
||||||
|
dataGridViewProjects.MultiSelect = false;
|
||||||
|
dataGridViewProjects.DataSource = projects;
|
||||||
|
dataGridViewProjects.Columns.Clear();
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "ProjectName",
|
||||||
|
Name = "Project Name",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "ClientName",
|
||||||
|
Name = "Client Name",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "StartDate",
|
||||||
|
Name = "Start Date",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "EndDate",
|
||||||
|
Name = "End Date",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "Status",
|
||||||
|
Name = "Status",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
var textColumn = new DataGridViewTextBoxColumn
|
||||||
|
{
|
||||||
|
AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill,
|
||||||
|
DataPropertyName = "Budget",
|
||||||
|
Name = "Budget",
|
||||||
|
Visible = true,
|
||||||
|
};
|
||||||
|
textColumn.DefaultCellStyle.Format = "$#,##0.00";
|
||||||
|
textColumn.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight;
|
||||||
|
textColumn.HeaderCell.Style.Alignment = DataGridViewContentAlignment.MiddleRight;
|
||||||
|
dataGridViewProjects.Columns.Add(textColumn);
|
||||||
|
}
|
||||||
|
|
||||||
|
dataGridViewProjects.DoubleClick += (s, e) =>
|
||||||
|
{
|
||||||
|
if (dataGridViewProjects.SelectedRows.Count > 0)
|
||||||
|
{
|
||||||
|
var selectedProject = dataGridViewProjects.SelectedRows[0].DataBoundItem as Project;
|
||||||
|
if (selectedProject != null)
|
||||||
|
{
|
||||||
|
var dialog = new ProjectForm(selectedProject);
|
||||||
|
if (dialog.ShowDialog(this) == DialogResult.OK)
|
||||||
|
{
|
||||||
|
// Project project = dialog.Project;
|
||||||
|
// ProjectData projectData = new ProjectData(connectionString);
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// projectData.Upsert(project);
|
||||||
|
// dataGridViewProjects.Refresh(); // Refresh the DataGridView to reflect changes
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// MessageBox.Show($"Error saving project: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
dataGridViewClients.SelectionChanged += (s, e) =>
|
||||||
|
{
|
||||||
|
if (dataGridViewClients.SelectedRows.Count > 0)
|
||||||
|
{
|
||||||
|
var selectedClient = dataGridViewClients.SelectedRows[0].DataBoundItem as Client;
|
||||||
|
if (selectedClient != null)
|
||||||
|
{
|
||||||
|
// Handle the selected client as needed
|
||||||
|
// MessageBox.Show($"Selected Client: {selectedClient.AddressStreet}", "Client Selected", MessageBoxButtons.OK, MessageBoxIcon.Information );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//private void button1_Click(object sender, EventArgs e)
|
||||||
|
//{
|
||||||
|
// var dialog = new ClientForm(new Client());
|
||||||
|
// if (dialog.ShowDialog(this) == DialogResult.OK)
|
||||||
|
// {
|
||||||
|
// Client client = dialog.Client;
|
||||||
|
// ClientData clientData = new ClientData(connectionString);
|
||||||
|
// try
|
||||||
|
// {
|
||||||
|
// clientData.Upsert(client);
|
||||||
|
// }
|
||||||
|
// catch (Exception ex)
|
||||||
|
// {
|
||||||
|
// MessageBox.Show($"Error saving client: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue