using CarCareTracker.External.Interfaces; using CarCareTracker.Models; using Microsoft.AspNetCore.Mvc; using System.Diagnostics; using CarCareTracker.Helper; using Microsoft.AspNetCore.Authorization; using System.Security.Claims; using CarCareTracker.Logic; namespace CarCareTracker.Controllers { [Authorize] public class HomeController : Controller { private readonly ILogger _logger; private readonly IVehicleDataAccess _dataAccess; private readonly IUserLogic _userLogic; private readonly ILoginLogic _loginLogic; private readonly IVehicleLogic _vehicleLogic; private readonly IFileHelper _fileHelper; private readonly IConfigHelper _config; private readonly IExtraFieldDataAccess _extraFieldDataAccess; private readonly IReminderRecordDataAccess _reminderRecordDataAccess; private readonly IReminderHelper _reminderHelper; private readonly ITranslationHelper _translationHelper; public HomeController(ILogger logger, IVehicleDataAccess dataAccess, IUserLogic userLogic, ILoginLogic loginLogic, IVehicleLogic vehicleLogic, IConfigHelper configuration, IFileHelper fileHelper, IExtraFieldDataAccess extraFieldDataAccess, IReminderRecordDataAccess reminderRecordDataAccess, IReminderHelper reminderHelper, ITranslationHelper translationHelper) { _logger = logger; _dataAccess = dataAccess; _config = configuration; _userLogic = userLogic; _fileHelper = fileHelper; _extraFieldDataAccess = extraFieldDataAccess; _reminderRecordDataAccess = reminderRecordDataAccess; _reminderHelper = reminderHelper; _loginLogic = loginLogic; _vehicleLogic = vehicleLogic; _translationHelper = translationHelper; } private int GetUserID() { return int.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)); } public IActionResult Index(string tab = "garage") { return View(model: tab); } [Route("/kiosk")] public IActionResult Kiosk(string exclusions, KioskMode kioskMode = KioskMode.Vehicle) { try { var viewModel = new KioskViewModel { Exclusions = string.IsNullOrWhiteSpace(exclusions) ? new List() : exclusions.Split(',').Select(x => int.Parse(x)).ToList(), KioskMode = kioskMode }; return View(viewModel); } catch (Exception ex) { _logger.LogError(ex.Message); return View(new KioskViewModel()); } } [HttpPost] public IActionResult KioskContent(KioskViewModel kioskParameters) { var vehiclesStored = _dataAccess.GetVehicles(); if (!User.IsInRole(nameof(UserData.IsRootUser))) { vehiclesStored = _userLogic.FilterUserVehicles(vehiclesStored, GetUserID()); } vehiclesStored.RemoveAll(x => kioskParameters.Exclusions.Contains(x.Id)); var userConfig = _config.GetUserConfig(User); if (userConfig.HideSoldVehicles) { vehiclesStored.RemoveAll(x => !string.IsNullOrWhiteSpace(x.SoldDate)); } switch (kioskParameters.KioskMode) { case KioskMode.Vehicle: { var kioskResult = _vehicleLogic.GetVehicleInfo(vehiclesStored); return PartialView("_Kiosk", kioskResult); } case KioskMode.Plan: { var kioskResult = _vehicleLogic.GetPlans(vehiclesStored, true); return PartialView("_KioskPlan", kioskResult); } break; case KioskMode.Reminder: { var kioskResult = _vehicleLogic.GetReminders(vehiclesStored, false); return PartialView("_KioskReminder", kioskResult); } } var result = _vehicleLogic.GetVehicleInfo(vehiclesStored); return PartialView("_Kiosk", result); } public IActionResult Garage() { var vehiclesStored = _dataAccess.GetVehicles(); if (!User.IsInRole(nameof(UserData.IsRootUser))) { vehiclesStored = _userLogic.FilterUserVehicles(vehiclesStored, GetUserID()); } var vehicleViewModels = vehiclesStored.Select(x => { var vehicleVM = new VehicleViewModel { Id = x.Id, ImageLocation = x.ImageLocation, Year = x.Year, Make = x.Make, Model = x.Model, LicensePlate = x.LicensePlate, SoldDate = x.SoldDate, IsElectric = x.IsElectric, IsDiesel = x.IsDiesel, UseHours = x.UseHours, OdometerOptional = x.OdometerOptional, ExtraFields = x.ExtraFields, Tags = x.Tags, DashboardMetrics = x.DashboardMetrics, VehicleIdentifier = x.VehicleIdentifier }; //dashboard metrics if (x.DashboardMetrics.Any()) { var vehicleRecords = _vehicleLogic.GetVehicleRecords(x.Id); var userConfig = _config.GetUserConfig(User); var distanceUnit = x.UseHours ? "h" : userConfig.UseMPG ? "mi." : "km"; if (vehicleVM.DashboardMetrics.Contains(DashboardMetric.Default)) { vehicleVM.LastReportedMileage = _vehicleLogic.GetMaxMileage(vehicleRecords); vehicleVM.HasReminders = _vehicleLogic.GetVehicleHasUrgentOrPastDueReminders(x.Id, vehicleVM.LastReportedMileage); } if (vehicleVM.DashboardMetrics.Contains(DashboardMetric.CostPerMile)) { var vehicleTotalCost = _vehicleLogic.GetVehicleTotalCost(vehicleRecords); var maxMileage = _vehicleLogic.GetMaxMileage(vehicleRecords); var minMileage = _vehicleLogic.GetMinMileage(vehicleRecords); var totalDistance = maxMileage - minMileage; vehicleVM.CostPerMile = totalDistance != default ? vehicleTotalCost / totalDistance : 0.00M; vehicleVM.DistanceUnit = distanceUnit; } if (vehicleVM.DashboardMetrics.Contains(DashboardMetric.TotalCost)) { vehicleVM.TotalCost = _vehicleLogic.GetVehicleTotalCost(vehicleRecords); } } return vehicleVM; }).ToList(); return PartialView("_GarageDisplay", vehicleViewModels); } public IActionResult Calendar() { var vehiclesStored = _dataAccess.GetVehicles(); if (!User.IsInRole(nameof(UserData.IsRootUser))) { vehiclesStored = _userLogic.FilterUserVehicles(vehiclesStored, GetUserID()); } var reminders = _vehicleLogic.GetReminders(vehiclesStored, true); return PartialView("_Calendar", reminders); } public IActionResult ViewCalendarReminder(int reminderId) { var reminder = _reminderRecordDataAccess.GetReminderRecordById(reminderId); var reminderUrgency = _reminderHelper.GetReminderRecordViewModels(new List { reminder }, 0, DateTime.Now).FirstOrDefault(); return PartialView("_ReminderRecordCalendarModal", reminderUrgency); } public async Task Settings() { var userConfig = _config.GetUserConfig(User); var languages = _fileHelper.GetLanguages(); var viewModel = new SettingsViewModel { UserConfig = userConfig, UILanguages = languages }; return PartialView("_Settings", viewModel); } public async Task Sponsors() { try { var httpClient = new HttpClient(); var sponsorsData = await httpClient.GetFromJsonAsync(StaticHelper.SponsorsPath) ?? new Sponsors(); return PartialView("_Sponsors", sponsorsData); } catch (Exception ex) { _logger.LogError($"Unable to retrieve sponsors: {ex.Message}"); return PartialView("_Sponsors", new Sponsors()); } } [HttpPost] public IActionResult WriteToSettings(UserConfig userConfig) { //retrieve existing userConfig. var existingConfig = _config.GetUserConfig(User); //copy over stuff that persists userConfig.UserColumnPreferences = existingConfig.UserColumnPreferences; userConfig.ReminderUrgencyConfig = existingConfig.ReminderUrgencyConfig; var result = _config.SaveUserConfig(User, userConfig); return Json(result); } [HttpPost] public IActionResult SaveReminderUrgencyThreshold(ReminderUrgencyConfig reminderUrgencyConfig) { //retrieve existing userConfig. var existingConfig = _config.GetUserConfig(User); existingConfig.ReminderUrgencyConfig = reminderUrgencyConfig; var result = _config.SaveUserConfig(User, existingConfig); return Json(result); } [Authorize(Roles = nameof(UserData.IsRootUser))] public IActionResult GetExtraFieldsModal(int importMode = 0) { var recordExtraFields = _extraFieldDataAccess.GetExtraFieldsById(importMode); if (recordExtraFields.Id != importMode) { recordExtraFields.Id = importMode; } return PartialView("_ExtraFields", recordExtraFields); } [Authorize(Roles = nameof(UserData.IsRootUser))] public IActionResult UpdateExtraFields(RecordExtraField record) { try { var result = _extraFieldDataAccess.SaveExtraFields(record); } catch (Exception ex) { _logger.LogError(ex.Message); } var recordExtraFields = _extraFieldDataAccess.GetExtraFieldsById(record.Id); return PartialView("_ExtraFields", recordExtraFields); } [HttpPost] public IActionResult GenerateTokenForUser() { try { //get current user email address. var emailAddress = User.FindFirstValue(ClaimTypes.Email); if (!string.IsNullOrWhiteSpace(emailAddress)) { var result = _loginLogic.GenerateTokenForEmailAddress(emailAddress, false); return Json(result); } return Json(false); } catch (Exception ex) { _logger.LogError(ex.Message); return Json(false); } } [HttpPost] public IActionResult UpdateUserAccount(LoginModel userAccount) { try { var userId = GetUserID(); if (userId > 0) { var result = _loginLogic.UpdateUserDetails(userId, userAccount); return Json(result); } return Json(new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage }); } catch (Exception ex) { _logger.LogError(ex.Message); return Json(new OperationResponse { Success = false, Message = StaticHelper.GenericErrorMessage }); } } [HttpGet] public IActionResult GetUserAccountInformationModal() { var emailAddress = User.FindFirstValue(ClaimTypes.Email); var userName = User.Identity.Name; return PartialView("_AccountModal", new UserData() { EmailAddress = emailAddress, UserName = userName }); } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpGet] public IActionResult GetRootAccountInformationModal() { var userName = User.Identity.Name; return PartialView("_RootAccountModal", new UserData() { UserName = userName }); } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpGet] public IActionResult GetTranslatorEditor(string userLanguage) { var translationData = _translationHelper.GetTranslations(userLanguage); return PartialView("_TranslationEditor", translationData); } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpPost] public IActionResult SaveTranslation(string userLanguage, Dictionary translationData) { var result = _translationHelper.SaveTranslation(userLanguage, translationData); return Json(result); } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpPost] public IActionResult ExportTranslation(Dictionary translationData) { var result = _translationHelper.ExportTranslation(translationData); return Json(result); } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpGet] public async Task GetAvailableTranslations() { try { var httpClient = new HttpClient(); var translations = await httpClient.GetFromJsonAsync(StaticHelper.TranslationDirectoryPath) ?? new Translations(); return PartialView("_Translations", translations); } catch (Exception ex) { _logger.LogError($"Unable to retrieve translations: {ex.Message}"); return PartialView("_Translations", new Translations()); } } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpGet] public async Task DownloadTranslation(string continent, string name) { try { var httpClient = new HttpClient(); var translationData = await httpClient.GetFromJsonAsync>(StaticHelper.GetTranslationDownloadPath(continent, name)) ?? new Dictionary(); if (translationData.Any()) { var result = _translationHelper.SaveTranslation(name, translationData); if (!result.Success) { return Json(false); } } else { _logger.LogError($"Unable to download translation: {name}"); return Json(false); } return Json(true); } catch (Exception ex) { _logger.LogError($"Unable to download translation: {ex.Message}"); return Json(false); } } [Authorize(Roles = nameof(UserData.IsRootUser))] [HttpGet] public async Task DownloadAllTranslations() { try { var httpClient = new HttpClient(); var translations = await httpClient.GetFromJsonAsync(StaticHelper.TranslationDirectoryPath) ?? new Translations(); int translationsDownloaded = 0; foreach (string translation in translations.Asia) { try { var translationData = await httpClient.GetFromJsonAsync>(StaticHelper.GetTranslationDownloadPath("Asia", translation)) ?? new Dictionary(); if (translationData.Any()) { var result = _translationHelper.SaveTranslation(translation, translationData); if (result.Success) { translationsDownloaded++; }; } } catch (Exception ex) { _logger.LogError($"Error Downloading Translation {translation}: {ex.Message} "); } } foreach (string translation in translations.Africa) { try { var translationData = await httpClient.GetFromJsonAsync>(StaticHelper.GetTranslationDownloadPath("Africa", translation)) ?? new Dictionary(); if (translationData.Any()) { var result = _translationHelper.SaveTranslation(translation, translationData); if (result.Success) { translationsDownloaded++; }; } } catch (Exception ex) { _logger.LogError($"Error Downloading Translation {translation}: {ex.Message} "); } } foreach (string translation in translations.Europe) { try { var translationData = await httpClient.GetFromJsonAsync>(StaticHelper.GetTranslationDownloadPath("Europe", translation)) ?? new Dictionary(); if (translationData.Any()) { var result = _translationHelper.SaveTranslation(translation, translationData); if (result.Success) { translationsDownloaded++; }; } } catch (Exception ex) { _logger.LogError($"Error Downloading Translation {translation}: {ex.Message} "); } } foreach (string translation in translations.NorthAmerica) { try { var translationData = await httpClient.GetFromJsonAsync>(StaticHelper.GetTranslationDownloadPath("NorthAmerica", translation)) ?? new Dictionary(); if (translationData.Any()) { var result = _translationHelper.SaveTranslation(translation, translationData); if (result.Success) { translationsDownloaded++; }; } } catch (Exception ex) { _logger.LogError($"Error Downloading Translation {translation}: {ex.Message} "); } } foreach (string translation in translations.SouthAmerica) { try { var translationData = await httpClient.GetFromJsonAsync>(StaticHelper.GetTranslationDownloadPath("SouthAmerica", translation)) ?? new Dictionary(); if (translationData.Any()) { var result = _translationHelper.SaveTranslation(translation, translationData); if (result.Success) { translationsDownloaded++; }; } } catch (Exception ex) { _logger.LogError($"Error Downloading Translation {translation}: {ex.Message} "); } } foreach (string translation in translations.Oceania) { try { var translationData = await httpClient.GetFromJsonAsync>(StaticHelper.GetTranslationDownloadPath("Oceania", translation)) ?? new Dictionary(); if (translationData.Any()) { var result = _translationHelper.SaveTranslation(translation, translationData); if (result.Success) { translationsDownloaded++; }; } } catch (Exception ex) { _logger.LogError($"Error Downloading Translation {translation}: {ex.Message} "); } } if (translationsDownloaded > 0) { return Json(new OperationResponse() { Success = true, Message = $"{translationsDownloaded} Translations Downloaded" }); } else { return Json(new OperationResponse() { Success = false, Message = "No Translations Downloaded" }); } } catch (Exception ex) { _logger.LogError($"Unable to retrieve translations: {ex.Message}"); return Json(new OperationResponse() { Success = false, Message = StaticHelper.GenericErrorMessage }); } } [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] public IActionResult Error() { return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); } } }