├── .gitattributes ├── ClubMembershipApplication.sln ├── ClubMembershipApplication ├── ClubMembershipApplication.csproj ├── CommonOutputFormat.cs ├── CommonOutputText.cs ├── Data │ ├── ClubMembershipDbContext.cs │ ├── ILogin.cs │ ├── IRegister.cs │ ├── LoginUser.cs │ └── RegisterUser.cs ├── Factory.cs ├── FieldValidators │ ├── FieldConstants.cs │ ├── IFieldValidator.cs │ └── UserRegistrationValidator.cs ├── Models │ └── User.cs ├── Program.cs └── Views │ ├── IView.cs │ ├── MainView.cs │ ├── UserLoginView.cs │ ├── UserRegistrationView.cs │ └── WelcomeUserView.cs ├── FieldValidatorAPI ├── CommonFieldValidatorFunctions.cs ├── CommonRegularExpressionValidationPatterns.cs └── FieldValidatorAPI.csproj └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /ClubMembershipApplication.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.29326.143 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClubMembershipApplication", "ClubMembershipApplication\ClubMembershipApplication.csproj", "{E256C6B4-EE69-4594-B3AD-25D3BFC70ABC}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FieldValidatorAPI", "FieldValidatorAPI\FieldValidatorAPI.csproj", "{AD0BB2E6-D1CA-4AB9-AB26-48331D576F27}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {E256C6B4-EE69-4594-B3AD-25D3BFC70ABC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {E256C6B4-EE69-4594-B3AD-25D3BFC70ABC}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {E256C6B4-EE69-4594-B3AD-25D3BFC70ABC}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {E256C6B4-EE69-4594-B3AD-25D3BFC70ABC}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {AD0BB2E6-D1CA-4AB9-AB26-48331D576F27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {AD0BB2E6-D1CA-4AB9-AB26-48331D576F27}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {AD0BB2E6-D1CA-4AB9-AB26-48331D576F27}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {AD0BB2E6-D1CA-4AB9-AB26-48331D576F27}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {3A879525-C980-49D0-85F1-BC2219796AEC} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /ClubMembershipApplication/ClubMembershipApplication.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Exe 5 | netcoreapp3.0 6 | 7 | 8 | 9 | 10 | 11 | all 12 | runtime; build; native; contentfiles; analyzers; buildtransitive 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /ClubMembershipApplication/CommonOutputFormat.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ClubMembershipApplication 6 | { 7 | public enum FontTheme 8 | { 9 | Default, 10 | Danger, 11 | Success 12 | } 13 | public static class CommonOutputFormat 14 | { 15 | public static void ChangeFontColor(FontTheme fontTheme) 16 | { 17 | if (fontTheme == FontTheme.Danger) 18 | { 19 | Console.BackgroundColor = ConsoleColor.Red; 20 | Console.ForegroundColor = ConsoleColor.White; 21 | } 22 | else if (fontTheme == FontTheme.Success) 23 | { 24 | Console.BackgroundColor = ConsoleColor.Green; 25 | Console.ForegroundColor = ConsoleColor.White; 26 | } 27 | else 28 | { 29 | Console.ResetColor(); 30 | } 31 | } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ClubMembershipApplication/CommonOutputText.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ClubMembershipApplication 6 | { 7 | public static class CommonOutputText 8 | { 9 | private static string MainHeading 10 | { 11 | get { 12 | string heading = "Cycling Club"; 13 | return $"{heading}{Environment.NewLine}{new string('-',heading.Length)}"; 14 | } 15 | } 16 | 17 | private static string RegistrationHeading 18 | { 19 | get { 20 | string heading = "Register"; 21 | return $"{heading}{Environment.NewLine}{new string('-', heading.Length)}"; 22 | } 23 | } 24 | private static string LoginHeading 25 | { 26 | get 27 | { 28 | string heading = "Login"; 29 | return $"{heading}{Environment.NewLine}{new string('-', heading.Length)}"; 30 | } 31 | } 32 | 33 | public static void WriteMainHeading() 34 | { 35 | Console.Clear(); 36 | Console.WriteLine(MainHeading); 37 | Console.WriteLine(); 38 | Console.WriteLine(); 39 | } 40 | public static void WriteLoginHeading() 41 | { 42 | Console.WriteLine(LoginHeading); 43 | Console.WriteLine(); 44 | Console.WriteLine(); 45 | } 46 | public static void WriteRegistrationHeading() 47 | { 48 | Console.WriteLine(RegistrationHeading); 49 | Console.WriteLine(); 50 | Console.WriteLine(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Data/ClubMembershipDbContext.cs: -------------------------------------------------------------------------------- 1 | using ClubMembershipApplication.Models; 2 | using Microsoft.EntityFrameworkCore; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace ClubMembershipApplication.Data 8 | { 9 | public class ClubMembershipDbContext:DbContext 10 | { 11 | protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) 12 | { 13 | optionsBuilder.UseSqlite($"Data Source={AppDomain.CurrentDomain.BaseDirectory}ClubMembershipDb.db"); 14 | base.OnConfiguring(optionsBuilder); 15 | } 16 | 17 | public DbSet Users { get; set; } 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Data/ILogin.cs: -------------------------------------------------------------------------------- 1 | using ClubMembershipApplication.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace ClubMembershipApplication.Data 7 | { 8 | public interface ILogin 9 | { 10 | User Login(string emailAddress, string password); 11 | 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Data/IRegister.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ClubMembershipApplication.Data 6 | { 7 | public interface IRegister 8 | { 9 | bool Register(string[] fields); 10 | bool EmailExists(string emailAddress); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Data/LoginUser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ClubMembershipApplication.Models; 5 | using System.Linq; 6 | 7 | namespace ClubMembershipApplication.Data 8 | { 9 | public class LoginUser : ILogin 10 | { 11 | public User Login(string emailAddress, string password) 12 | { 13 | User user = null; 14 | 15 | using (var dbContext = new ClubMembershipDbContext()) 16 | { 17 | user = dbContext.Users.FirstOrDefault(u => u.EmailAddress.Trim().ToLower() == emailAddress.Trim().ToLower() && u.Password.Equals(password)); 18 | } 19 | return user; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Data/RegisterUser.cs: -------------------------------------------------------------------------------- 1 | using ClubMembershipApplication.Models; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | using ClubMembershipApplication.FieldValidators; 6 | using System.Linq; 7 | 8 | namespace ClubMembershipApplication.Data 9 | { 10 | public class RegisterUser : IRegister 11 | { 12 | public bool EmailExists(string emailAddress) 13 | { 14 | bool emailExists = false; 15 | 16 | using (var dbContext = new ClubMembershipDbContext()) 17 | { 18 | emailExists = dbContext.Users.Any(u => u.EmailAddress.ToLower().Trim() == emailAddress.Trim().ToLower()); 19 | } 20 | return emailExists; 21 | } 22 | 23 | public bool Register(string[] fields) 24 | { 25 | using (var dbContext = new ClubMembershipDbContext()) 26 | { 27 | User user = new User 28 | { 29 | EmailAddress = fields[(int)FieldConstants.UserRegistrationField.EmailAddress], 30 | FirstName = fields[(int)FieldConstants.UserRegistrationField.FirstName], 31 | LastName = fields[(int)FieldConstants.UserRegistrationField.LastName], 32 | Password = fields[(int)FieldConstants.UserRegistrationField.Password], 33 | DateOfBirth = DateTime.Parse(fields[(int)FieldConstants.UserRegistrationField.DateOfBirth]), 34 | PhoneNumber = fields[(int)FieldConstants.UserRegistrationField.PhoneNumber], 35 | AddressFirstLine = fields[(int)FieldConstants.UserRegistrationField.AddressFirstLine], 36 | AddressSecondLine = fields[(int)FieldConstants.UserRegistrationField.AddressSecondLine], 37 | AddressCity = fields[(int)FieldConstants.UserRegistrationField.AddressCity], 38 | PostCode = fields[(int)FieldConstants.UserRegistrationField.PostCode] 39 | 40 | }; 41 | 42 | dbContext.Users.Add(user); 43 | 44 | dbContext.SaveChanges(); 45 | } 46 | return true; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Factory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ClubMembershipApplication.Views; 5 | using ClubMembershipApplication.Data; 6 | using ClubMembershipApplication.FieldValidators; 7 | 8 | namespace ClubMembershipApplication 9 | { 10 | public static class Factory 11 | { 12 | public static IView GetMainViewObject() 13 | { 14 | ILogin login = new LoginUser(); 15 | IRegister register = new RegisterUser(); 16 | IFieldValidator userRegistrationValidator = new UserRegistrationValidator(register); 17 | userRegistrationValidator.InitialiseValidatorDelegates(); 18 | 19 | IView registerView = new UserRegistrationView(register, userRegistrationValidator); 20 | IView loginView = new UserLoginView(login); 21 | IView mainView = new MainView(registerView, loginView); 22 | 23 | return mainView; 24 | 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /ClubMembershipApplication/FieldValidators/FieldConstants.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ClubMembershipApplication.FieldValidators 6 | { 7 | public class FieldConstants 8 | { 9 | public enum UserRegistrationField 10 | { 11 | EmailAddress, 12 | FirstName, 13 | LastName, 14 | Password, 15 | PasswordCompare, 16 | DateOfBirth, 17 | PhoneNumber, 18 | AddressFirstLine, 19 | AddressSecondLine, 20 | AddressCity, 21 | PostCode 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /ClubMembershipApplication/FieldValidators/IFieldValidator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace ClubMembershipApplication.FieldValidators 6 | { 7 | public delegate bool FieldValidatorDel(int fieldIndex, string fieldValue, string[] fieldArray, out string fieldInvalidMessage); 8 | public interface IFieldValidator 9 | { 10 | void InitialiseValidatorDelegates(); 11 | string[] FieldArray { get; } 12 | FieldValidatorDel ValidatorDel { get; } 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ClubMembershipApplication/FieldValidators/UserRegistrationValidator.cs: -------------------------------------------------------------------------------- 1 | using ClubMembershipApplication.Data; 2 | using FieldValidatorAPI; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace ClubMembershipApplication.FieldValidators 8 | { 9 | public class UserRegistrationValidator:IFieldValidator 10 | { 11 | const int FirstName_Min_Length = 2; 12 | const int FirstName_Max_Length = 100; 13 | const int LastName_Min_Length = 2; 14 | const int LastName_Max_Length = 100; 15 | 16 | delegate bool EmailExistsDel(string emailAddress); 17 | 18 | FieldValidatorDel _fieldValidatorDel = null; 19 | 20 | RequiredValidDel _requiredValidDel = null; 21 | StringLengthValidDel _stringLenthValidDel = null; 22 | DateValidDel _dateValidDel = null; 23 | PatternMatchValidDel _patternMatchValidDel = null; 24 | CompareFieldsValidDel _compareFieldsValidDel = null; 25 | 26 | EmailExistsDel _emailExistsDel = null; 27 | 28 | string[] _fieldArray = null; 29 | IRegister _register = null; 30 | 31 | public string[] FieldArray 32 | { 33 | get 34 | { 35 | if (_fieldArray == null) 36 | _fieldArray = new string[Enum.GetValues(typeof(FieldConstants.UserRegistrationField)).Length]; 37 | return _fieldArray; 38 | } 39 | } 40 | 41 | public FieldValidatorDel ValidatorDel => _fieldValidatorDel; 42 | 43 | public UserRegistrationValidator(IRegister register) 44 | { 45 | _register = register; 46 | } 47 | 48 | public void InitialiseValidatorDelegates() 49 | { 50 | _fieldValidatorDel = new FieldValidatorDel(ValidField); 51 | _emailExistsDel = new EmailExistsDel(_register.EmailExists); 52 | 53 | _requiredValidDel = CommonFieldValidatorFunctions.RequiredFieldValidDel; 54 | _stringLenthValidDel = CommonFieldValidatorFunctions.StringLengthFieldValidDel; 55 | _dateValidDel = CommonFieldValidatorFunctions.DateFieldValidDel; 56 | _patternMatchValidDel = CommonFieldValidatorFunctions.PatternMatchValidDel; 57 | _compareFieldsValidDel = CommonFieldValidatorFunctions.FieldsCompareValidDel; 58 | } 59 | 60 | private bool ValidField(int fieldIndex, string fieldValue, string[] fieldArray, out string fieldInvalidMessage) 61 | { 62 | 63 | fieldInvalidMessage = ""; 64 | 65 | FieldConstants.UserRegistrationField userRegistrationField = (FieldConstants.UserRegistrationField)fieldIndex; 66 | 67 | switch (userRegistrationField) 68 | { 69 | case FieldConstants.UserRegistrationField.EmailAddress: 70 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 71 | fieldInvalidMessage = (fieldInvalidMessage == "" && !_patternMatchValidDel(fieldValue,CommonRegularExpressionValidationPatterns.Email_Address_RegEx_Pattern)) ? $"You must enter a valid email address{Environment.NewLine}" : fieldInvalidMessage; 72 | fieldInvalidMessage = (fieldInvalidMessage == "" && _emailExistsDel(fieldValue)) ? $"This email address already exists. Please try again{Environment.NewLine}" : fieldInvalidMessage; 73 | 74 | break; 75 | case FieldConstants.UserRegistrationField.FirstName: 76 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 77 | fieldInvalidMessage = (fieldInvalidMessage == "" && !_stringLenthValidDel(fieldValue, FirstName_Min_Length,FirstName_Max_Length)) ? $"The length for field: {Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)} must be between {FirstName_Min_Length} and {FirstName_Max_Length}{Environment.NewLine}" : fieldInvalidMessage; 78 | break; 79 | case FieldConstants.UserRegistrationField.LastName: 80 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 81 | fieldInvalidMessage = (fieldInvalidMessage == "" && !_stringLenthValidDel(fieldValue, LastName_Min_Length, LastName_Max_Length)) ? $"The length for field: {Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)} must be between {LastName_Min_Length} and {LastName_Max_Length}{Environment.NewLine}" : fieldInvalidMessage; 82 | break; 83 | case FieldConstants.UserRegistrationField.Password: 84 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 85 | fieldInvalidMessage = (fieldInvalidMessage == "" && !_patternMatchValidDel(fieldValue, CommonRegularExpressionValidationPatterns.Strong_Password_RegEx_Pattern)) ? $"Your password must contain at least 1 small-case letter, 1 capital letter, 1 special character and the length should be between 6 - 10 characters{Environment.NewLine}" : fieldInvalidMessage; 86 | break; 87 | case FieldConstants.UserRegistrationField.PasswordCompare: 88 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 89 | fieldInvalidMessage = (fieldInvalidMessage == "" && !_compareFieldsValidDel(fieldValue,fieldArray[(int)FieldConstants.UserRegistrationField.Password])) ? $"Your entry did not match your password{Environment.NewLine}" : fieldInvalidMessage; 90 | break; 91 | case FieldConstants.UserRegistrationField.DateOfBirth: 92 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 93 | fieldInvalidMessage = (fieldInvalidMessage == "" && !_dateValidDel(fieldValue, out DateTime validDateTime)) ? $"You did not enter a valid date" : fieldInvalidMessage; 94 | break; 95 | case FieldConstants.UserRegistrationField.PhoneNumber: 96 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 97 | fieldInvalidMessage = (fieldInvalidMessage == "" && !_patternMatchValidDel(fieldValue,CommonRegularExpressionValidationPatterns.Uk_PhoneNumber_RegEx_Pattern)) ? $"You did not enter a valid UK phone number{Environment.NewLine}" : fieldInvalidMessage; 98 | break; 99 | case FieldConstants.UserRegistrationField.AddressFirstLine: 100 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 101 | break; 102 | case FieldConstants.UserRegistrationField.AddressSecondLine: 103 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 104 | break; 105 | case FieldConstants.UserRegistrationField.AddressCity: 106 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 107 | break; 108 | case FieldConstants.UserRegistrationField.PostCode: 109 | fieldInvalidMessage = (!_requiredValidDel(fieldValue)) ? $"You must enter a value for field:{Enum.GetName(typeof(FieldConstants.UserRegistrationField), userRegistrationField)}{Environment.NewLine}" : ""; 110 | fieldInvalidMessage = (fieldInvalidMessage == "" && !_patternMatchValidDel(fieldValue, CommonRegularExpressionValidationPatterns.Uk_Post_Code_RegEx_Pattern)) ? $"You did not enter a valid UK post code{Environment.NewLine}" : fieldInvalidMessage; 111 | break; 112 | default: 113 | throw new ArgumentException("This field does not exists"); 114 | 115 | } 116 | 117 | return (fieldInvalidMessage == ""); 118 | 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Models/User.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel.DataAnnotations.Schema; 4 | using System.Text; 5 | 6 | namespace ClubMembershipApplication.Models 7 | { 8 | public class User 9 | { 10 | [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 11 | public int Id { get; set; } 12 | 13 | public string EmailAddress { get; set; } 14 | 15 | public string FirstName { get; set; } 16 | 17 | public string LastName { get; set; } 18 | 19 | public string Password { get; set; } 20 | 21 | public DateTime DateOfBirth { get; set; } 22 | 23 | public string PhoneNumber { get; set; } 24 | 25 | public string AddressFirstLine { get; set; } 26 | 27 | public string AddressSecondLine { get; set; } 28 | 29 | public string AddressCity { get; set; } 30 | 31 | public string PostCode { get; set; } 32 | 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using ClubMembershipApplication.Views; 3 | namespace ClubMembershipApplication 4 | { 5 | class Program 6 | { 7 | static void Main(string[] args) 8 | { 9 | IView mainView = Factory.GetMainViewObject(); 10 | mainView.RunView(); 11 | 12 | Console.ReadKey(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Views/IView.cs: -------------------------------------------------------------------------------- 1 | using ClubMembershipApplication.FieldValidators; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace ClubMembershipApplication.Views 7 | { 8 | public interface IView 9 | { 10 | void RunView(); 11 | IFieldValidator FieldValidator { get; } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Views/MainView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ClubMembershipApplication.FieldValidators; 5 | 6 | 7 | namespace ClubMembershipApplication.Views 8 | { 9 | class MainView : IView 10 | { 11 | public IFieldValidator FieldValidator => null; 12 | 13 | IView _registerView = null; 14 | IView _loginView = null; 15 | public MainView(IView registerView, IView loginView) 16 | { 17 | _registerView = registerView; 18 | _loginView = loginView; 19 | } 20 | public void RunView() 21 | { 22 | CommonOutputText.WriteMainHeading(); 23 | 24 | Console.WriteLine("Please press 'l' to login or if you are not yet registered please press 'r'"); 25 | 26 | ConsoleKey key = Console.ReadKey().Key; 27 | 28 | if (key == ConsoleKey.R) 29 | { 30 | RunUserRegistrationView(); 31 | RunLoginView(); 32 | } 33 | else if (key == ConsoleKey.L) 34 | { 35 | RunLoginView(); 36 | } 37 | else 38 | { 39 | Console.Clear(); 40 | Console.WriteLine("Goodbye"); 41 | Console.ReadKey(); 42 | 43 | } 44 | 45 | } 46 | 47 | private void RunUserRegistrationView() 48 | { 49 | _registerView.RunView(); 50 | } 51 | 52 | private void RunLoginView() 53 | { 54 | _loginView.RunView(); 55 | } 56 | 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Views/UserLoginView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using ClubMembershipApplication.Data; 5 | using ClubMembershipApplication.FieldValidators; 6 | using ClubMembershipApplication.Models; 7 | 8 | namespace ClubMembershipApplication.Views 9 | { 10 | public class UserLoginView : IView 11 | { 12 | ILogin _loginUser = null; 13 | public IFieldValidator FieldValidator => null; 14 | 15 | public UserLoginView(ILogin login) 16 | { 17 | _loginUser = login; 18 | } 19 | public void RunView() 20 | { 21 | CommonOutputText.WriteMainHeading(); 22 | 23 | CommonOutputText.WriteLoginHeading(); 24 | 25 | Console.WriteLine("Please enter your email address"); 26 | 27 | string emailAddress = Console.ReadLine(); 28 | 29 | Console.WriteLine("Please enter your password"); 30 | 31 | string password = Console.ReadLine(); 32 | 33 | User user = _loginUser.Login(emailAddress,password); 34 | 35 | if (user != null) 36 | { 37 | WelcomeUserView welcomeUserView = new WelcomeUserView(user); 38 | welcomeUserView.RunView(); 39 | } 40 | else 41 | { 42 | Console.Clear(); 43 | CommonOutputFormat.ChangeFontColor(FontTheme.Danger); 44 | Console.WriteLine("The credentials that you entered do not match any of our records"); 45 | CommonOutputFormat.ChangeFontColor(FontTheme.Default); 46 | Console.ReadKey(); 47 | } 48 | 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Views/UserRegistrationView.cs: -------------------------------------------------------------------------------- 1 | using ClubMembershipApplication.Data; 2 | using ClubMembershipApplication.FieldValidators; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace ClubMembershipApplication.Views 8 | { 9 | public class UserRegistrationView:IView 10 | { 11 | IFieldValidator _fieldValidator = null; 12 | 13 | IRegister _register = null; 14 | 15 | public IFieldValidator FieldValidator { get => _fieldValidator;} 16 | 17 | public UserRegistrationView(IRegister register, IFieldValidator fieldValidator) 18 | { 19 | _fieldValidator = fieldValidator; 20 | _register = register; 21 | } 22 | 23 | public void RunView() 24 | { 25 | CommonOutputText.WriteMainHeading(); 26 | CommonOutputText.WriteRegistrationHeading(); 27 | 28 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.EmailAddress] = GetInputFromUser(FieldConstants.UserRegistrationField.EmailAddress,"Please enter your email address: "); 29 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.FirstName] = GetInputFromUser(FieldConstants.UserRegistrationField.FirstName, "Please enter your first name: "); 30 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.LastName] = GetInputFromUser(FieldConstants.UserRegistrationField.LastName, "Please enter your last name: "); 31 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.Password] = GetInputFromUser(FieldConstants.UserRegistrationField.Password, $"Please enter your password.{Environment.NewLine}(Your password must contain at least 1 small-case letter,{Environment.NewLine}1 Capital letter, 1 digit, 1 special character{Environment.NewLine} and the length should be between 6-10 characters): "); 32 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.PasswordCompare] = GetInputFromUser(FieldConstants.UserRegistrationField.PasswordCompare, "Please re-enter your password: "); 33 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.DateOfBirth] = GetInputFromUser(FieldConstants.UserRegistrationField.DateOfBirth, "Please enter your date of birth: "); 34 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.PhoneNumber] = GetInputFromUser(FieldConstants.UserRegistrationField.PhoneNumber, "Please enter your phone number: "); 35 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.AddressFirstLine] = GetInputFromUser(FieldConstants.UserRegistrationField.AddressFirstLine, "Please enter the first line of your address: "); 36 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.AddressSecondLine] = GetInputFromUser(FieldConstants.UserRegistrationField.AddressSecondLine, "Please enter the second line of your address: "); 37 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.AddressCity] = GetInputFromUser(FieldConstants.UserRegistrationField.AddressCity, "Please enter the city where you live: "); 38 | _fieldValidator.FieldArray[(int)FieldConstants.UserRegistrationField.PostCode] = GetInputFromUser(FieldConstants.UserRegistrationField.PostCode, "Please enter your post code: "); 39 | 40 | RegisterUser(); 41 | } 42 | 43 | private void RegisterUser() 44 | { 45 | _register.Register(_fieldValidator.FieldArray); 46 | 47 | CommonOutputFormat.ChangeFontColor(FontTheme.Success); 48 | Console.WriteLine("You have successfully registered. Please press any key to login"); 49 | CommonOutputFormat.ChangeFontColor(FontTheme.Default); 50 | Console.ReadKey(); 51 | } 52 | 53 | private string GetInputFromUser(FieldConstants.UserRegistrationField field, string promptText) 54 | { 55 | string fieldVal = ""; 56 | 57 | do 58 | { 59 | Console.Write(promptText); 60 | fieldVal = Console.ReadLine(); 61 | } 62 | while (!FieldValid(field, fieldVal)); 63 | 64 | return fieldVal; 65 | } 66 | 67 | private bool FieldValid(FieldConstants.UserRegistrationField field, string fieldValue) 68 | { 69 | if (!_fieldValidator.ValidatorDel((int)field, fieldValue, _fieldValidator.FieldArray, out string invalidMessage)) 70 | { 71 | CommonOutputFormat.ChangeFontColor(FontTheme.Danger); 72 | 73 | Console.WriteLine(invalidMessage); 74 | 75 | CommonOutputFormat.ChangeFontColor(FontTheme.Default); 76 | 77 | return false; 78 | } 79 | return true; 80 | } 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /ClubMembershipApplication/Views/WelcomeUserView.cs: -------------------------------------------------------------------------------- 1 | using ClubMembershipApplication.FieldValidators; 2 | using ClubMembershipApplication.Models; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Text; 6 | 7 | namespace ClubMembershipApplication.Views 8 | { 9 | 10 | 11 | public class WelcomeUserView:IView 12 | { 13 | User _user = null; 14 | 15 | public WelcomeUserView(User user) 16 | { 17 | _user = user; 18 | } 19 | 20 | public IFieldValidator FieldValidator => null; 21 | 22 | public void RunView() 23 | { 24 | Console.Clear(); 25 | CommonOutputText.WriteMainHeading(); 26 | 27 | CommonOutputFormat.ChangeFontColor(FontTheme.Success); 28 | Console.WriteLine($"Hi {_user.FirstName}!!{Environment.NewLine}Welcome to the Cycling Club!!"); 29 | CommonOutputFormat.ChangeFontColor(FontTheme.Default); 30 | Console.ReadKey(); 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /FieldValidatorAPI/CommonFieldValidatorFunctions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Text.RegularExpressions; 5 | 6 | namespace FieldValidatorAPI 7 | { 8 | public delegate bool RequiredValidDel(string fieldVal); 9 | public delegate bool StringLengthValidDel(string fieldVal, int min, int max); 10 | public delegate bool DateValidDel(string fieldVal, out DateTime validDateTime); 11 | public delegate bool PatternMatchValidDel(string fieldVal, string pattern); 12 | public delegate bool CompareFieldsValidDel(string fieldVal, string fieldValCompare); 13 | public class CommonFieldValidatorFunctions 14 | { 15 | private static RequiredValidDel _requiredValidDel = null; 16 | private static StringLengthValidDel _stringLengthValidDel = null; 17 | private static DateValidDel _dateValidDel = null; 18 | private static PatternMatchValidDel _patternMatchValidDel = null; 19 | private static CompareFieldsValidDel _compareFieldsValidDel = null; 20 | 21 | public static RequiredValidDel RequiredFieldValidDel 22 | { 23 | get 24 | { 25 | if (_requiredValidDel == null) 26 | _requiredValidDel = new RequiredValidDel(RequiredFieldValid); 27 | 28 | return _requiredValidDel; 29 | } 30 | } 31 | 32 | public static StringLengthValidDel StringLengthFieldValidDel 33 | { 34 | get 35 | { 36 | if (_stringLengthValidDel == null) 37 | _stringLengthValidDel = new StringLengthValidDel(StringFieldLengthValid); 38 | 39 | return _stringLengthValidDel; 40 | } 41 | } 42 | public static DateValidDel DateFieldValidDel 43 | { 44 | get 45 | { 46 | if (_dateValidDel == null) 47 | _dateValidDel = new DateValidDel(DateFieldValid); 48 | 49 | return _dateValidDel; 50 | } 51 | } 52 | public static PatternMatchValidDel PatternMatchValidDel 53 | { 54 | get 55 | { 56 | if (_patternMatchValidDel == null) 57 | _patternMatchValidDel = new PatternMatchValidDel(FieldPatternValid); 58 | 59 | return _patternMatchValidDel; 60 | } 61 | } 62 | 63 | public static CompareFieldsValidDel FieldsCompareValidDel 64 | { 65 | get 66 | { 67 | if (_compareFieldsValidDel == null) 68 | _compareFieldsValidDel = new CompareFieldsValidDel(FieldComparisonValid); 69 | 70 | return _compareFieldsValidDel; 71 | } 72 | } 73 | 74 | 75 | private static bool RequiredFieldValid(string fieldVal) 76 | { 77 | if (!string.IsNullOrEmpty(fieldVal)) 78 | return true; 79 | 80 | return false; 81 | 82 | } 83 | 84 | private static bool StringFieldLengthValid(string fieldVal, int min, int max) 85 | { 86 | if (fieldVal.Length >= min && fieldVal.Length <= max) 87 | return true; 88 | 89 | return false; 90 | 91 | } 92 | 93 | private static bool DateFieldValid(string dateTime, out DateTime validDateTime) 94 | { 95 | if (DateTime.TryParse(dateTime, out validDateTime)) 96 | return true; 97 | 98 | return false; 99 | 100 | } 101 | 102 | private static bool FieldPatternValid(string fieldVal, string regularExpressionPattern) 103 | { 104 | Regex regex = new Regex(regularExpressionPattern); 105 | 106 | if (regex.IsMatch(fieldVal)) 107 | return true; 108 | 109 | return false; 110 | 111 | } 112 | 113 | private static bool FieldComparisonValid(string field1, string field2) 114 | { 115 | if (field1.Equals(field2)) 116 | return true; 117 | 118 | return false; 119 | } 120 | 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /FieldValidatorAPI/CommonRegularExpressionValidationPatterns.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace FieldValidatorAPI 6 | { 7 | public static class CommonRegularExpressionValidationPatterns 8 | { 9 | 10 | public const string Email_Address_RegEx_Pattern = @"^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$"; 11 | 12 | public const string Uk_PhoneNumber_RegEx_Pattern = @"^\(?(?:(?:0(?:0|11)\)?[\s-]?\(?|\+)44\)?[\s-]?\(?(?:0\)?[\s-]?\(?)?|0)(?:\d{2}\)?[\s-]?\d{4}[\s-]?\d{4}|\d{3}\)?[\s-]?\d{3}[\s-]?\d{3,4}|\d{4}\)?[\s-]?(?:\d{5}|\d{3}[\s-]?\d{3})|\d{5}\)?[\s-]?\d{4,5}|8(?:00[\s-]?11[\s-]?11|45[\s-]?46[\s-]?4\d))(?:(?:[\s-]?(?:x|ext\.?\s?|\#)\d+)?)$"; 13 | 14 | public const string Uk_Post_Code_RegEx_Pattern = @"([Gg][Ii][Rr] 0[Aa]{2})|((([A-Za-z][0-9]{1,2})|(([A-Za-z][A-Ha-hJ-Yj-y][0-9]{1,2})|(([A-Za-z][0-9][A-Za-z])|([A-Za-z][A-Ha-hJ-Yj-y][0-9][A-Za-z]?))))\s?[0-9][A-Za-z]{2})"; 15 | 16 | public const string Strong_Password_RegEx_Pattern = @"(?=^.{6,10}$)(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[!@#$%^&*()_+}{":;'?/>.<,])(?!.*\s).*$"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /FieldValidatorAPI/FieldValidatorAPI.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ClubMembershipApplication 2 | This code example is part of a tutorial on CSharp Delegates 3 | Please find the relevant tutorial at this location, https://www.youtube.com/watch?v=jABhPwEfA-I&lc=UgwmqSpc8z0An7NSWVl4AaABAg 4 | If you download this project and run it you'll get an exception (this is because you'll need to run relevant EF Core migration commands to build a SQLite database) 5 | Once you have run the relvant migration commands, the code will run as expected 6 | Please go through the video tutorial first before running the code 7 | I explain how to run the relevant EF Core migration commands at around the 13:54 mark. 8 | --------------------------------------------------------------------------------