module Main where import UserManager import Control.Exception import Text.Printf import Data.ByteString.Char8 (ByteString) import qualified Data.ByteString.Char8 as B import qualified Data.Map as Map -- Main entry point of the program main :: IO () main = do putStrLn "Welcome to User Management Console!" -- display a message to the user initializeDB -- initialize the database mainMenu -- start the main menu -- Main menu of the program mainMenu :: IO () mainMenu = do putStrLn "1. Add User" -- display the options to the user putStrLn "2. List Users" putStrLn "3. Find User" putStrLn "4. Delete User" putStrLn "5. (DEBUG) Generate and Add Users" putStrLn "6. Exit" putStrLn "Choose an option: " -- ask the user to choose an option option <- getLine case option of "1" -> addUserHandler -- handle the option chosen by the user "2" -> maplistUsersHandler "3" -> findUserHandler "4" -> deleteUserHandler "5" -> do putStrLn "Enter the number of users to generate and add: " numUsers <- readLn :: IO Int generateAndAddUsers numUsers putStrLn $ "Generated and added " ++ show numUsers ++ " users" mainMenu "6" -> putStrLn "Exiting..." -- exit the program _ -> putStrLn "Invalid option" >> mainMenu formatUser :: User -> ByteString formatUser user = B.pack $ printf "Name: %s Email: %s Password: %s" (userName user) (userEmail user) (userPassword user) -- Handle the addition of a user addUserHandler :: IO () addUserHandler = do putStrLn "Enter user name: " -- ask the user for a name name <- getLine putStrLn "Enter user email: " -- ask the user for an email email <- getLine putStrLn "Enter user password: " -- ask the user for a password password <- getLine addUser name email password `catch` handler -- add the user to the database, handling any errors mainMenu -- Handle the listing of all users listUsersHandler :: IO () listUsersHandler = do putStrLn "" users <- listUsers -- get the list of all users from the database let numberedUsers :: [(Int, User)] numberedUsers = zipWith (\n user -> (n, user)) [1..] users -- add numbering to the users formattedUsers = map (\(n, user) -> printf "%3d. %-15s %-20s %s" n (userName user) (userEmail user) (userPassword user)) numberedUsers -- format each user as a table row tableHeader = "No. Name Email Password" -- create the table header putStrLn tableHeader -- print the table header putStrLn $ replicate (length tableHeader) '-' -- print a line of dashes under the header mapM_ putStrLn formattedUsers -- print each user as a table row putStrLn "" mainMenu -- Handle the listing of all users using Data.Map maplistUsersHandler :: IO () maplistUsersHandler = do putStrLn "" users <- listUsers -- get the list of all users from the database let userMap = Map.fromList $ map (\user -> (userName user, user)) users -- create a map with user names as keys numberedUsers :: [(Int, (UserName, User))] numberedUsers = zipWith (\n (name, user) -> (n, (name, user))) [1..] (Map.toList userMap) -- add numbering to the users formattedUsers = map (\(n, (name, user)) -> printf "%3d. %-15s %-20s %s" n name (userEmail user) (userPassword user)) numberedUsers -- format each user as a table row tableHeader = "No. Name Email Password" -- create the table header putStrLn tableHeader -- print the table header putStrLn $ replicate (length tableHeader) '-' -- print a line of dashes under the header mapM_ putStrLn formattedUsers -- print each user as a table row putStrLn "" mainMenu -- Handle the finding of a user findUserHandler :: IO () findUserHandler = do putStrLn "Enter user name or email to find: " -- ask the user for a name or email to search for searchTerm <- getLine users <- findUsers searchTerm -- search the database for users matching the search term case users of [] -> putStrLn "User not found" _ -> mapM_ (putStrLn . B.unpack . formatUser) users -- print the users to the console using the formatted string mainMenu -- Handle the deletion of a user deleteUserHandler :: IO () deleteUserHandler = do putStrLn "Enter user name to delete: " -- ask the user for a name to delete name <- getLine deleteUser name `catch` handler -- delete the user from the database, handling any errors mainMenu -- Handle any exceptions that are thrown by the program handler :: SomeException -> IO () handler ex = putStrLn $ "An error occurred: " ++ show ex