Untitled

 avatar
unknown
plain_text
23 days ago
30 kB
8
Indexable
using System;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Text;
using System.Transactions;

namespace Udemy
{
    internal class BankApp
    {
        static readonly List<string> AvailableBanks = new List<string>()
        {
            "National Bank of Kuwait (NBK)",
            "Boubyan Bank",
            "Kuwait Financial House (KFH)",
            "Al-Ahlei Bank",
            "Hamad National Bank"
        };

        static User client = new User();
        public static async Task RunAsync()
        {

            User user = new User();            

            do
            {
                user = await MainPage();
                if(user == null)
                {
                    Message.WriteLine("Incorrect Login Credentials!", ConsoleColor.Red);
                    await Task.Delay(1000);
                    Message.ClearConsole();
                }

            } while (user == null);

            for (int i = 0; i < 12; i++)
            {
                if (i % 4 == 0)
                {
                    Message.ClearConsole();
                    Message.Write("Logging In", Message.Blue);
                    await Task.Delay(300);
                }

                Message.Write(".", Message.Blue);
                await Task.Delay(300);
            }

            client = user;
            while (true)
            {                
                int userInput = await ClientOptions(user);

                switch(userInput)
                {
                    case 1: await Withdraw(); break;
                    case 2: await Deposit(); break;
                    case 3: await PrintLogs(client); break;
                    case 4: break;
                }

                //break;
            }
            // Print Client Information

            // Display Client Options : Withdraw - Deposit - Logs - Delete Account
            


        }

        static async Task PrintLogs(User user)
        {
            Console.Clear();
            await user.GetLogs();

            foreach(var log in user.TransactionLogs)
            {
                Console.Write($"{log.ID} : {log.TransactionDate.ToString("MM/dd/yyyy")}  -  ");
                if(log.TransactionType == "Withdraw")
                {
                    Message.Write($"[{log.TransactionType}]", Message.Red);
                }
                else
                {
                    Message.Write($"[{log.TransactionType}] ", Message.Success);
                }
                Console.Write($" || Amount : {log.Amount.ToString("N3")} KWD - New Balance : {log.Balance.ToString("N3")} KWD\n");
                
            }

            Console.ReadLine();
        }
        static async Task Withdraw()
        {
            bool withdraw = false;
            do
            {
                Console.Clear();
                await PrintClientBaseInformation(client);

                Console.ForegroundColor = ConsoleColor.DarkBlue;
                Console.Write("\nWithdraw Amount : ");
                Console.ForegroundColor = ConsoleColor.Magenta;                
                string userInput = Console.ReadLine()!;
                Console.WriteLine();
                if(!decimal.TryParse(userInput, out decimal result))
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Only numerical values allowed!");                    
                }
                else
                {
                    withdraw = decimal.TryParse(userInput, out decimal amount) && await client.Withdraw(amount);

                }

                await Task.Delay(2500);
                Console.ForegroundColor = ConsoleColor.White;

            } while (!withdraw);
        }
        static async Task Deposit()
        {
            bool deposit = false;
            do
            {
                Console.Clear();
                await PrintClientBaseInformation(client);

                Console.ForegroundColor = ConsoleColor.DarkBlue;
                Console.Write("\nDeposit Amount : ");
                Console.ForegroundColor = ConsoleColor.Magenta;
                string userInput = Console.ReadLine()!;
                Console.WriteLine();
                if (!decimal.TryParse(userInput, out decimal result))
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Only numerical values allowed!");
                }
                else
                {
                    deposit = decimal.TryParse(userInput, out decimal amount) && await client.Deposit(amount);

                }

                await Task.Delay(2500);
                Console.ForegroundColor = ConsoleColor.White;

            } while (!deposit);
        }
        static async Task<int> ClientOptions(User user)
        {
            string userInput = "s";
            int index = 0;

            do
            {
                Message.ClearConsole();
                await PrintClientBaseInformation(user);

                index = 1;
                Message.WriteLine("\nWhat do you want to do :", ConsoleColor.Yellow);
                Message.WriteLine($"\n{index++}- Withdraw", ConsoleColor.DarkGreen);
                Message.WriteLine($"{index++}- Deposit", ConsoleColor.DarkGreen);
                Message.WriteLine($"{index++}- View Transaction Logs", ConsoleColor.DarkGreen);
                Message.WriteLine($"{index}- Delete Account", ConsoleColor.DarkRed);
                Message.Write("\nUser Input : ", ConsoleColor.Magenta);
                userInput = Console.ReadLine()!;

                if(!int.TryParse(userInput, out int result2) || result2 <= 0 || result2 > index)
                {
                    Message.Write("Incorrect Syntax", Message.Red);
                    await Task.Delay(1000);
                }

            } while (!int.TryParse(userInput, out int result) || result <= 0 || result > index);  
            return int.Parse(userInput);
        }
        static async Task PrintClientBaseInformation(User user)
        {
            
            Console.Write("ID : ");
            Message.WriteLine($"{user.ID.ToString("D5")}", Message.Red);

            Console.Write("Full Name : ");
            Message.WriteLine($"{user.FirstName} {user.LastName}", ConsoleColor.Yellow);            

            Console.Write("Bank : ");
            Message.WriteLine($"{user.BankName}", Message.Blue);            

            Console.Write("Balance : ");
            Message.WriteLine($"{user.Balance.ToString("N3")} KWD", ConsoleColor.DarkBlue);

        }
        async static Task<User> MainPage()
        {
            User user = new User();
            user.ID = 0;
            string path = Path.Combine(FileSystem.BasePath, "data.txt");

            if (File.Exists(path))
            {
                int userInput = await WelcomePage();

                switch (userInput)
                {
                    case 1: user = await Login(); break;
                    case 2: user = await Register(); break;
                }
            }
            else
            {
                await FileSystem.CreateMainFile();

                Message.WriteLine("Text databse not found!, Creating new one...", Message.Blue);
                await Task.Delay(2000);
                Message.ClearConsole();
                Message.WriteLine("Opening Register Page!", ConsoleColor.DarkCyan);
                await Task.Delay(1000);
                Message.ClearConsole();

                user = await Register();

            }

            return user;
        }
        async static Task<int> WelcomePage()
        {
            Message.ClearConsole();
            Console.Write("Welcome to ");
            Console.ForegroundColor = ConsoleColor.Green;
            Console.Write("BankApp");
            Console.ForegroundColor = ConsoleColor.White;
            Console.Write("\n\n1-Login\n2-Register\n");

            return await Message.UserInputsNumbersOnly(2, WelcomePage);
        }

        async static Task<User> Login()
        {
            Message.ClearConsole();
            Console.Write("Username: ");
            string username = Console.ReadLine()!;
            
            while(username.Contains(","))
            {
                Message.WriteLine("Incorrect Syntax!, Username cannot contain \",\"", Message.Red);
                await Task.Delay(1250);
                Message.ClearConsole();
                Console.Write("Username: ");
                username = Console.ReadLine()!;

            }

            string usernameMessage = $"Username: {username}";

            Console.Write("Password: ");
            string password = Console.ReadLine()!;

            while (password.Contains(","))
            {
                Message.WriteLine("Incorrect Syntax!, Password cannot contain \",\"", Message.Red);
                await Task.Delay(1250);
                Message.ClearConsole();
                Console.WriteLine(usernameMessage);
                Console.Write("Password: ");
                password = Console.ReadLine()!;

            }


            return await FileSystem.GetUser(username, password);
        }

        async static Task<User> Register()
        {
            string bankName = string.Empty;
            while(true)
            {
                Message.ClearConsole();
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("All Available Banks : \n");
                Console.ForegroundColor = ConsoleColor.White;
                int index = 1;

                foreach(var bank in AvailableBanks)
                {
                    Console.ForegroundColor = ConsoleColor.Blue;
                    Console.WriteLine($"{index++}-{bank}");
                }

                Console.ForegroundColor = ConsoleColor.White;
                Console.Write("\nChoose your Bank : ");
                string userInput = Console.ReadLine()!;

                if(int.TryParse(userInput, out int value) && value > 0 && value <= index)
                {
                    bankName = AvailableBanks[value-1];
                    break;
                }

                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Incorrect Syntax!");
                await Task.Delay(1000);
            }

            Message.ClearConsole();
            User user = await GetUserInformation(); // Gets First and Last name, Civil ID and DOB

            user.BankName = bankName;
            user.Balance = 100000;
            user.CreatedAt = DateTime.Today.Date;


            string userName = string.Empty;

            do
            {
                if (userName.Contains(","))
                {
                    Message.Write("Incorrect Syntax \",\"", Message.Red);
                    await Task.Delay(1000);
                }
                Message.ClearConsole();
                Console.Write("Username : ");
                userName = Console.ReadLine()!;
                
            } while (userName.Contains(","));

            string usernameMessage = $"Username : {userName}";

            string password = string.Empty;

            do
            {
                if(password.Contains(","))
                {
                    Message.Write("Incorrect Syntax \",\"", Message.Red);
                    await Task.Delay(1000);
                }
                Message.ClearConsole();
                Console.WriteLine(usernameMessage);
                Console.Write("Password : ");
                password = Console.ReadLine()!;

            } while (password.Contains(","));

            user.Username = userName;
            user.Password = password;


            int id = await FileSystem.GetNewID();

            user.ID = id;

            await FileSystem.WriteNewUser(user);

            Message.WriteLine("Saved New User to Text databse!", Message.Success);
            await Task.Delay(2000);
            Message.ClearConsole();
            return user;
        }

        async static Task<User> GetUserInformation()
        {
            /* First Name */
            List<string> previousMessages = new List<string>();
            Console.Write("First Name : ");
            string firstName = Console.ReadLine()!;

            previousMessages.Add($"First Name : ");
            while (firstName.Contains(","))
            {
                Message.WriteLine("Incorrect Syntax \",\"", Message.Red);
                await Task.Delay(1000);
                Message.ClearConsole();
                foreach (string message in previousMessages)
                {
                    Console.Write(message);
                }

                firstName = Console.ReadLine()!;
            }

            previousMessages.RemoveAt(previousMessages.Count - 1);
            previousMessages.Add($"First Name : {firstName}\n");

            /* Last Name */
            Console.Write("Last Name : ");
            string lastName = Console.ReadLine()!;

            previousMessages.Add($"Last Name : ");
            while (lastName.Contains(","))
            {
                Message.WriteLine("Incorrect Syntax \",\"", Message.Red);
                await Task.Delay(1000);
                Message.ClearConsole();
                foreach (string message in previousMessages)
                {
                    Console.Write(message);
                }

                lastName = Console.ReadLine()!;
            }

            previousMessages.RemoveAt(previousMessages.Count - 1);
            previousMessages.Add($"Last Name : {lastName}\n");

            /* Civil-ID */
            Console.Write("Civil-ID : ");
            string civilID = Console.ReadLine()!;

            previousMessages.Add($"Civil-ID : ");
            while (civilID.Contains(",") || !long.TryParse(civilID, out long value) || civilID.Length != 12)
            {
                Message.WriteLine("Incorrect Syntax : Civil ID is a number only, must be exactly 12 digit!", Message.Red);
                await Task.Delay(3000);
                Message.ClearConsole();
                foreach (string message in previousMessages)
                {
                    Console.Write(message);
                }

                civilID = Console.ReadLine()!;
            }

            previousMessages.RemoveAt(previousMessages.Count - 1);
            previousMessages.Add($"Civil-ID : {civilID}\n");

            /* DOB */
            Console.Write("Date of Birth (M-D-Y) : ");
            string dob = Console.ReadLine()!;

            previousMessages.Add($"Date of Birth (M-D-Y) : ");
            while (!DateTime.TryParse(dob, out _))
            {
                Message.WriteLine("Incorrect Syntax : Date Format Only!", Message.Red);
                await Task.Delay(1000);
                Message.ClearConsole();
                foreach (string message in previousMessages)
                {
                    Console.Write(message);
                }

                dob = Console.ReadLine()!;
            }

            previousMessages.RemoveAt(previousMessages.Count - 1);
            previousMessages.Add($"Date of Birth (M-D-Y) : {dob}\n");

            User user = new User
            {
                FirstName = firstName.Trim(),
                LastName = lastName.Trim(),
                CivilID = long.Parse(civilID.Trim()),
                DOB = DateTime.Parse(dob.Trim())
            };

            return user;
        }
    }

    public class User
    {
        /*  User Information */
        public int ID { get; set; }
        public string BankName { get; set; } = string.Empty;
        public string FirstName { get; set; } = string.Empty;
        public string LastName { get; set; } = string.Empty;
        public long CivilID { get; set; }
        public decimal Balance { get; set; }
        public DateTime CreatedAt { get; set; }
        public DateTime DOB { get; set; }

        /*  User Credentials */

        public string Username { get; set; } = string.Empty;
        public string Password { get; set; } = string.Empty;

        /* Transaction Logs */

        public ICollection<TransactionLogs> TransactionLogs { get; set; } = new List<TransactionLogs>();

        /* Constructor */
        public User(string firstName, string lastName, long civilID, DateTime dob, string bankName, int id = 0)
        {
            FirstName = firstName;
            LastName = lastName;
            CivilID = civilID;
            DOB = dob;
            CreatedAt = DateTime.Now;
            Balance = 5000;
            BankName = bankName;
            /* For New Registerd Client a new Id will be issued with GetNewID() Method, For Current and Old Client the Id will be pulled from text database*/
            ID = id;

            FileSystem.CreateNewFile(ID).GetAwaiter();
            // Create A new text file for this User if doesnt exist
        }


        public User() { } // This to remove any errors regarding no arguments given        

        public async Task<bool> Withdraw(decimal amount)
        {
            if (amount == 0) return true;

            if(amount <= 0)
            {
                Message.WriteLine("Withdraw amount must be positive", Message.Red);
                return false;
            }

            if(amount > Balance)
            {
                Message.WriteLine("Insufficient funds!", Message.Red);
                return false;
            }


            Balance -= amount;
            await FileSystem.EditClientDatabase(this);
            await LogTransaction("Withdraw", amount);
            Console.Write($"Succesfully Withdrawn ");
            Message.Write($"{amount:N3} KWD", Message.Success);
            Console.Write(" New Balance : ");
            Message.Write($"{Balance:N3} KWD", Message.Blue);
            return true;            
        }

        public async Task<bool> Deposit(decimal amount)
        {
            if (amount == 0) return true;

            if (amount <= 0)
            {
                Message.WriteLine("Deposit amount must be positive", Message.Red);
                return false;
            }

            if (amount + Balance >= decimal.MaxValue)
            {
                Message.WriteLine("System Detected Fraud!, Closing the application Now!", Message.Red);
                await Task.Delay(2000);
                Environment.Exit(130);
            }


            Balance += amount;
            await FileSystem.EditClientDatabase(this);
            await LogTransaction("Deposit", amount);
            Console.Write($"Succesfully Deposited ");
            Message.Write($"{amount:N3} KWD", Message.Success);
            Console.Write(" New Balance : ");
            Message.Write($"{Balance:N3} KWD", Message.Blue);


            return true;
        }

        public async Task LogTransaction(string transactionType, decimal amount)
        {
            DateTime LogDate = DateTime.Today.Date;
            int id = await FileSystem.GetNewTransactionLogID(this);
            string log = $"{id}, {LogDate}, {transactionType}, {amount}, {Balance}";
            await FileSystem.WriteToFile(ID,log);

        }

        public async Task GetLogs()
        {
            // Use File system to get all the logs and then have it as a return type

            TransactionLogs = await FileSystem.GetLogs(ID);
        }

              
    }
     
    public class TransactionLogs()
    {
        public int ID { get; set; }
        public string TransactionType { get; set; } = string.Empty;
        public DateTime TransactionDate { get; set; }
        public decimal Amount { get; set; }
        public decimal Balance { get; set; }
    }
    public static class Message
    {
        public static ConsoleColor Success = ConsoleColor.Green;
        public static ConsoleColor Blue = ConsoleColor.Blue;
        public static ConsoleColor Red = ConsoleColor.Red;
        public static void Write(string message, ConsoleColor color)
        {
            Console.ForegroundColor = color;
            Console.Write(message);
            Console.ForegroundColor = ConsoleColor.White;
        }

        public static void WriteLine(string message, ConsoleColor color)
        {
            Console.ForegroundColor = color;
            Console.WriteLine(message);
            Console.ForegroundColor = ConsoleColor.White;
        }

        public static void ClearConsole()
        {
            Console.Clear();
            Console.ForegroundColor = ConsoleColor.White;
        }

        public async static Task<int> UserInputsNumbersOnly(int maxValue, Func<Task<int>> Page)
        {
            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.Write("\nUser Inputs : ");
            Console.ForegroundColor = ConsoleColor.White;

            string userInput = Console.ReadLine()!;

            if (!int.TryParse(userInput, out int value) || value > maxValue || value <= 0)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Incorrect Syntax or Number exceeded the limit given");
                await Task.Delay(1000);
                await Page.Invoke();
            }
            return value;
        }
        
    }

    public static class FileSystem
    {

        public static readonly string BasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "BankApp");


        public static void CreateDirectories()  
        {
            string clientPath = Path.Combine(BasePath, "Clients");            
            Directory.CreateDirectory(clientPath);
        }

        public static async Task CreateNewFile(int id)
        {
            await CreateMainFile();

            string path = Path.Combine(BasePath, "Clients", $"{id}.txt");

            if (!File.Exists(path))
            {
                using (File.Create(path)) { }
            }
        }

        public static async Task CreateMainFile()
        {
            CreateDirectories();

            string path = Path.Combine(BasePath, "data.txt");

            if (!File.Exists(path))
            {
                using (File.Create(path)) { }
            }
        }

        public static async Task WriteToFile(int id, string log)
        {
            await CreateNewFile(id);

            string path = Path.Combine(BasePath, "Clients", $"{id}.txt");

            //File.WriteAllText(path, log);

            using (StreamWriter sw = new StreamWriter(path, append: true))
            {
                await sw.WriteLineAsync(log);
            }
        }

        public static async Task<List<TransactionLogs>> GetLogs(int id)
        {
            List<TransactionLogs> logs = new List<TransactionLogs>();

            string path = Path.Combine(BasePath, "Clients", $"{id}.txt");

            if(!File.Exists(path))
            {
                return logs;
            }


            using (StreamReader sr = new StreamReader(path))
            {
                string? line;
                while ((line = await sr.ReadLineAsync()) != null)
                {
                    if (string.IsNullOrWhiteSpace(line)) continue;

                    string[] parts = line.Split(",");

                    if (parts.Length < 5) continue;

                    TransactionLogs log = new TransactionLogs
                    {                   
                        ID = int.Parse(parts[0]),
                        TransactionDate = DateTime.Parse(parts[1].Trim()),
                        TransactionType = parts[2].Trim(),
                        Amount = decimal.Parse(parts[3].Trim()),
                        Balance = decimal.Parse(parts[4].Trim())
                    };

                    logs.Add(log);
                }
            }
            return logs;
        }

        public static async Task<User> GetUser(string username, string password)
        {
            string path = Path.Combine(BasePath, "data.txt");
                        
            if(!File.Exists(path))
            {
                await CreateMainFile();
            }


            using (StreamReader sr = new StreamReader(path))
            {
                string? line;
                while((line = await sr.ReadLineAsync()) != null)
                {
                    if (string.IsNullOrWhiteSpace(line)) continue;

                    string[] parts = line.Split(",");

                    if(parts.Length < 10) continue;

                    if (parts[8].Trim() != username.Trim()) continue;

                    User user = new User
                    {
                        ID = int.Parse(parts[0].Trim()),
                        BankName = parts[1].Trim(),
                        FirstName = parts[2].Trim(),
                        LastName = parts[3].Trim(),
                        CivilID = long.Parse(parts[4].Trim()),
                        Balance = decimal.Parse(parts[5].Trim()),
                        CreatedAt = DateTime.Parse(parts[6].Trim()),
                        DOB = DateTime.Parse(parts[7].Trim()),
                        Username = parts[8].Trim(),
                        Password = parts[9].Trim(),


                    };


                    if(user.Password == password.Trim())
                    {
                        return user;
                    }
                    
                }
            }

            return null!;
        }

        public static async Task WriteNewUser(User user)
        {
            string path = Path.Combine(BasePath, "data.txt");

            if (!File.Exists(path))
            {                
                await CreateMainFile();
            }

            using (StreamWriter sw = new StreamWriter(path, append: true))
            {
                string client = $"{user.ID}, {user.BankName}, {user.FirstName}, {user.LastName}, {user.CivilID}, {user.Balance}, {user.CreatedAt}, {user.DOB}, {user.Username}, {user.Password}";

                await sw.WriteLineAsync(client);
            }            

        }

        public static async Task<int> GetNewID()
        {
            string path = Path.Combine(BasePath, "data.txt");

            if (!File.Exists(path))
            {
                await CreateMainFile();
                return 1;
            }

            using (StreamReader sr = new StreamReader(path))
            {
                string? line;
                string? lastLine = string.Empty;
                while ((line = await sr.ReadLineAsync()) != null)
                {
                    lastLine = line;
                }

                if (lastLine == string.Empty) return 1;


                string[] parts = lastLine.Split(",");

                int id = int.Parse(parts[0].Trim()) + 1;

                return id;


            }            
        }

        public static async Task<int> GetNewTransactionLogID(User user)
        {
            string path = Path.Combine(BasePath, "Clients", $"{user.ID}.txt");

            if (!File.Exists(path))
            {
                await CreateNewFile(user.ID);
                return 1;
            }

            using (StreamReader sr = new StreamReader(path))
            {
                string? line;
                string lastLine = string.Empty;
                while((line = await sr.ReadLineAsync()) != null)
                {
                    lastLine = line;
                }

                if(lastLine == string.Empty) return 1;

                string[] parts = lastLine.Split(',');
                
                int id = int.Parse(parts[0].Trim()) + 1;

                return id;
            }
            

        }

        public static async Task EditClientDatabase(User user)
        {
            string path = Path.Combine(BasePath, "data.txt");

            if(!File.Exists(path))
            {
                await CreateMainFile();
            }

            string client = $"{user.ID}, {user.BankName}, {user.FirstName}, {user.LastName}, {user.CivilID}, {user.Balance}, {user.CreatedAt}, {user.DOB}, {user.Username}, {user.Password}";
            bool foundClient = false;
            int lineNumber = -1;
            using (StreamReader sr = new StreamReader(path))
            {
                string? line;                
                
                while((line = await sr.ReadLineAsync()) != null)
                {
                    lineNumber++;
                    if (string.IsNullOrWhiteSpace(line)) continue;

                    string[] parts = line.Split(",");

                    if (int.TryParse(parts[0], out int id) && id == user.ID)
                    {
                        foundClient = true;
                        break;
                    }
                }
            }
            
            string[] lines = File.ReadAllLines(path);
            if(foundClient)
            {
                lines[lineNumber] = client;
                File.WriteAllLines(path, lines);
            }
        }
        

    }

}
Editor is loading...
Leave a Comment