angular.module("clientApp").controller('educationCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('employmentCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('credentialCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('referenceCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('piiCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('drivingRecordCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('empCollectionCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { var token = queryString("token"); $scope.collection = { _: new BgoRequest({ $timeout: $timeout, $http: $http, $scope: $scope }), data: null, ifEmpty: function (value1, value2) { return value1 == undefined || value1.trim().length == 0 ? value2 : value1; }, toggle: function (x, value) { x.Hide = value; }, onBlur: function () { var items = $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items; var jobRefresh = true; items.forEach(function (o) { if (o.Employer == undefined || o.Employer.length == 0) jobRefresh = false; else if (o.Start == undefined || o.Start.length == 0) jobRefresh = false; else if (o.Current == false && (o.End == undefined || o.End.length == 0)) jobRefresh = false; }); if (jobRefresh) $scope.collection.getTimeline(); }, getTimeline: function () { var items = $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items; if (items.length > 0) { $scope.collection._.postJson("/api/applicant/GetTimeline", { config: { data: { token: token, employments: $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items } }, success: function () { $timeout(function () { scaleTimeline(); }, 0); } }); } }, addNew: function ($event, x) { cancelEvent($event); var defaultItem = { Employer: "", Start: "", End: "" }; var existing = undefined; if (x != undefined) { existing = Object.fromEntries( Object.keys(defaultItem).map(key => [key, x[key] !== undefined ? x[key] : defaultItem[key]]) ); } $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].NoHistory = false; $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items.push(existing || defaultItem); if (x != undefined) $scope.collection.getTimeline(); }, delete: function ($event, $index) { cancelEvent($event); $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items.splice($index, 1); $scope.collection.getTimeline(); }, currentStep: function () { var currentStepName = $scope.$parent.currentStep; return $scope.$parent.applicant.request.data?.Steps?.Active?.find(function (x) { return x.data == currentStepName; }); }, index: undefined, }; this.$onInit = function () { if ($scope.applicant.request.data.Information.DataCollection == undefined) $scope.applicant.request.data.Information.DataCollection = []; $scope.collection.index = $scope.applicant.request.data.Information.DataCollection.findIndex(function (x) { return x.CollectionType == "Employment" }); if ($scope.collection.index < 0) { $scope.applicant.request.data.Information.DataCollection.push({ CollectionType: "Employment" }); $scope.collection.index = $scope.applicant.request.data.Information.DataCollection.findIndex(function (x) { return x.CollectionType == "Employment" }); } if ($scope.applicant.request.data.Information.DataCollection[$scope.collection.index].CollectionType == undefined) $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].CollectionType = "Employment"; if ($scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items == undefined) $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items = []; if ($scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items.length == 0) { //$scope.collection.addNew(); // $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items = // [ // // { Employer: "Peoplefinders", Start: "011990", End: "", Current: "true" }, // // { Employer: "Informdata", Start: "012022", End: "062022", Current: "false" }, // // { Employer: "CA State Lottery", Start: "012013", End: "122024", Current: "false" }, // { Employer: "BGO", Start: "012024", End: "", Current: "true" } // ]; } $scope.collection.getTimeline(); }; function scaleTimeline() { const wrapper = document.querySelector('.timeline-scale-wrapper'); const content = document.querySelector('.timeline-scale-content'); if (!wrapper || !content) return; content.style.transform = 'scale(1)'; const available = wrapper.clientWidth; const needed = content.scrollWidth; const scale = Math.min(available / needed, 1); content.style.transform = `scale(${scale})`; } // Re-scale on resize/orientation change window.addEventListener('resize', scaleTimeline); window.addEventListener('orientationchange', scaleTimeline); }); angular.module("clientApp").controller('instructionsCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('drugCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('dataCollectionCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { $scope.collection = { data: null, types: [{ text: "Employer", value: "Employer" }, { text: "School", value: "School" }], addNew: function ($event, x) { cancelEvent($event); var defaultItem = { Type: null, Address: "", City: "", State: "", Zip: "" }; var existing = undefined; if (x != undefined) { existing = Object.fromEntries( Object.keys(defaultItem).map(key => [key, x[key] !== undefined ? x[key] : defaultItem[key]]) ); } $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items.push(existing || defaultItem); }, delete: function ($event, $index) { cancelEvent($event); $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items.splice($index, 1); if ($scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items.length == 0) $scope.collection.addNew(); }, currentStep: function () { var currentStepName = $scope.$parent.currentStep; return $scope.$parent.applicant.request.data?.Steps?.Active?.find(function (x) { return x.data == currentStepName; }); }, index: undefined, }; this.$onInit = function () { if ($scope.applicant.request.data.Information.DataCollection == undefined) $scope.applicant.request.data.Information.DataCollection = []; $scope.collection.index = $scope.applicant.request.data.Information.DataCollection.findIndex(function (x) { return x.CollectionType == "Address" }); if ($scope.collection.index < 0) { $scope.applicant.request.data.Information.DataCollection.push({}); $scope.collection.index = 0; } if ($scope.applicant.request.data.Information.DataCollection[$scope.collection.index].CollectionType == undefined) $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].CollectionType = "Address"; if ($scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items == undefined) $scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items = []; if ($scope.applicant.request.data.Information.DataCollection[$scope.collection.index].Items.length == 0) $scope.collection.addNew(); }; }); angular.module('core').factory("SseService", function ($http, $rootScope, $timeout) { var svc = {}; var source = null; var clientId = null; var reconnectDelay = 2000; var shouldReconnect = false; // ?? controls on-demand reconnect svc.start = function () { // Prevent duplicate connections if (source !== null) { console.warn("SSE already running"); return; } shouldReconnect = true; console.log("Starting SSE…"); source = new EventSource("/api/applicant/stream"); // Connected source.onopen = function () { console.log("SSE connected"); reconnectDelay = 2000; $rootScope.$broadcast("sse:connected"); }; // Receive clientId source.addEventListener("clientId", function (e) { clientId = e.data; console.log("Client ID:", clientId); $rootScope.$broadcast("sse:clientId", clientId); }); // Receive update events source.addEventListener("update", function (e) { var data = JSON.parse(e.data); console.log("Update event:", data); $rootScope.$broadcast("sse:update", data); }); // Heartbeat source.addEventListener("ping", function () { console.log("heartbeat"); $rootScope.$broadcast("sse:heartbeat"); }); // Disconnect / error source.onerror = function () { console.warn("SSE disconnected"); $rootScope.$broadcast("sse:disconnected"); source.close(); source = null; if (!shouldReconnect) { console.log("SSE stopped manually — no reconnect"); return; } // Auto-reconnect $timeout(function () { svc.start(); reconnectDelay = Math.min(reconnectDelay * 1.5, 30000); }, reconnectDelay); }; }; // ?? STOP SSE COMPLETELY svc.stop = function () { console.log("Stopping SSE…"); shouldReconnect = false; if (source) { source.close(); source = null; } }; // Expose clientId svc.getClientId = function () { return clientId; }; return svc; }); angular.module("clientApp").controller('idvCtrl', ['$scope', '$rootScope', '$http', '$sce', '$timeout', 'SseService', function ($scope, $rootScope, $http, $sce, $timeout, SseService) { this.$onInit = function () { var idvStep = $scope.applicant.request.data?.Steps?.Active?.find(x => x.data == "IDV") || {}; if (idvStep != undefined) { Object.assign($scope.applicant.request.data.Information, { NoMobile: false, NoMobile_Certify: false, NoMobile_Signature: "" } ); $scope.plaid.step = idvStep; if ($scope.plaid.step.link_token?.length > 0) { if ($scope.plaid.step.idv_status == "success") { $scope.plaid.complete(); } else { $scope.plaid.state = "started"; $scope.plaid.started = true; $scope.applicant.saving.done = false; } } } $timeout(function () { $("form bgo-input input:visible:first").focus(); }, 200); }; $scope.plaid = { progress: new BgoRequest({ $timeout: $timeout, $http: $http, $scope: $scope }), _: new BgoRequest({ $timeout: $timeout, $http: $http, $scope: $scope }), _get: new BgoRequest({ $timeout: $timeout, $http: $http, $scope: $scope }), listenState: "disconnected", state: "start", step: {}, started: false, lastHeartbeat: Date.now(), evtSource: undefined, manualClose: false, heartbeatInterval: null, activity: [], //Start: "ACCEPT_TOS", Start: "VERIFY_SMS", Start: "DOCUMENTARY_VERIFICATION", Pass: "RISK_CHECK", Pass: ""DOCUMENTARY_VERIFICATION"" //IDENTITY_VERIFICATION_PASS_SESSION steps: [ { label: "Phone Verification", value: "VERIFY_SMS", completed: false, active: false }, { label: "Document Verification", value: "DOCUMENTARY_VERIFICATION", completed: false, active: false }, { label: "Validation", completed: false, active: false } ], supportsDesktop: function () { return $scope.plaid.step?.idv_desktop == true; }, isActive: function (x) { if (!$scope.plaid._.done) return false; return x?.label == $scope.plaid.steps.find(o => o.completed == false)?.label; }, saveProgress: function (data) { $scope.plaid._.postJson("/anonproxy/bgoplaid/SaveProgress", { config: { data: data } }); }, setListenState: function (value) { $timeout(() => { $scope.plaid.listenState = value; }); }, startListening: function () { }, listen: function () { $scope.plaid.setListenState("connecting"); SseService.start(); }, complete: function () { //console.log("plaid.complete"); $scope.plaid.state = "completed"; $timeout(function () { $scope.plaid.activity.push({ data: { eventName: "Validating Submission" } }); }); $scope.plaid.steps.forEach(function (x) { if (x != $scope.plaid.steps[$scope.plaid.steps.length - 1]) { x.completed = true; } }); }, cancelNoMobile: function () { $scope.applicant.request.data.Information.NoMobile = false; Object.assign($scope.applicant.request.data.Information, { NoMobile_Certify: false, NoMobile_Signature: "" } ); }, start: function () { $timeout(function () { $scope.plaid.activity.push({ data: { eventName: "" } }); }); $scope.plaid._.postJson("/anonproxy/bgoplaid/CreateIdvToken", { config: { data: { token: $scope.token } }, success: function () { $scope.plaid.state = "started"; $scope.plaid.started = true; $scope.applicant.saving.done = false; const handler = Plaid.create({ token: $scope.plaid._.data.link_token, onSuccess: function(public_token, metadata) { $scope.plaid.complete(); //console.log("IDV completed:", metadata); $scope.plaid._get.postJson("/anonproxy/bgoplaid/GetFlowData", { config: { data: { token: $scope.token } }, success: function () { $scope.plaid.step.idv_status = $scope.plaid._get.data.status; Object.assign($scope.applicant.request.data.Information, $scope.plaid._get.data.Information); }, fail: function (r) { $timeout(function () { $scope.plaid.activity.push({ data: { eventName: "Error" } }); }); if (r.data?.message?.startsWith("{")) $scope.plaid._get.data = JSON.parse(r.data.message); else $scope.plaid._get.data = r.data; $scope.plaid.steps[$scope.plaid.steps.length - 1].error = true; } }); }, onExit: function(err, metadata) { //console.log("User exited IDV:", err, metadata); }, onEvent: function(eventName, metadata) { //console.log("Event:", eventName, metadata); var activity = eventName .replace("IDENTITY_VERIFICATION_START_STEP", "Starting") + " " + metadata.view_name .replace("VERIFY_SMS", "Phone Verification") .replace("DOCUMENTARY_VERIFICATION", "Document Verification"); if (eventName == "IDENTITY_VERIFICATION_START_STEP") { var index = $scope.plaid.steps.findIndex(s => s.value === metadata.view_name); if (index >= 0) { $scope.plaid.steps.forEach((s, i) => { if (i < index) s.complete = true; }); } } else if (eventName == "IDENTITY_VERIFICATION_PASS_STEP") { var step = $scope.plaid.steps.find(o => o.value == metadata.view_name); if (step) step.complete = true; } $timeout(function () { $scope.plaid.activity.push({ data: { eventName: activity } }); }); } }); // 3. Open Plaid Link handler.open(); } }); } }; $scope.getErrors = function (field) { return $scope.applicant.saving?.errors?.find(o => o.key == field)?.exceptions || []; }; $scope.getError = function (field) { return $scope.getErrors(field).join("
"); }; $scope.$on("sse:connected", () => { $scope.plaid.setListenState("connected"); }); }]); angular.module("clientApp").controller('caDisclosureCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('investigativeCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('authorizationCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('genericCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('californiaCreditCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('nycCreditCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('vermontCreditCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('mvrCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('locationsCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('disclosureCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('referenceCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('employmentCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('nyAuthCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('educationCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('nycConditionalCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('intCrimCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('paymentCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('informationCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('consentCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('instructionsCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('uploadCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { }); angular.module("clientApp").controller('genericCtrl', function ($scope, $rootScope, $timeout, $http, $sce, $timeout) { });