diff --git a/Areas/OTcalculate/Controllers/HodDashboardController.cs b/Areas/OTcalculate/Controllers/HodDashboardController.cs
new file mode 100644
index 0000000..7491183
--- /dev/null
+++ b/Areas/OTcalculate/Controllers/HodDashboardController.cs
@@ -0,0 +1,22 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.EntityFrameworkCore;
+using PSTW_CentralSystem.Areas.OTcalculate.Models;
+using PSTW_CentralSystem.DBContext;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace PSTW_CentralSystem.Areas.OTcalculate.Controllers
+{
+ [Area("OTcalculate")]
+ [Authorize]
+ public class HodDashboardController : Controller
+ {
+ public IActionResult HodApproval()
+ {
+ return View();
+ }
+ }
+}
diff --git a/Areas/OTcalculate/Controllers/HrDashboardController.cs b/Areas/OTcalculate/Controllers/HrDashboardController.cs
index d8a0829..ddcc809 100644
--- a/Areas/OTcalculate/Controllers/HrDashboardController.cs
+++ b/Areas/OTcalculate/Controllers/HrDashboardController.cs
@@ -1,4 +1,5 @@
-using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using PSTW_CentralSystem.Areas.OTcalculate.Models;
using PSTW_CentralSystem.DBContext;
@@ -10,6 +11,7 @@ using System.Threading.Tasks;
namespace PSTW_CentralSystem.Areas.OTcalculate.Controllers
{
[Area("OTcalculate")]
+ [Authorize]
public class HrDashboardController : Controller
{
diff --git a/Areas/OTcalculate/Controllers/OvertimeController.cs b/Areas/OTcalculate/Controllers/OvertimeController.cs
index 2bb66a7..93a2757 100644
--- a/Areas/OTcalculate/Controllers/OvertimeController.cs
+++ b/Areas/OTcalculate/Controllers/OvertimeController.cs
@@ -1,8 +1,10 @@
-using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
namespace PSTW_CentralSystem.Areas.OTcalculate.Controllers
{
[Area("OTcalculate")]
+ [Authorize]
public class OvertimeController : Controller
{
public IActionResult OtRegister()
diff --git a/Areas/OTcalculate/Models/OtRecordsModel.cs b/Areas/OTcalculate/Models/OtRecordsModel.cs
new file mode 100644
index 0000000..46eb9e6
--- /dev/null
+++ b/Areas/OTcalculate/Models/OtRecordsModel.cs
@@ -0,0 +1,7 @@
+namespace PSTW_CentralSystem.Areas.OTcalculate.Models
+{
+ public class OtRecordsModel
+ {
+
+ }
+}
diff --git a/Areas/OTcalculate/Models/OtRegisterModel.cs b/Areas/OTcalculate/Models/OtRegisterModel.cs
index 89054d6..cd74523 100644
--- a/Areas/OTcalculate/Models/OtRegisterModel.cs
+++ b/Areas/OTcalculate/Models/OtRegisterModel.cs
@@ -28,6 +28,7 @@ namespace PSTW_CentralSystem.Areas.OTcalculate.Models
public string OtDescription { get; set; }
public string OtDays { get; set; }
public required string PDFBase64 { get; set; }
+ public required string IvBase64 { get; set; }
[Required]
public int UserId { get; set; }
diff --git a/Areas/OTcalculate/Views/HodDashboard/HodApproval.cshtml b/Areas/OTcalculate/Views/HodDashboard/HodApproval.cshtml
new file mode 100644
index 0000000..db6acb4
--- /dev/null
+++ b/Areas/OTcalculate/Views/HodDashboard/HodApproval.cshtml
@@ -0,0 +1,17 @@
+@{
+ ViewData["Title"] = "Overtime Approval";
+ Layout = "~/Views/Shared/_Layout.cshtml";
+}
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
+
diff --git a/Areas/OTcalculate/Views/Overtime/OtRegister.cshtml b/Areas/OTcalculate/Views/Overtime/OtRegister.cshtml
index c3d6db5..0b65585 100644
--- a/Areas/OTcalculate/Views/Overtime/OtRegister.cshtml
+++ b/Areas/OTcalculate/Views/Overtime/OtRegister.cshtml
@@ -241,44 +241,70 @@
console.log("Sending userId:", this.userId);
const reader = new FileReader();
- reader.onload = async (event) => {
- const base64String = event.target.result.split(',')[1];
+ reader.onload = async (event) => {
+ const base64String = event.target.result.split(',')[1];
- const payload = {
- otDate: this.selectedDate,
- officeFrom: this.formatTime(this.officeFrom) || null,
- officeTo: this.formatTime(this.officeTo) || null,
- officeBreak: this.officeBreak || 0,
- outsideFrom: this.formatTime(this.outsideFrom) || null,
- outsideTo: this.formatTime(this.outsideTo) || null,
- outsideBreak: this.outsideBreak || 0,
- stationId: this.selectedAirStation,
- otDescription: this.otDescription,
- otDays: this.selectedDayType,
- pdfBase64: base64String,
- userId: this.userId,
- };
+ // Generate a crypto key
+ const key = await crypto.subtle.generateKey(
+ { name: "AES-GCM", length: 256 },
+ true,
+ ["encrypt", "decrypt"]
+ );
- try {
- const response = await fetch(`${window.location.origin}/OvertimeAPI/AddOvertime`, {
- method: "POST",
- headers: { "Content-Type": "application/json" },
- body: JSON.stringify(payload),
- });
+ // Export the key (for sending to backend if needed or for testing)
+ const exportedKey = await crypto.subtle.exportKey("jwk", key);
- if (!response.ok) {
- const errorText = await response.text();
- throw new Error(`HTTP error! status: ${response.status} - ${errorText}`);
- }
+ // Generate a random IV
+ const iv = crypto.getRandomValues(new Uint8Array(12));
+
+ // Encode data
+ const encoded = new TextEncoder().encode(base64String);
+
+ // Encrypt the data
+ const encrypted = await crypto.subtle.encrypt(
+ { name: "AES-GCM", iv: iv },
+ key,
+ encoded
+ );
+
+ // Convert encrypted data to base64
+ const encryptedBase64 = btoa(String.fromCharCode(...new Uint8Array(encrypted)));
+ const ivBase64 = btoa(String.fromCharCode(...iv));
+
+ const payload = {
+ otDate: this.selectedDate,
+ officeFrom: this.formatTime(this.officeFrom) || null,
+ officeTo: this.formatTime(this.officeTo) || null,
+ officeBreak: this.officeBreak || 0,
+ outsideFrom: this.formatTime(this.outsideFrom) || null,
+ outsideTo: this.formatTime(this.outsideTo) || null,
+ outsideBreak: this.outsideBreak || 0,
+ stationId: this.selectedAirStation,
+ otDescription: this.otDescription,
+ otDays: this.selectedDayType,
+ pdfBase64: encryptedBase64,
+ ivBase64: ivBase64, // store this too
+ userId: this.userId,
+ encryptionKey: exportedKey.k, // only if you're doing a simple demo; ideally don't send this from frontend
+ };
+
+ // Send to backend
+ const response = await fetch(`${window.location.origin}/OvertimeAPI/AddOvertime`, {
+ method: "POST",
+ headers: { "Content-Type": "application/json" },
+ body: JSON.stringify(payload),
+ });
+
+ if (!response.ok) {
+ const errorText = await response.text();
+ throw new Error(`HTTP error! status: ${response.status} - ${errorText}`);
+ }
+
+ const result = await response.json();
+ alert(result.message);
+ this.clearForm();
+ };
- const result = await response.json();
- alert(result.message);
- this.clearForm();
- } catch (error) {
- console.error("Error adding overtime:", error);
- alert("Failed to save overtime. Please check the console for errors.");
- }
- };
reader.onerror = () => {
console.error("Error reading file");
diff --git a/Views/Shared/_Layout.cshtml b/Views/Shared/_Layout.cshtml
index 5dda427..331cb05 100644
--- a/Views/Shared/_Layout.cshtml
+++ b/Views/Shared/_Layout.cshtml
@@ -539,6 +539,21 @@
+
+