FrymasterBadgeApp/EmployeePage.xaml.cs

572 lines
18 KiB
C#

using System.IO; // Explicitly included for Path
using FrymasterBadgeApp.Services;
using Microsoft.Data.SqlClient;
using Microsoft.Maui.Controls.Shapes; // For RoundRectangle
using Microsoft.Maui.Graphics;
namespace FrymasterBadgeApp;
public partial class EmployeePage : ContentPage
{
private readonly SqlService _db;
private readonly PrinterService _printerService;
private Dictionary<string, object>? _selectedEmployee;
private readonly Dictionary<string, object> _currentCompany;
private string _tempCapturePath = "";
private double _editX = 0;
private double _editY = 0;
private string _currentBadgeType = "Office";
private string _currentGuestImage = "Guest1.png";
public EmployeePage(
SqlService db,
PrinterService printerService,
Dictionary<string, object> company
)
{
InitializeComponent();
_db = db;
_printerService = printerService;
_currentCompany = company;
EditorPhotoPreview.SetBinding(
Image.ScaleProperty,
new Binding("Value", source: ZoomSlider)
);
GuestImagePicker.Items.Add("Guest1.png");
GuestImagePicker.Items.Add("Guest2.png");
GuestImagePicker.Items.Add("Guest3.png");
GuestImagePicker.SelectedIndex = 0;
GuestImagePicker.SelectedIndexChanged += OnGuestImageChanged;
BadgeTypePicker.SelectedIndexChanged += OnBadgeTypeChanged;
LoadCompanyLogo();
LoadEmployees();
}
private string GetPhotoDir()
{
string path = @"C:\FrymasterData\photos";
if (!Directory.Exists(path))
Directory.CreateDirectory(path);
return path;
}
private void LoadCompanyLogo()
{
string logoPath = _currentCompany.GetValueOrDefault("logo")?.ToString() ?? "";
if (!string.IsNullOrEmpty(logoPath) && File.Exists(logoPath))
{
PreviewLogoFront.Source = ImageSource.FromFile(logoPath);
}
}
private void LoadEmployees()
{
string sql =
"SELECT *, ISNULL(BadgeType, 'Office') AS BadgeType FROM dbo.tblData ORDER BY Data2";
var results = _db.Query(sql, null);
MainThread.BeginInvokeOnMainThread(() => EmployeeList.ItemsSource = results);
}
private void OnSearchTextChanged(object sender, TextChangedEventArgs e)
{
string search = $"%{e.NewTextValue}%";
string sql =
@"SELECT *, ISNULL(BadgeType, 'Office') AS BadgeType
FROM dbo.tblData
WHERE Data2 LIKE @s OR Data1 LIKE @s
ORDER BY Data2";
var results = _db.Query(sql, new[] { new SqlParameter("@s", search) });
MainThread.BeginInvokeOnMainThread(() =>
{
EmployeeList.SelectedItem = null;
EmployeeList.ItemsSource = results;
});
}
private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
_selectedEmployee = e.CurrentSelection.FirstOrDefault() as Dictionary<string, object>;
if (_selectedEmployee == null)
{
ClearBadgePreview();
return;
}
_currentBadgeType =
_selectedEmployee.GetValueOrDefault("BadgeType")?.ToString() ?? "Office";
BadgeTypePicker.SelectedItem = _currentBadgeType;
GuestImageSelector.IsVisible = _currentBadgeType == "Guest";
RenderBadgePreview(_selectedEmployee);
}
private void OnBadgeTypeChanged(object sender, EventArgs e)
{
if (_selectedEmployee == null)
return;
_currentBadgeType = BadgeTypePicker.SelectedItem?.ToString() ?? "Office";
GuestImageSelector.IsVisible = _currentBadgeType == "Guest";
string sql = "UPDATE dbo.tblData SET BadgeType = @type WHERE Data1 = @id";
_db.Execute(
sql,
new[]
{
new SqlParameter("@type", _currentBadgeType),
new SqlParameter("@id", _selectedEmployee["Data1"]),
}
);
_selectedEmployee["BadgeType"] = _currentBadgeType;
RenderBadgePreview(_selectedEmployee);
}
private void OnGuestImageChanged(object sender, EventArgs e)
{
_currentGuestImage = GuestImagePicker.SelectedItem?.ToString() ?? "Guest1.png";
if (_selectedEmployee != null && _currentBadgeType == "Guest")
RenderBadgePreview(_selectedEmployee);
}
private void ClearBadgePreview()
{
PreviewFrame.Content = null;
}
private void RenderBadgePreview(Dictionary<string, object> emp)
{
string firstName = (emp.GetValueOrDefault("Data8")?.ToString() ?? "").Trim();
string lastName = (emp.GetValueOrDefault("Data7")?.ToString() ?? "").Trim();
string recordNum = (emp.GetValueOrDefault("Data1")?.ToString() ?? "").Trim();
string department = (emp.GetValueOrDefault("Data9")?.ToString() ?? "").Trim();
string title = (emp.GetValueOrDefault("Data10")?.ToString() ?? "").Trim();
string data5 = (emp.GetValueOrDefault("Data5")?.ToString() ?? "").Trim();
string fullName = $"{firstName} {lastName}".Trim();
string barcode = $"*{recordNum}*";
string picCode = emp.GetValueOrDefault("picCode")?.ToString() ?? "";
string photoPath = string.IsNullOrEmpty(picCode)
? ""
: System.IO.Path.Combine(GetPhotoDir(), $"{picCode}.jpg"); // Fully qualified
double scale = SafeToDouble(emp.GetValueOrDefault("cropScale"), 1.0);
double tx = SafeToDouble(emp.GetValueOrDefault("cropX"), 0.0);
double ty = SafeToDouble(emp.GetValueOrDefault("cropY"), 0.0);
bool medicalBlue = false;
bool medicalRed = false;
var mainLayout = new HorizontalStackLayout
{
Spacing = 60,
Padding = 20,
HorizontalOptions = LayoutOptions.Center,
};
// FRONT BADGE
var frontLayout = new VerticalStackLayout { Spacing = 15 };
Color frontBg = Colors.White;
Color frontBorderColor = Colors.Gray;
switch (_currentBadgeType)
{
case "Plant":
frontBg = Color.FromArgb("#e8f5e8");
frontBorderColor = Colors.Green;
break;
case "Maintenance":
frontBg = Color.FromArgb("#fff3e0");
frontBorderColor = Colors.Orange;
break;
case "Guest":
frontBg = Color.FromArgb("#f3e8ff");
frontBorderColor = Colors.Purple;
break;
case "Visitor":
case "Vendor":
frontBg = Color.FromArgb("#ffebee");
frontBorderColor = Colors.Red;
break;
}
var frontBorder = new Border
{
Stroke = frontBorderColor,
StrokeThickness = 4,
BackgroundColor = frontBg,
Padding = 25,
WidthRequest = 380,
StrokeShape = new RoundRectangle { CornerRadius = 20 },
Shadow = new Shadow
{
Brush = SolidColorBrush.Black,
Offset = new Point(0, 4),
Radius = 10f,
Opacity = 0.3f,
},
Content = frontLayout,
};
frontLayout.Children.Add(
new Image
{
Source = PreviewLogoFront.Source,
HeightRequest = 70,
HorizontalOptions = LayoutOptions.Center,
Aspect = Aspect.AspectFit,
}
);
if (_currentBadgeType == "Guest")
{
frontLayout.Children.Add(
new Image
{
Source = ImageSource.FromResource(
$"FrymasterBadgeApp.Resources.Images.{_currentGuestImage}"
),
HeightRequest = 200,
WidthRequest = 200,
Aspect = Aspect.AspectFit,
}
);
}
else if (File.Exists(photoPath))
{
var photoImg = new Image
{
Source = ImageSource.FromFile(photoPath),
HeightRequest = 200,
WidthRequest = 200,
Aspect = Aspect.AspectFill,
Scale = scale,
TranslationX = tx,
TranslationY = ty,
};
frontLayout.Children.Add(photoImg);
}
else
{
frontLayout.Children.Add(
new Label
{
Text = "No Photo",
FontSize = 18,
TextColor = Colors.Gray,
HorizontalTextAlignment = TextAlignment.Center,
}
);
}
frontLayout.Children.Add(
new Label
{
Text = fullName,
FontSize = 24,
FontAttributes = FontAttributes.Bold,
HorizontalTextAlignment = TextAlignment.Center,
TextColor = Colors.Black,
}
);
if (!string.IsNullOrEmpty(title))
frontLayout.Children.Add(
new Label
{
Text = title,
FontSize = 18,
HorizontalTextAlignment = TextAlignment.Center,
TextColor = Colors.Black,
}
);
if (!string.IsNullOrEmpty(department))
frontLayout.Children.Add(
new Label
{
Text = department,
FontSize = 16,
HorizontalTextAlignment = TextAlignment.Center,
TextColor = Colors.Gray,
}
);
mainLayout.Children.Add(frontBorder);
// BACK BADGE
var backLayout = new VerticalStackLayout { Spacing = 12 };
var backBorder = new Border
{
Stroke = Colors.Gray,
StrokeThickness = 4,
BackgroundColor = Colors.White,
Padding = 25,
WidthRequest = 380,
StrokeShape = new RoundRectangle { CornerRadius = 20 },
Shadow = new Shadow
{
Brush = SolidColorBrush.Black,
Offset = new Point(0, 4),
Radius = 10f,
Opacity = 0.3f,
},
Content = backLayout,
};
backLayout.Children.Add(
new Image
{
Source = PreviewLogoFront.Source,
HeightRequest = 50,
HorizontalOptions = LayoutOptions.Center,
Aspect = Aspect.AspectFit,
}
);
backLayout.Children.Add(
new Label
{
Text =
$"This badge is the property of {_currentCompany.GetValueOrDefault("Name")} L.L.C.",
FontSize = 14,
FontAttributes = FontAttributes.Bold,
HorizontalTextAlignment = TextAlignment.Center,
TextColor = Colors.Black,
}
);
backLayout.Children.Add(
new Label
{
Text = $"ID: {recordNum}",
FontSize = 16,
TextColor = Colors.Black,
}
);
backLayout.Children.Add(
new Label
{
Text = title,
FontSize = 16,
TextColor = Colors.Black,
}
);
backLayout.Children.Add(
new Label
{
Text = data5,
FontSize = 16,
TextColor = Colors.Black,
}
);
string address = _currentCompany.GetValueOrDefault("Address")?.ToString() ?? "";
if (!string.IsNullOrEmpty(address))
backLayout.Children.Add(
new Label
{
Text = address,
FontSize = 14,
TextColor = Colors.Black,
}
);
var locationParts = new[]
{
_currentCompany.GetValueOrDefault("City")?.ToString(),
_currentCompany.GetValueOrDefault("State")?.ToString(),
_currentCompany.GetValueOrDefault("Zip")?.ToString(),
}
.Where(p => !string.IsNullOrEmpty(p))
.ToArray();
if (locationParts.Length > 0)
backLayout.Children.Add(
new Label
{
Text = string.Join(", ", locationParts),
FontSize = 14,
TextColor = Colors.Black,
}
);
string phone = _currentCompany.GetValueOrDefault("Phone")?.ToString() ?? "";
if (!string.IsNullOrEmpty(phone))
backLayout.Children.Add(
new Label
{
Text = phone,
FontSize = 14,
TextColor = Colors.Black,
}
);
if (medicalBlue || medicalRed)
{
var medStack = new HorizontalStackLayout
{
HorizontalOptions = LayoutOptions.Center,
Spacing = 10,
};
if (medicalBlue)
medStack.Children.Add(
new Label
{
Text = "🩺",
FontSize = 36,
TextColor = Colors.Blue,
}
);
if (medicalRed)
medStack.Children.Add(
new Label
{
Text = "🩺",
FontSize = 36,
TextColor = Colors.Red,
}
);
backLayout.Children.Add(medStack);
}
if (_currentBadgeType == "Office" || _currentBadgeType == "Plant")
{
backLayout.Children.Add(
new Label
{
Text = barcode,
FontFamily = "BarcodeFont",
FontSize = 50,
HorizontalTextAlignment = TextAlignment.Center,
TextColor = Colors.Black,
}
);
}
mainLayout.Children.Add(backBorder);
PreviewFrame.Content = mainLayout;
}
private async void OnTakePhotoClicked(object sender, EventArgs e)
{
if (_selectedEmployee == null)
return;
try
{
var photo = await MediaPicker.Default.CapturePhotoAsync();
if (photo != null)
{
_tempCapturePath = System.IO.Path.Combine(
FileSystem.CacheDirectory,
"temp_editor.jpg"
); // Fully qualified
using var source = await photo.OpenReadAsync();
using var dest = File.OpenWrite(_tempCapturePath);
await source.CopyToAsync(dest);
EditorPhotoPreview.Source = ImageSource.FromFile(_tempCapturePath);
_editX = _editY = 0;
EditorPhotoPreview.TranslationX = EditorPhotoPreview.TranslationY = 0;
ZoomSlider.Value = 1;
PhotoEditorOverlay.IsVisible = true;
}
}
catch (Exception ex)
{
await DisplayAlert("Camera Error", ex.Message, "OK");
}
}
private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
{
if (e.StatusType == GestureStatus.Running)
{
EditorPhotoPreview.TranslationX = _editX + e.TotalX;
EditorPhotoPreview.TranslationY = _editY + e.TotalY;
}
else if (e.StatusType == GestureStatus.Completed)
{
_editX = EditorPhotoPreview.TranslationX;
_editY = EditorPhotoPreview.TranslationY;
}
}
private async void OnApplyPhoto(object sender, EventArgs e)
{
if (_selectedEmployee == null)
return;
try
{
string firstName = (
_selectedEmployee.GetValueOrDefault("Data8")?.ToString() ?? ""
).Trim();
string lastName = (
_selectedEmployee.GetValueOrDefault("Data7")?.ToString() ?? ""
).Trim();
string recordNum = (
_selectedEmployee.GetValueOrDefault("Data1")?.ToString() ?? ""
).Trim();
string picCode = $"{lastName}{recordNum}{firstName}{lastName}";
string finalPath = System.IO.Path.Combine(GetPhotoDir(), $"{picCode}.jpg"); // Fully qualified
File.Copy(_tempCapturePath, finalPath, true);
string sql =
@"UPDATE dbo.tblData SET picCode = @pic, cropScale = @s, cropX = @x, cropY = @y WHERE Data1 = @id";
_db.Execute(
sql,
new[]
{
new SqlParameter("@pic", picCode),
new SqlParameter("@s", ZoomSlider.Value),
new SqlParameter("@x", EditorPhotoPreview.TranslationX),
new SqlParameter("@y", EditorPhotoPreview.TranslationY),
new SqlParameter("@id", recordNum),
}
);
_selectedEmployee["picCode"] = picCode;
_selectedEmployee["cropScale"] = ZoomSlider.Value;
_selectedEmployee["cropX"] = EditorPhotoPreview.TranslationX;
_selectedEmployee["cropY"] = EditorPhotoPreview.TranslationY;
RenderBadgePreview(_selectedEmployee);
PhotoEditorOverlay.IsVisible = false;
}
catch (Exception ex)
{
await DisplayAlert("Save Error", ex.Message, "OK");
}
}
private void OnCancelPhoto(object sender, EventArgs e) => PhotoEditorOverlay.IsVisible = false;
private double SafeToDouble(object? value, double defaultValue)
{
if (value == null || value == DBNull.Value)
return defaultValue;
return double.TryParse(value.ToString(), out double d) ? d : defaultValue;
}
private void OnPrintClicked(object sender, EventArgs e)
{
if (_selectedEmployee != null)
_printerService.PrintBadge(_selectedEmployee, _currentCompany, _currentBadgeType);
}
}