diff --git a/AVSCartonShipmentVerifier.csproj b/AVSCartonShipmentVerifier.csproj
index 0e54e59..9b56a64 100644
--- a/AVSCartonShipmentVerifier.csproj
+++ b/AVSCartonShipmentVerifier.csproj
@@ -13,4 +13,8 @@
+
+
+
+
diff --git a/Program.cs b/Program.cs
index 2e6167b..1028f84 100644
--- a/Program.cs
+++ b/Program.cs
@@ -4,6 +4,7 @@ using AVSCartonShipmentVerifier.Repositories;
using AVSCartonShipmentVerifier.ScanHistory;
using AVSCartonShipmentVerifier.Services;
using Microsoft.EntityFrameworkCore;
+using Microsoft.Extensions.FileProviders;
var builder = WebApplication.CreateBuilder(args);
@@ -50,6 +51,11 @@ if (!app.Environment.IsDevelopment())
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
+app.UseStaticFiles(new StaticFileOptions
+{
+ FileProvider = new PhysicalFileProvider(Path.Combine(builder.Environment.ContentRootPath, "Resources")),
+ RequestPath = "/resources"
+});
app.MapStaticAssets();
app.MapControllerRoute(
@@ -58,4 +64,3 @@ app.MapControllerRoute(
.WithStaticAssets();
app.Run();
-
diff --git a/Resources/Sound/alert.wav b/Resources/Sound/alert.wav
new file mode 100644
index 0000000..8605fd7
Binary files /dev/null and b/Resources/Sound/alert.wav differ
diff --git a/wwwroot/js/verification-dashboard.js b/wwwroot/js/verification-dashboard.js
index e742bae..0a18028 100644
--- a/wwwroot/js/verification-dashboard.js
+++ b/wwwroot/js/verification-dashboard.js
@@ -17,6 +17,8 @@
};
const antiForgeryToken = document.querySelector('input[name="__RequestVerificationToken"]')?.value;
+ const failureAlarm = new Audio("/resources/Sound/alert.wav");
+ failureAlarm.preload = "auto";
let isSubmitting = false;
qrInput.addEventListener("keydown", async event => {
@@ -70,7 +72,6 @@
if (!response.ok) {
const fallbackMessage = "Verification service is unavailable.";
setFailedState(payload.message ?? fallbackMessage);
- triggerFailureAlarm();
resetDetails();
return;
}
@@ -97,7 +98,19 @@
}
setFailedState(result.message);
- triggerFailureAlarm();
+ if (shouldTriggerFailureAlarm(result)) {
+ triggerFailureAlarm();
+ }
+ }
+
+ function shouldTriggerFailureAlarm(result) {
+ const message = (result.message ?? "").toLowerCase();
+ return !result.existsInSystem
+ && (
+ message.includes("invalid qr format")
+ || message.includes("qr value is required")
+ || message.includes("not found")
+ );
}
function setFailedState(message) {
@@ -183,22 +196,10 @@
}
function triggerFailureAlarm() {
- const context = new AudioContext();
- const oscillator = context.createOscillator();
- const gainNode = context.createGain();
-
- oscillator.type = "sawtooth";
- oscillator.frequency.setValueAtTime(740, context.currentTime);
- oscillator.frequency.exponentialRampToValueAtTime(320, context.currentTime + 0.4);
- oscillator.connect(gainNode);
- gainNode.connect(context.destination);
-
- gainNode.gain.setValueAtTime(0.0001, context.currentTime);
- gainNode.gain.exponentialRampToValueAtTime(0.5, context.currentTime + 0.05);
- gainNode.gain.exponentialRampToValueAtTime(0.0001, context.currentTime + 0.45);
-
- oscillator.start(context.currentTime);
- oscillator.stop(context.currentTime + 0.45);
- oscillator.onended = () => context.close();
+ failureAlarm.pause();
+ failureAlarm.currentTime = 0;
+ failureAlarm.play().catch(() => {
+ // Some browsers block audio until the scanner input is treated as a user gesture.
+ });
}
})();