PageSourceSearch

https://app.exabler.com/app/components/home/onboarding.wizard.component.js

js exabler.com collected 2026-09-24 10:21:14 UTC 16,237 bytes, 434 lines download raw bytes

1app.component("onboardingWizard", {
2    bindings: {
3        provider: '<?'
4    },
5    templateUrl: "/app/components/home/onboarding.wizard.html",
6
7    controller: function ($uibModal, $log, $localstorage, AuthService, $rootScope, $timeout, $location) {
8
9
10        let self = this;
11
12        self.onboarder_dismissed = false;
13        self.onboarding_actions = [];
14        self.onboarding_progress = 0;
15        self.onboarding_steps_complete = 0;
16        self.onboarding_max = 0;
17
18        let onboarding_var = AuthService.User.role + '_onboarding';
19        let onboarding_id = AuthService.User.orgid + '_orgid';
20        let onboarding_actions = onboarding_var + '_actions';
21        
22
23        let provider_onboarding_actions = [
24            {id: 1, title: "Upload a logo", complete: false, href: "/uorg/uploads"},
25            // {id: 1, title: "Run the tour", complete: false},
26            // {id: 2, title: "Watch the product video", complete: false},
27            {id: 2, title: "Complete a Trade Services Hub profile", complete: false, action: true},
28            {id: 3, title: "Complete company address/EORI", href: "/uorg/registrations", complete: false},
29            {id: 4, title: "Create a client workspace", complete: false, action: true },
30            {id: 5, title: "Invite colleagues", href: "/uorg/contacts", complete: false},
31        ];
32
33        let trader_onboarding_actions = [
34            {id: 1, title: "Run the tour", complete: false},
35            {id: 2, title: "Watch the product video", complete: false},
36            {id: 4, title: "Invite colleagues", complete: false},
37            {id: 5, title: "Complete company details", complete: false},
38            {id: 6, title: "Upload a logo", complete: false}
39        ];
40
41
42        self.$onInit = function () {
43
44            let onboarding_history = $localstorage.getObject(onboarding_var);
45
46            if (!(onboarding_history && onboarding_history.actions) ||
47                !(onboarding_id == onboarding_history.id)) // todo add version check too               
48             {
49                
50                let config;
51                if (AuthService.User.role == 'provider' && [6,7,8].includes(AuthService.User.base_plan_id)) {
52                    config = angular.copy({ id: onboarding_id, version: 'p1.01', dismissed: self.onboarder_dismissed, actions: provider_onboarding_actions} );
53                } else if ([1,2,3].includes(AuthService.User.base_plan_id)) {
54                    config = angular.copy({ id: onboarding_id, version: 't0.01', dismissed: self.onboarder_dismissed, actions: trader_onboarding_actions} );
55                } else {
56                    return
57                }
58
59                $localstorage.setObject(onboarding_var, config);
60                self.onboarding_actions = config.actions;
61
62            } else {
63                
64                self.onboarding_actions = onboarding_history.actions;
65                self.onboarder_dismissed = onboarding_history.dismissed;
66                // check to see if it where it is different, add the new or changed titles
67            }
68
69            updateWizard();
70
71        }
72
73
74        let updateWizard = function () {
75            const tempFilterData = _.filter(self.onboarding_actions, { complete: true });
76            self.onboarding_steps_complete = (tempFilterData && tempFilterData.length) || 0;
77            self.onboarding_max = self.onboarding_actions.length;
78            self.onboarding_progress = Math.floor(self.onboarding_steps_complete / self.onboarding_actions.length * 100 + 1);
79            
80            $rootScope.$emit('watchOnBoardingProgress');
81        }
82
83
84        $rootScope.$on('onboarding-action', (event, data) => {
85
86            let index = self.onboarding_actions.findIndex((action) => {
87                return (action.id == data)
88            })
89
90            if (index > -1) {
91
92               self.onboarding_actions[index].complete = true;
93                updateWizard();
94            }
95
96            let update_local = $localstorage.getObject(onboarding_var);
97            update_local.actions = self.onboarding_actions;
98            $localstorage.setObject(onboarding_var, update_local);
99            //console.log("receiving onboard completion event")
100            $rootScope.$emit('watchOnBoardingProgress');
101        });
102
103
104        self.dismissOnboarder = function (dismissed = true) {
105            
106            let onboarding_history = $localstorage.getObject(onboarding_var);
107            onboarding_history.dismissed = dismissed;
108            // am not why I need the scope apply! (normally only used if outside angular)
109            $localstorage.setObject(onboarding_var, onboarding_history);
110
111            self.onboarder_dismissed = dismissed;
112
113        }
114        
115        self.reopen_onboarder = function () {
116            self.dismissOnboarder(false);
117        }
118
119        $rootScope.$on("reopenOnboardingAction", self.reopen_onboarder);
120
121        self.launchAction = function (id) {
122
123            switch (id) {
124                case 4:
125                    openAddClient();
126                    break
127                case 2:
128                    openTshProfile();
129                    break
130                default:
131                    const action = provider_onboarding_actions.find((el)=>{return el.id == id });
132                    $location.path(action.href || '#');
133                    return
134            }
135        }
136
137        let openAddClient = function () {
138
139            $location.path('/home');
140            
141            $timeout(()=>{
142                $rootScope.$emit('open-add-client',{});
143            },1000)
144            
145            
146                      
147        }
148
149
150        let openTshProfile = function () {
151            var modalInstance = $uibModal.open({
152                animation: true,
153                component: 'tshProfile'
154                //   resolve: {
155                //     items: function () {
156                //       return $ctrl.items;
157                //     }
158                //   }
159            });
160
161            modalInstance.result.then(function (selectedItem) {
162                self.selected = selectedItem;
163            }, function () {
164                $log.info('modal-component dismissed at: ' + new Date());
165            });
166        };
167
168
169    }
170});
171
172
173app.component("tshProfile", {
174    bindings: {
175        resolve: '<',
176        close: '&',
177        dismiss: '&'
178    },
179    templateUrl: "tshOnboardQuestions.html",
180
181    controller: function (
182        $rootScope,
183        $localstorage,
184        $timeout,
185        $http,
186        orgServices,
187        AuthService,
188        TradeModelService) {
189
190
191        var self = this;
192
193        $http.get('/data/onboarding.php').then((results) => {
194            
195            let user_type;
196            if ([6].includes(AuthService.User.base_plan_id)) {
197                user_type = "freight";
198            } else if ([7,8].includes(AuthService.User.base_plan_id)) {
199                user_type = "customs_agent";
200            }
201            const found = results.data[0].find((elem) => { return elem.user_type === user_type; });
202            if (found) self.onboarding_questions = found.questions;
203
204        });
205
206
207        var currentTab = 0; // Current tab is set to be the first tab (0)
208        self.currentOrgData = null;
209        
210        self.$onInit = function () {
211
212
213            $timeout(() => {
214                showTab(currentTab); // Display the current tab
215                
216                self.currentUser = AuthService.User;
217                orgServices.getMyOrganisation()
218                .then((result) => {
219                    self.currentOrgData = result;
220                    
221                    const previously_completed = _.get(result, "extra_data.tsh_profile", []);
222                    if (previously_completed.length > 0) {
223                        // self.onboarding_questions = previously_completed;
224                    }
225
226                    if (self.onboarding_questions) {
227                        self.onboarding_questions = self.onboarding_questions.map(function (item) {
228                            // if (item.type === 'select') {
229                            //     item.selectedValue = item.options.length > 0 ? item.options[0].value : '';
230                            // }
231                            if (typeof item.options === 'string') {
232                                if (item.options === 'regions') {
233                                    item.options = self.countries;
234                                } else if (item.options === 'ukports') {
235                                    item.options = self.ukports;
236                                }
237                            }
238                            previously_completed.forEach((pitem) => {
239                                if (pitem.name === item.name) {
240                                    if (pitem.selectedValue) item.selectedValue = pitem.selectedValue;
241                                    if (pitem.selectedOptions) item.selectedOptions = pitem.selectedOptions;
242                                    if (pitem.other_options) item.other_options = pitem.other_options;
243                                }
244                            })
245                            return item;
246                        });
247                    }
248                    
249                })
250                .catch((error) => {
251                    console.error("Problem getting provider details in onboarding modal " + JSON.stringify(error));
252                });
253
254            },500)
255
256        }
257        self.ok = async function () {
258
259            // save to org data of my company 
260            // capture all the questions and save on the org data
261            // so it is saved under extra_data.tsh_profile = {} an object 
262
263            if (self.currentOrgData && self.currentOrgData.extra_data) {
264
265                self.onboarding_questions.forEach((question)=>{
266                    if(question.options)
267                        delete question.options
268                        delete question.label
269                        delete question.type
270                })
271
272                self.currentOrgData.extra_data.tsh_profile = self.onboarding_questions;
273               
274
275                await orgServices.updateUOrg(self.currentOrgData).then(function(resp) {
276                    if (resp && resp.status === 200 && resp.data && resp.data.success) {
277                    }
278                }).catch(function(err) {
279                    console.log('Getting error while updating organisation data for onboarding wizard', err)
280                });
281            }
282            
283            $rootScope.$emit('onboarding-action', 2);
284
285            // todo -- add a update to the onboarding wizard local storage to set this item complete
286            // 
287
288            self.close({$value: 'ok'});
289        };
290
291        self.cancel = async function () {
292            
293            if (self.currentOrgData && self.currentOrgData.extra_data) {
294
295                self.onboarding_questions.forEach((question)=>{
296                    if(question.options)
297                        delete question.options
298                        delete question.label
299                        delete question.type
300                })
301
302                self.currentOrgData.extra_data.tsh_profile = self.onboarding_questions;
303
304                await orgServices.updateUOrg(self.currentOrgData);
305            }
306            
307            self.dismiss({$value: 'cancel'});
308            
309        };
310
311        self.countries = TradeModelService.ordered_countries_list.map((c) => {
312            return {value: c.alpha_2, text: c.name}
313        });
314        self.ukports = TradeModelService.CDS_locations_array.map((loc) => {
315            return {value: loc.code, text: loc.code+" - "+loc.desc}
316        });
317
318        function showTab(n) {
319            // This function will display the specified tab of the form ...
320            var x = document.getElementsByClassName("tab");
321
322            x[n].style.display = "block";
323            // ... and fix the Previous/Next buttons:
324            if (n == 0) {
325                document.getElementById("prevBtn").style.display = "none";
326            } else {
327                document.getElementById("prevBtn").style.display = "inline";
328            }
329            if (n == (x.length - 1)) {
330                document.getElementById("nextBtn").innerHTML = "Submit";
331            } else {
332                document.getElementById("nextBtn").innerHTML = "Next";
333            }
334            // ... and run a function that displays the correct step indicator:
335       //     fixStepIndicator(n)
336        }
337
338        self.nextPrev = function (n) {
339            // This function will figure out which tab to display
340            var x = document.getElementsByClassName("tab");
341            // Exit the function if any field in the current tab is invali
341d:
342            if (n == 1 && !validateForm()) return false;
343            // Hide the current tab:
344            x[currentTab].style.display = "none";
345            // Increase or decrease the current tab by 1:
346            currentTab = currentTab + n;
347            // if you have reached the end of the form... :
348            if (currentTab >= x.length) {
349                //...the form gets submitted:
350                //document.getElementById("regForm").submit();
351                // set next steps
352
353                return false;
354            }
355            // Otherwise, display the correct tab:
356            showTab(currentTab);
357        }
358
359        let validateForm = function () {
360
361            return true; // disabled
362
363            // This function deals with validation of the form fields
364            var x, y, i, valid = true;
365            x = document.getElementsByClassName("tab");
366            y = x[currentTab].getElementsByTagName("select");
367            // A loop that checks every input field in the current tab:
368            for (i = 0; i < y.length; i++) {
369                // If a field is empty...
370                if (y[i].value == "") {
371                    // add an "invalid" class to the field:
372                    y[i].className += " invalid";
373                    // and set the current valid status to false:
374                    valid = false;
375                }
376            }
377            // If the valid status is true, mark the step as finished and valid:
378            if (valid) {
379                document.getElementsByClassName("step")[currentTab].className += " finish";
380            }
381            return valid; // return the valid status
382        }
383        
384        self.toggle = function(question) {
385            if (!question.all_selected) {
386                question.selectedValue = question.options.map((o) => {
387                    return o.value
388                });
389                question.all_selected = true;
390            } else {
391                question.selectedValue = undefined;
392                question.all_selected = false;
393            }
394        }
395        
396        self.addToSelected = function(question, option) {
397            if (!question.selectedOptions) question.selectedOptions = [];
398            // don't add if already existing
399            question.selectedOptions.push(option);
400        }
401        
402        self.deleteFromSelected = function(question, idx) {
403            question.selectedOptions.splice(idx, 1);
404        }
405        
406        self.addOther = function(question) {
407            if (!question.other_options) question.other_options = [];
408            question.other_options.push({text: "", value: ""});
409        }
410        
411        self.updateOther = function(question, idx) {
412            const user_input = question.other_options[idx].text;
413            question.other_options[idx] = {text: user_input, value: user_input, cardtext: user_input};
414        }
415        
416        self.deleteOther = function(question, idx) {
417            question.other_options.splice(idx, 1);
418        }
419
420        // let fixStepIndicator = function (n) {
421
422        //     // This function removes the "active" class of all steps...
423        //     var i, x = document.getElementsByClassName("#RegForm.step");
424        //     for (i = 0; i < x.length; i++) {
425        //         x[i].className = x[i].className.replace(" active", "");
426        //     }
427        //     //... and adds the "active" class to the current step:
428        //     x[n].className += " active";
429        // }
430
431
432    }
433});
434

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.