-
Notifications
You must be signed in to change notification settings - Fork 132
Initial submission #157
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
m1chael888
wants to merge
4
commits into
TheCSharpAcademy:main
Choose a base branch
from
m1chael888:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Initial submission #157
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| <Solution> | ||
| <Project Path="DrinksInfo.m1chael888/DrinksInfo.m1chael888.csproj" /> | ||
| </Solution> |
88 changes: 88 additions & 0 deletions
88
DrinksInfo.m1chael888/DrinksInfo.m1chael888/Controllers/DrinksController.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| using DrinksInfo.m1chael888.Views; | ||
| using DrinksInfo.m1chael888.Services; | ||
| using DrinksInfo.m1chael888.Models; | ||
| using static DrinksInfo.m1chael888.Enums.MainMenuEnums; | ||
| using Spectre.Console; | ||
|
|
||
| namespace DrinksInfo.m1chael888.Controllers; | ||
|
|
||
| public class DrinksController | ||
| { | ||
| private readonly IDrinksView _drinksView; | ||
| private readonly IDrinksService _drinksService; | ||
| public DrinksController(IDrinksView tableView, IDrinksService drinksService) | ||
| { | ||
| _drinksView = tableView; | ||
| _drinksService = drinksService; | ||
| } | ||
|
|
||
| public void HandleMainMenu() | ||
| { | ||
| var choice = _drinksView.ShowMainMenu(); | ||
|
|
||
| switch (choice) | ||
| { | ||
| case MainMenuOption.ViewCategories: | ||
| try | ||
| { | ||
| HandleCategoryChoice(); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| _drinksView.ShowAccessError(ex.Message); | ||
| } | ||
| break; | ||
| case MainMenuOption.Exit: | ||
| Environment.Exit(0); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| private void HandleCategoryChoice() | ||
| { | ||
| var categories = _drinksService.GetCategories(); | ||
| if (categories.Count == 0) | ||
| { | ||
| ReturnStatus("Drinks menu currently unnavailable"); | ||
| } | ||
| else | ||
| { | ||
| var categoryChoice = _drinksView.ShowCategoryPrompt(categories); | ||
| try | ||
| { | ||
| HandleDrinkChoice(categoryChoice); | ||
| } | ||
| catch (Exception ex) | ||
| { | ||
| _drinksView.ShowAccessError(ex.Message); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private void HandleDrinkChoice(Category categoryChoice) | ||
| { | ||
| var drinks = _drinksService.GetDrinks(categoryChoice.strCategory); | ||
| if (drinks.Count == 0) | ||
| { | ||
| ReturnStatus("Drinks menu currently unnavailable"); | ||
| } | ||
| else | ||
| { | ||
| var drinkChoice = _drinksView.ShowDrinkPrompt(drinks); | ||
| _drinksView.ShowDrinkInfo(drinkChoice); | ||
| } | ||
|
|
||
| } | ||
|
|
||
| private void ReturnStatus(string msg) | ||
| { | ||
| AnsiConsole.MarkupLine($"[cyan]{msg}[/]"); | ||
| AnsiConsole.Status() | ||
| .Spinner(Spinner.Known.Point) | ||
| .SpinnerStyle("white") | ||
| .Start($"[grey74]Press any key to return[/]", x => | ||
| { | ||
| Console.ReadKey(); | ||
| }); | ||
| } | ||
| } |
17 changes: 17 additions & 0 deletions
17
DrinksInfo.m1chael888/DrinksInfo.m1chael888/DrinksInfo.m1chael888.csproj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| <Project Sdk="Microsoft.NET.Sdk"> | ||
|
|
||
| <PropertyGroup> | ||
| <OutputType>Exe</OutputType> | ||
| <TargetFramework>net10.0</TargetFramework> | ||
| <ImplicitUsings>enable</ImplicitUsings> | ||
| <Nullable>enable</Nullable> | ||
| </PropertyGroup> | ||
|
|
||
| <ItemGroup> | ||
| <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.2" /> | ||
| <PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> | ||
| <PackageReference Include="RestSharp" Version="113.1.0" /> | ||
| <PackageReference Include="Spectre.Console" Version="0.54.0" /> | ||
| </ItemGroup> | ||
|
|
||
| </Project> |
17 changes: 17 additions & 0 deletions
17
DrinksInfo.m1chael888/DrinksInfo.m1chael888/Enums/Extensions.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| using System.ComponentModel; | ||
|
|
||
| namespace DrinksInfo.m1chael888.Enums; | ||
|
|
||
| public static class Extensions | ||
| { | ||
| public static string GetDescription(Enum value) | ||
| { | ||
| var field = value.GetType().GetField(value.ToString()); | ||
| var attributes = (DescriptionAttribute[])field.GetCustomAttributes(typeof(DescriptionAttribute), false); | ||
| if (attributes.Length > 0) | ||
| { | ||
| return attributes[0].Description; | ||
| } | ||
| return value.ToString(); | ||
| } | ||
| } | ||
14 changes: 14 additions & 0 deletions
14
DrinksInfo.m1chael888/DrinksInfo.m1chael888/Enums/MainMenuEnums.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| using System.ComponentModel; | ||
|
|
||
| namespace DrinksInfo.m1chael888.Enums; | ||
|
|
||
| public static class MainMenuEnums | ||
| { | ||
| public enum MainMenuOption | ||
| { | ||
| [Description("View Categories")] | ||
| ViewCategories, | ||
| [Description("Exit App")] | ||
| Exit | ||
| } | ||
| } |
18 changes: 18 additions & 0 deletions
18
DrinksInfo.m1chael888/DrinksInfo.m1chael888/Infrastructure/Router.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| using DrinksInfo.m1chael888.Controllers; | ||
|
|
||
| namespace DrinksInfo.m1chael888.Infrastructure; | ||
|
|
||
| public interface IRouter | ||
| { | ||
| void Route(DrinksController drinksController); | ||
| } | ||
| public class Router : IRouter | ||
| { | ||
| public void Route(DrinksController drinksController) | ||
| { | ||
| while (true) | ||
| { | ||
| drinksController.HandleMainMenu(); | ||
| } | ||
| } | ||
| } |
13 changes: 13 additions & 0 deletions
13
DrinksInfo.m1chael888/DrinksInfo.m1chael888/Models/CategoryModel.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| using Newtonsoft.Json; | ||
|
|
||
| namespace DrinksInfo.m1chael888.Models; | ||
|
|
||
| public class Category | ||
| { | ||
| public string strCategory { get; set; } = string.Empty; | ||
| } | ||
| public class Categories | ||
| { | ||
| [JsonProperty("drinks")] | ||
| public List<Category> CategoriesList { get; set; } | ||
| } |
16 changes: 16 additions & 0 deletions
16
DrinksInfo.m1chael888/DrinksInfo.m1chael888/Models/DrinkModel.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,16 @@ | ||
| using Newtonsoft.Json; | ||
|
|
||
| namespace DrinksInfo.m1chael888.Models; | ||
|
|
||
| public class Drink | ||
| { | ||
| public string strDrink { get; set; } = string.Empty; | ||
| public int idDrink { get; set; } | ||
| public string strDrinkThumb { get; set; } = string.Empty; | ||
| } | ||
|
|
||
| public class Drinks | ||
| { | ||
| [JsonProperty("drinks")] | ||
| public List<Drink> DrinkList { get; set; } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| using Microsoft.Extensions.DependencyInjection; | ||
| using DrinksInfo.m1chael888.Infrastructure; | ||
| using DrinksInfo.m1chael888.Services; | ||
| using DrinksInfo.m1chael888.Views; | ||
| using System.Text; | ||
| using DrinksInfo.m1chael888.Controllers; | ||
|
|
||
| namespace DrinksInfo.m1chael888; | ||
|
|
||
| internal class Program | ||
| { | ||
| static void Main(string[] args) | ||
| { | ||
| Console.OutputEncoding = Encoding.UTF8; | ||
|
|
||
| var collection = new ServiceCollection(); | ||
|
|
||
| collection.AddScoped<IRouter, Router>(); | ||
| collection.AddScoped<DrinksController>(); | ||
| collection.AddScoped<IDrinksService, DrinksService>(); | ||
| collection.AddScoped <IDrinksView, DrinksView>(); | ||
|
|
||
| var provider = collection.BuildServiceProvider(); | ||
|
|
||
| var drinksController = provider.GetRequiredService<DrinksController>(); | ||
| var router = provider.GetRequiredService<IRouter>(); | ||
| router.Route(drinksController); | ||
| } | ||
| } |
50 changes: 50 additions & 0 deletions
50
DrinksInfo.m1chael888/DrinksInfo.m1chael888/Services/DrinksService.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| using Newtonsoft.Json; | ||
| using RestSharp; | ||
| using DrinksInfo.m1chael888.Models; | ||
|
|
||
| namespace DrinksInfo.m1chael888.Services; | ||
|
|
||
| public interface IDrinksService | ||
| { | ||
| List<Category> GetCategories(); | ||
| List<Drink> GetDrinks(string category); | ||
| } | ||
| public class DrinksService : IDrinksService | ||
| { | ||
| private readonly string _drinkClient = "https://www.thecocktaildb.com/api/json/v1/1/"; | ||
| public List<Category> GetCategories() | ||
| { | ||
| var client = new RestClient(_drinkClient); | ||
| var request = new RestRequest("list.php?c=list"); | ||
| var response = client.ExecuteAsync(request); | ||
|
|
||
| if (response.Result.StatusCode == System.Net.HttpStatusCode.OK) | ||
| { | ||
| var responseString = response.Result.Content; | ||
| var serialize = JsonConvert.DeserializeObject<Categories>(responseString); | ||
|
|
||
| List<Category> categories = serialize.CategoriesList; | ||
|
|
||
| return categories; | ||
| } | ||
| return new List<Category> { }; | ||
| } | ||
|
|
||
| public List<Drink> GetDrinks(string category) | ||
| { | ||
| var client = new RestClient(_drinkClient); | ||
| var request = new RestRequest($"filter.php?c={category}"); | ||
| var response = client.ExecuteAsync(request); | ||
|
|
||
| if (response.Result.StatusCode == System.Net.HttpStatusCode.OK) | ||
| { | ||
| var responseString = response.Result.Content; | ||
| var serialize = JsonConvert.DeserializeObject<Drinks>(responseString); | ||
|
|
||
| List<Drink> drinks = serialize.DrinkList; | ||
|
|
||
| return drinks; | ||
| } | ||
| return new List<Drink> { }; | ||
| } | ||
| } |
83 changes: 83 additions & 0 deletions
83
DrinksInfo.m1chael888/DrinksInfo.m1chael888/Views/DrinksView.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,83 @@ | ||
| using Spectre.Console; | ||
| using DrinksInfo.m1chael888.Models; | ||
| using static DrinksInfo.m1chael888.Enums.Extensions; | ||
| using static DrinksInfo.m1chael888.Enums.MainMenuEnums; | ||
|
|
||
| namespace DrinksInfo.m1chael888.Views; | ||
|
|
||
| public interface IDrinksView | ||
| { | ||
| Category ShowCategoryPrompt(List<Category> categories); | ||
| Drink ShowDrinkPrompt(List<Drink> drinks); | ||
| void ShowDrinkInfo(Drink drink); | ||
| MainMenuOption ShowMainMenu(); | ||
| void ShowAccessError(string msg); | ||
| } | ||
| public class DrinksView : IDrinksView | ||
| { | ||
| public MainMenuOption ShowMainMenu() | ||
| { | ||
| Console.Clear(); | ||
| return AnsiConsole.Prompt( | ||
| new SelectionPrompt<MainMenuOption>() | ||
| .Title("[cyan]Main Menu::[/]") | ||
| .AddChoices(Enum.GetValues<MainMenuOption>()) | ||
| .UseConverter(x => $"[grey74]{GetDescription(x)}[/]") | ||
| .HighlightStyle("DarkOrange") | ||
| .WrapAround()); | ||
| } | ||
|
|
||
| public Category ShowCategoryPrompt(List<Category> categories) | ||
| { | ||
| Console.Clear(); | ||
| return AnsiConsole.Prompt( | ||
| new SelectionPrompt<Category>() | ||
| .Title("[cyan]Choose a category to view::[/]") | ||
| .AddChoices(categories) | ||
| .UseConverter(x => $"[grey74]{x.strCategory}[/]") | ||
| .HighlightStyle("DarkOrange") | ||
| .PageSize(categories.Count) | ||
| .WrapAround()); | ||
| } | ||
|
|
||
| public Drink ShowDrinkPrompt(List<Drink> drinks) | ||
| { | ||
| Console.Clear(); | ||
| return AnsiConsole.Prompt( | ||
| new SelectionPrompt<Drink>() | ||
| .Title("[cyan]Choose a drink::[/]") | ||
| .AddChoices(drinks) | ||
| .UseConverter(x => $"[grey74]{x.strDrink}[/]") | ||
| .HighlightStyle("DarkOrange") | ||
| .PageSize(25) | ||
| .WrapAround()); | ||
| } | ||
|
|
||
| public void ShowDrinkInfo(Drink drink) | ||
| { | ||
| Console.Clear(); | ||
| AnsiConsole.MarkupLine($"[cyan]Drink info::[/]\n"); | ||
| AnsiConsole.MarkupLine($" [darkorange]Name -[/] [grey74]{drink.strDrink}[/]"); | ||
| AnsiConsole.MarkupLine($" [darkorange]Id -[/] [grey74]{drink.idDrink}[/]"); | ||
| AnsiConsole.MarkupLine($"[darkorange]Image -[/] [grey74]{drink.strDrinkThumb}[/]\n"); | ||
| ReturnToMenu(); | ||
| } | ||
|
|
||
| public void ShowAccessError(string msg) | ||
| { | ||
| Console.Clear(); | ||
| AnsiConsole.MarkupLine($"[cyan]Error: {msg}[/]"); | ||
| ReturnToMenu(); | ||
| } | ||
|
|
||
| private void ReturnToMenu() | ||
| { | ||
| AnsiConsole.Status() | ||
| .Spinner(Spinner.Known.Point) | ||
| .SpinnerStyle("grey74") | ||
| .Start("[grey74]Press any key to return to menu[/]", x => | ||
| { | ||
| Console.ReadKey(); | ||
| }); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| # DrinksInfo.m1chael888 | ||
| This is a simple program used to call a drinks menu API in a C# Console. API calls are done using RestSharp, and the results are displayed in the console using Spectre. | ||
|
|
||
| # How it works | ||
| * Starting the app will display a main menu, allowing you to view drink categories or exit the app. Choosing to view categories will display a list of all available drink categories. To choose a category, navigate up and down the list using your arrow keys and press enter to select one. | ||
| * After choosing a category, a list of all matching drinks will be similarly displayed, and you can choose one in the same way. After choosing a drink, the details associated with it will be displayed, including the drinks name, id and thumbnail image url. You can then press any key to return to the menu. |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔴 Potential IndexOutOfRangeException Bug
💡 The GetDescription method has a logic error. When no DescriptionAttribute is found, it still tries to access
attributes[0].Description, which will throw an IndexOutOfRangeException. Fix by returning the enum name instead: