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. + }); } })();