using System.Globalization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using TicketOffice.Data; using TicketOffice.Models; using TicketOffice.Services; using Route = TicketOffice.Models.Route; namespace TicketOffice.Pages.Management.Routes; public class CreateModel : PageModel { // Error massage displaying when route number validation failed. public string NumberValidationError = null!; // Error massage displaying when route capacity validation failed. public string CapacityValidationError = null!; // Array of error massages displaying when route name validation failed. public string[] NameValidationError; // Array of error massages displaying when cities // departure time validation failed. public string[] DepartureTimeValidationError; // Array of error massages displaying when cities // arrival time validation failed. public string[] ArrivalTimeValidationError; private readonly TicketOfficeContext context; private readonly UserValidationService validationService; public CreateModel(TicketOfficeContext context, UserValidationService validationService) { this.context = context; this.validationService = validationService; } // Object representing that will be created. [BindProperty] public Route Route { get; set; } // Object holding cities' arrival/departure dates. [BindProperty] public DateString[] TimeStrings { get; set; } // Amount of cities to be added to the route [BindProperty] public int? CitiesCount { get; set; } // Called when GET request is sent to the page. public IActionResult OnGet() { if (!validationService.IsManager(HttpContext)) { return RedirectToPage("/Index"); } return Page(); } // Called when POST request is sent to the page (when user tries to add new // route). Validates input, creates new route in the database and // redirects to "Management/Routes" page. public ActionResult OnPost() { if (CitiesCount != null) { Route = new Route(); Route.Cities = new List(); TimeStrings = new DateString[(int) CitiesCount]; for (int i = 0; i < CitiesCount; i++) { TimeStrings[i] = new DateString(); Route.Cities.Add(new RouteCity()); } NameValidationError = new string[(int) CitiesCount]; DepartureTimeValidationError = new string[(int) CitiesCount]; ArrivalTimeValidationError = new string[(int) CitiesCount]; return Page(); } NameValidationError = new string[Route.Cities.Count]; DepartureTimeValidationError = new string[Route.Cities.Count]; ArrivalTimeValidationError = new string[Route.Cities.Count]; InsertDatesIntoCities(); if (!ValidateInput()) { return Page(); } context.Route.Add(Route); context.SaveChanges(); return RedirectToPage("./Index"); } private void InsertDatesIntoCities() { for (int i = 0; i < Route.Cities.Count; i++) { try { Route.Cities[i].DepartureTime = ConvertStringToDate(TimeStrings[i].DepartureDate); } catch(Exception e) { if (Route.Cities.Count > 2) { InitializeArray(DepartureTimeValidationError, Route.Cities.Count, ""); } DepartureTimeValidationError[i] = "Формат: dd.MM.yyyy, hh:mm"; } try { Route.Cities[i].ArrivalTime = ConvertStringToDate(TimeStrings[i].ArrivalDate); } catch(Exception e) { if (Route.Cities.Count > 2) { InitializeArray(ArrivalTimeValidationError, Route.Cities.Count, ""); } ArrivalTimeValidationError[i] = "Формат: dd.MM.yyyy, hh:mm"; } } DateTime? ConvertStringToDate(string dateStr) { if (String.IsNullOrWhiteSpace(dateStr) || String.IsNullOrEmpty(dateStr)) { return null; } if (dateStr.Count(c => c == '.') != 2 && dateStr.Count(c => c == ':') != 2 && dateStr.Count(c => c == ',') != 1) { throw new ArgumentException("Invalid input format"); } string[] date = dateStr.Split(",")[0].Split("."); string[] time = dateStr.Split(",")[1].Split(":"); date.ToList().ForEach(s => s.Trim()); time.ToList().ForEach(s => s.Trim()); return new DateTime( Int32.Parse(date[2]), Int32.Parse(date[1]), Int32.Parse(date[0]), Int32.Parse(time[0]), Int32.Parse(time[1]), 0); } } private bool ValidateInput() { bool isValidNumber = ValidateNumber(Route.Number, out NumberValidationError); bool isValidCapacity = ValidateCapacity(Route.Capacity, out CapacityValidationError); for (int i = 0; i < Route.Cities.Count; i++) { if (Route.Cities.Count > 2) { InitializeArray(NameValidationError, Route.Cities.Count, ""); } ValidateName(Route.Cities[i].Name, out NameValidationError[i]); } for (int i = 0; i < Route.Cities.Count; i++) { if (Route.Cities.Count > 2) { InitializeArray(DepartureTimeValidationError, Route.Cities.Count, ""); } ValidateDate(Route.Cities[i].DepartureTime, out DepartureTimeValidationError[i]); } for (int i = 0; i < Route.Cities.Count; i++) { if (Route.Cities.Count > 2) { InitializeArray(ArrivalTimeValidationError, Route.Cities.Count, ""); } ValidateDate(Route.Cities[i].ArrivalTime, out ArrivalTimeValidationError[i]); } if (!isValidNumber || !isValidCapacity || NameValidationError.Any(e => e != "") || DepartureTimeValidationError.Any(e => e != "") || ArrivalTimeValidationError.Any(e => e != "")) { return false; } return true; bool ValidateNumber(int number, out string validationError) { validationError = ""; if (number < 1 || number > 9999) { validationError = "Має бути в проміжку від 1 до 9999"; return false; } return true; } bool ValidateCapacity(int capacity, out string validationError) { validationError = ""; if (capacity < 1 || capacity > 40) { validationError = "Має бути в проміжку від 5 до 45"; return false; } return true; } bool ValidateName(string name, out string validationError) { validationError = ""; if (String.IsNullOrWhiteSpace(name) || String.IsNullOrEmpty(name)) { validationError = "Поле має бути заповненим"; return false; } return true; } bool ValidateDate(DateTime? date, out string validationError) { validationError = ""; if (date == null) { return true; } if (date < DateTime.Today) { validationError = $"Має бути не раніше ніж {DateTime.Today.ToString(CultureInfo.GetCultureInfo("uk-UA")).Split(" ")[0]}"; return false; } return true; } } private void InitializeArray(T[] arr, int length, T initVal) { arr = new T[length]; for (int i = 0; i < length; i++) { arr[i] = initVal; } } }