public RegistrationTypeSelectionPageViewModel(
            INavigationService navigationService,
            IAnalyticService analyticService,
            IFirebaseAuthService authService,
            IUserDialogs dialogs) : base(navigationService)
        {
            Title = "Registration Type";
            analyticService.TrackScreen("registration-type");

            Tradesman = ReactiveCommand.CreateFromTask(async() =>
            {
                await dialogs.AlertAsync("Coming Soon!").ConfigureAwait(false);
                analyticService.TrackTapEvent("register-as-tradesman");

                //await navigationService.NavigateAsync(nameof(TradesmentRegistrationPage)).ConfigureAwait(false);
            });

            Contractor = ReactiveCommand.CreateFromTask(async() =>
            {
                analyticService.TrackTapEvent("register-as-contractor");
                await navigationService.NavigateAsync(
                    nameof(ContractorRegistrationPage),
                    new NavigationParameters {
                    { "user_id", _userId }
                }).ConfigureAwait(false);
            });

            GoBack = ReactiveCommand.CreateFromTask <Unit, Unit>(async _ =>
            {
                var result = await dialogs.ConfirmAsync(
                    new ConfirmConfig
                {
                    Title      = "Cancel Account Creation?",
                    Message    = "Are you sure you want to cancel account creation?  This will discard any information you have entered so far",
                    OkText     = "Yes",
                    CancelText = "No"
                });
                if (result)
                {
                    analyticService.TrackTapEvent("cancel-account-creation");

                    // make sure we log out so the user has to log in again
                    await authService.Logout();

                    await NavigationService.NavigateToLoginPageAsync().ConfigureAwait(false);
                }

                return(Unit.Default);
            });

            NavigatingTo
            .Where(args => args.ContainsKey("user_id"))
            .Select(args => args["user_id"].ToString())
            .BindTo(this, x => x._userId);
        }
Example #2
0
        public ContactUsPageViewModel(
            INavigationService navigationService,
            IAnalyticService analyticService,
            IUserService userService) : base(navigationService)
        {
            Title = "Contact Us";
            analyticService.TrackScreen("contact-us-page");
            AddValidationRules();

            Submit = ReactiveCommand.CreateFromTask(
                async _ =>
            {
                if (!IsValid())
                {
                    return;
                }

                analyticService.TrackTapEvent("submit");

                var random = new Random();
                await Task.Delay(random.Next(400, 2000));
                await NavigationService.GoBackAsync(useModalNavigation: true).ConfigureAwait(false);
            });

            Submit.IsExecuting
            .StartWith(false)
            .ToProperty(this, x => x.IsBusy, out _isBusy);

            NavigatingTo
            .Take(1)
            .Subscribe(_ =>
            {
                Email.Value = userService.AuthenticatedUser.EmailAddress;
            });
        }
Example #3
0
        public ProjectsPageViewModel(
            INavigationService navigationService,
            IProjectDataStore projectDataStore,
            IAnalyticService analyticService) : base(navigationService)
        {
            Title = "Projects";

            this.WhenActivated((CompositeDisposable _) =>
            {
                // track every time this screen is activated
                analyticService.TrackScreen("my-projects");
            });

            ViewProjectDetails = ReactiveCommand.CreateFromTask <Project, Unit>(async project =>
            {
                analyticService.TrackTapEvent("view-project");

                await NavigationService.NavigateAsync(
                    nameof(ProjectDetailsPage),
                    new NavigationParameters
                {
                    { "project", project }
                }).ConfigureAwait(false);

                return(Unit.Default);
            });

            AddProject = ReactiveCommand.CreateFromTask(async() =>
            {
                analyticService.TrackTapEvent("new-project");
                await NavigationService.NavigateAsync($"NavigationPage/{nameof(EditProjectPage)}", useModalNavigation: true).ConfigureAwait(false);
            });

            Filter = ReactiveCommand.CreateFromTask(async() =>
            {
                // TODO: Finish this
                await NavigationService.NavigateAsync(
                    $"NavigationPage/{nameof(ProjectFilterPage)}",
                    new NavigationParameters
                {
                    { "filter", _filter }
                },
                    useModalNavigation: true).ConfigureAwait(false);
            });

            // set up the command used to load projects
            LoadProjects = ReactiveCommand.CreateFromTask(_ =>
            {
                this.Log().Debug($"Loading projects on thread: {Thread.CurrentThread.ManagedThreadId}, IsBackground = {Thread.CurrentThread.IsBackground}");
                AssertRunningOnBackgroundThread();
                return(projectDataStore.LoadOldProjects(_oldestProject, ItemsPerPage));
            });

            // set up the command used to refresh projects
            RefreshProjects = ReactiveCommand.CreateFromTask(_ =>
            {
                // TODO: Should track this with analytics?
                this.Log().Debug($"Refreshing projects on thread: {Thread.CurrentThread.ManagedThreadId}, IsBackground = {Thread.CurrentThread.IsBackground}");
                AssertRunningOnBackgroundThread();
                return(_newestProject != null ?
                       projectDataStore.LoadNewProjects(_newestProject, ItemsPerPage) :
                       projectDataStore.LoadNewProjects(ItemsPerPage));
            });

            LoadProjects
            .Merge(RefreshProjects)
            .SubscribeSafe(projects =>
            {
                if (projects.Any())
                {
                    // NOTE: This probably isn't necessary...
                    projects = projects.ExceptBy(Projects, p => p.ProjectId);

                    // get the oldest and newest projects from the new data set. Age is simply
                    // determined by the date the project was created
                    var oldProject = projects.MinBy(p => p.CreateDate).First();
                    var newProject = projects.MaxBy(p => p.CreateDate).First();

                    if (_oldestProject == null && _newestProject == null)
                    {
                        _oldestProject = oldProject;
                        _newestProject = newProject;

                        // first projects being added. Add them to the list
                        Projects.AddRange(projects);
                    }
                    else if (_oldestProject?.CreateDate > oldProject.CreateDate)
                    {
                        _oldestProject = oldProject;

                        // if the projects are older, add them to the end of the list
                        Projects.AddRange(projects);
                    }
                    else if (_newestProject?.CreateDate < newProject.CreateDate)
                    {
                        _newestProject = newProject;

                        // if the projects are newer, insert them at the beginning of the list
                        Projects.InsertRange(0, projects);
                    }
                }
            });

            // when either of the commands are executing, update the busy state
            LoadProjects.IsExecuting
            .CombineLatest(RefreshProjects.IsExecuting, (isLoadExecuting, isRefreshExecuting) => isLoadExecuting || isRefreshExecuting)
            .DistinctUntilChanged()
            .StartWith(false)
            .ToProperty(this, x => x.IsBusy, out _isBusy, scheduler: RxApp.MainThreadScheduler);

            // When an exception is thrown for either command, log the error and let the user handle
            // the exception
            LoadProjects.ThrownExceptions
            .Merge(RefreshProjects.ThrownExceptions)
            .SelectMany(exception =>
            {
                this.Log().ErrorException("Error loading or refreshing data", exception);
                return(SharedInteractions.Error.Handle(exception));
            })
            .Subscribe();
        }
Example #4
0
        public EditProjectPageViewModel(
            INavigationService navigationService,
            IUserDialogs dialogService,
            IAnalyticService analyticService) : base(navigationService)
        {
            Title = "New Project";
            analyticService.TrackScreen("edit-project-page");

            // store the fields in an enumerable for easy use later on in this class
            _validatableFields = new IValidity[]
            {
                ProjectName,

                //StartStatus,
                Description,
                SkillsRequired,
                PayRate,

                //PaymentType
            };

            AddValidationRules();

            Save = ReactiveCommand.CreateFromTask(async() =>
            {
                if (!IsValid())
                {
                    return;
                }

                analyticService.TrackTapEvent("save");

                if (_project != null)
                {
                    // if the product was being edited, map the local fields back to the project and
                    // save it
                    //_project.Name = ProjectName.Value;
                    _project.Description = Description.Value;

                    //_project.SkillsRequired = SkillsRequired.Value;
                    //_project.PaymentRate = decimal.Parse(PayRate.Value);
                    //_project.PaymentType = PaymentType.Value;

                    //switch (StartStatus.Value)
                    //{
                    //    case ProjectStartStatus.ReadyNow:
                    //        _project.EstimatedStartDate = DateTime.Today;
                    //        break;

                    // case ProjectStartStatus.OneToTwoWeeks: _project.EstimatedStartDate =
                    // DateTime.Today.AddDays(7); break;

                    // case ProjectStartStatus.ThreeToFourWeeks: _project.EstimatedStartDate =
                    // DateTime.Today.AddDays(7 * 3); break;

                    // case ProjectStartStatus.FiveOrMoreWeeks: _project.EstimatedStartDate =
                    // DateTime.Today.AddDays(7 * 5); break;

                    //    default:
                    //        throw new InvalidOperationException("Invalid start status");
                    //}

                    // TODO: projectDataStore.Update(_project);
                }
                else
                {
                    // the project was a new project. Save it

                    // TODO: projectDataStore.Save(_project);
                }

                // TODO: Return the project in the navigation parameters so we can refresh it in the UI of the calling page.

                await NavigationService.GoBackAsync(useModalNavigation: true).ConfigureAwait(false);
            });

            Cancel = ReactiveCommand.CreateFromTask(async() =>
            {
                if (_validatableFields.Any(field => field.IsChanged))
                {
                    bool keepEditing = await dialogService.ConfirmAsync(
                        new ConfirmConfig
                    {
                        Title      = "Unsaved changes",
                        Message    = "Are you sure you want to discard this project?",
                        OkText     = "Keep Editing",
                        CancelText = "Discard"
                    });
                    if (keepEditing)
                    {
                        // the user has chosen the option to continue editing
                        return;
                    }
                }

                analyticService.TrackTapEvent("cancel");

                // if there are no changes, or the user chooses to discard, go back to the previous screen
                await NavigationService.GoBackAsync(useModalNavigation: true).ConfigureAwait(false);
            });

            NavigatingTo
            .Take(1)
            .Where(args => args.ContainsKey("project"))
            .Select(args => (Project)args["project"])
            .Subscribe(project =>
            {
                // store the project being edited
                _project = project;
                Title    = "Edit Project";

                // map the project being edited to the local fields
                //ProjectName.Value = project.Name;
                //StartStatus.Value = project.StartStatus;
                Description.Value = project.Description;

                //SkillsRequired.Value = project.SkillsRequired;
                //PayRate.Value = project.PaymentRate.ToString();
                //PaymentType.Value = project.PaymentType;

                // accept changes for all fields
                foreach (var field in _validatableFields)
                {
                    field.AcceptChanges();
                }
            });

            // accept changes so we can determine whether they've been changed later on
            foreach (var field in _validatableFields)
            {
                field.AcceptChanges();
            }
        }
        public MyProjectsPageViewModel(
            INavigationService navigationService,
            IProjectDataStore projectDataStore,
            IUserDialogs dialogService,
            IUserService userService,
            IAnalyticService analyticService) : base(navigationService)
        {
            Title = "My Projects";

            this.WhenActivated((CompositeDisposable _) =>
            {
                // track every time this screen is activated
                analyticService.TrackScreen("my-projects");
            });

            var initialize = ReactiveCommand.CreateFromTask <Unit, IEnumerable <Project> >(_ =>
            {
                AssertRunningOnBackgroundThread();
                return(projectDataStore.LoadProjectsForUser(userService.AuthenticatedUser.AccountId));
            });

            initialize
            .Subscribe(projects =>
            {
                Projects.Reset(projects.Select(proj => new MyProjectViewModel(proj, Delete, Close, Edit)));
            });

            Projects.ActOnEveryObject(
                _ =>
            {
                this.Log().Debug("Item added");
            },
                projViewModel =>
            {
                this.Log().Debug("Item removed");

                // make sure we dispose of the item to release the subscription from the item's
                // commands to our commands
                projViewModel.Dispose();
            });

            // When an exception is thrown while loading data, log the error and let the user handle
            // the exception
            initialize.ThrownExceptions
            .SelectMany(exception =>
            {
                this.Log().ErrorException("Error loading or refreshing data", exception);
                return(SharedInteractions.Error.Handle(exception));
            })
            .Subscribe();

            Activator
            .Activated
            .Take(1)
            .ObserveOn(RxApp.TaskpoolScheduler)
            .InvokeCommand(initialize);

            ViewProjectDetails = ReactiveCommand.CreateFromTask <MyProjectViewModel, Unit>(async project =>
            {
                analyticService.TrackTapEvent("view-project");

                await NavigationService.NavigateAsync(
                    nameof(ProjectDetailsPage),
                    new NavigationParameters
                {
                    { "project", project.Project }
                }).ConfigureAwait(false);

                return(Unit.Default);
            });

            Delete = ReactiveCommand.CreateFromTask <MyProjectViewModel, Unit>(async project =>
            {
                bool shouldDelete = await dialogService.ConfirmAsync(
                    new ConfirmConfig
                {
                    Message    = "Are you sure you want to delete the project?",
                    OkText     = "Delete",
                    CancelText = "Cancel"
                });
                if (!shouldDelete)
                {
                    return(Unit.Default);
                }

                analyticService.TrackTapEvent("delete-project");

                // remove the project
                await projectDataStore.DeleteProjectAsync(project.Project);
                Projects.Remove(project);

                dialogService.Toast(new ToastConfig("Project deleted successfully!"));

                return(Unit.Default);
            });

            Close = ReactiveCommand.CreateFromTask <MyProjectViewModel, Unit>(async project =>
            {
                bool shouldDelete = await dialogService.ConfirmAsync(
                    new ConfirmConfig
                {
                    Message    = "Are you sure you want to close the project?",
                    OkText     = "Close",
                    CancelText = "Cancel"
                });
                if (!shouldDelete)
                {
                    return(Unit.Default);
                }

                analyticService.TrackTapEvent("close-project");

                //project.Project.Status = ProjectStatus.Closed;

                // TODO: Save to the database

                return(Unit.Default);
            });

            Edit = ReactiveCommand.CreateFromTask <MyProjectViewModel, Unit>(async project =>
            {
                analyticService.TrackTapEvent("edit-project");

                await NavigationService.NavigateAsync(
                    $"NavigationPage/{nameof(EditProjectPage)}",
                    new NavigationParameters
                {
                    { "project", project.Project }
                },
                    useModalNavigation: true).ConfigureAwait(false);

                return(Unit.Default);
            });

            initialize.IsExecuting
            .StartWith(false)
            .ToProperty(this, x => x.IsBusy, out _isBusy, scheduler: RxApp.MainThreadScheduler);
        }