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 +
+
+
+
+ +
Rate
+ +
+
+ +
+
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 @@ + +