Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions DrinksInfo.slnx
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<Solution>
<Project Path="DrinksInfo/DrinksInfo.csproj" />
</Solution>
118 changes: 118 additions & 0 deletions DrinksInfo/Controllers/DrinksController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using DrinksInfo.Models;
using DrinksInfo.Services;
using DrinksInfo.Utils;
using Spectre.Console;

namespace DrinksInfo.Controllers;

internal class DrinksController(DrinksService drinksService)
{
//Logo credits: https://patorjk.com/
private readonly string logo = "[blue] ___ ___ ___ _ _ _ _____ ___ _ _ ___ ___ \r\n | \\| _ \\_ _| \\| | |/ / __| |_ _| \\| | __/ _ \\ \r\n | |) | /| || .` | ' <\\__ \\ | || .` | _| (_) |\r\n |___/|_|_\\___|_|\\_|_|\\_\\___/ |___|_|\\_|_| \\___/ \r\n [/]";
internal readonly DrinksService _drinksService = drinksService;

public async Task CategoryMenuScreen()
{
try
{
while (true)
{
var categories = await _drinksService.GetCategories();
categories.Add(new Category { StrCategory = Shared.exitText });
AnsiConsole.Clear();
AnsiConsole.MarkupLine(logo);
var choice = AnsiConsole.Prompt(
new SelectionPrompt<Category>()
.Title("")
.AddChoices(categories)
.WrapAround(true)
.PageSize(30)
.UseConverter(cat => cat.StrCategory)
);

if (choice.StrCategory == Shared.exitText) Environment.Exit(0);
await DrinksFromCategoryScreen(choice);
}
}
catch (Exception e)
{
AnsiConsole.MarkupLine($"[{Styles.error}]Something went wrong[/]: {e.Message}]");
Shared.AskForKey();
}
}

public async Task DrinksFromCategoryScreen(Category category)
{
try
{
var drinks = await _drinksService.GetDrinksByCategory(category);
drinks.Add(new Drink { StrDrink = Shared.goBackText });
AnsiConsole.Clear();
var choice = AnsiConsole.Prompt(
new SelectionPrompt<Drink>()
.Title("")
.AddChoices(drinks)
.WrapAround(true)
.PageSize(30)
.UseConverter(drink => drink.StrDrink));

if (choice.StrDrink == Shared.goBackText) return;
await DrinkScreen(choice);
}
catch (Exception e)
{
AnsiConsole.MarkupLine($"[{Styles.error}]Something went wrong[/]: {e.Message}");
Shared.AskForKey();
}
}

public async Task DrinkScreen(Drink drink)
{
try
{
var drinkDetail = await _drinksService.GetDrink(drink.IdDrink);
var panel = new Panel(FormatDrinkString(drinkDetail))
.Border(BoxBorder.Rounded)
.Header(drinkDetail.StrDrink);

panel.Header.Centered();
panel.BorderStyle(Color.Blue);
AnsiConsole.Clear();
AnsiConsole.Write(panel);
}
catch (Exception e)
{
AnsiConsole.MarkupLine($"[{Styles.error}]Error[/]: {e.Message}");
}
Shared.AskForKey();
}

private static string FormatDrinkString(DrinkDetail drink)
{
var formattedStr = $"""
{$"[{Styles.subtle}]Category[/] {drink.StrCategory}"}

[{Styles.subtle}]Alcoholic:[/] [{Styles.warn}]{drink.StrAlcoholic}[/]
[{Styles.subtle}]Glass:[/] {drink.StrGlass} {(drink.StrIBA is not null && drink.StrIBA != "" ? $"[{Styles.subtle}]IBA:[/] {drink.StrIBA}" : "")}

[{Styles.subtle}]Instructions:[/] {drink.StrInstructions}

""";

for (var i = 1; i < 13; i++)
{
var ingredientVal = drink.GetType().GetProperty($"StrIngredient{i}").GetValue(drink);
var measureVal = drink.GetType().GetProperty($"StrMeasure{i}").GetValue(drink);

if (ingredientVal is not null && ingredientVal != "")
{
formattedStr += $"[{Styles.subtle}]Ingredient[/]: {ingredientVal}" +
$"{(measureVal is not null && measureVal != "" ? $" — {measureVal}" : "")}\n";
}
else { break; }
}

formattedStr += $"\n[{Styles.subtle}]Date modified:[/] {drink.DateModified}";
return formattedStr;
}
}
15 changes: 15 additions & 0 deletions DrinksInfo/DrinksInfo.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<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.1" />
<PackageReference Include="Spectre.Console" Version="0.54.0" />
</ItemGroup>

</Project>
16 changes: 16 additions & 0 deletions DrinksInfo/Models/Category.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Text.Json.Serialization;

namespace DrinksInfo.Models
{
public class Category
{
[JsonPropertyName("strCategory")]
public string StrCategory { get; set; }
}

public class Categories
{
[JsonPropertyName("drinks")]
public List<Category> CategoriesList { get; set; }
}
}
18 changes: 18 additions & 0 deletions DrinksInfo/Models/Drink.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System.Text.Json.Serialization;

namespace DrinksInfo.Models
{
public class Drinks
{
[JsonPropertyName("drinks")]
public List<Drink> DrinksList { get; set; } = [];
}

public class Drink
{
[JsonPropertyName("idDrink")]
public string IdDrink { get; set; } = "";
[JsonPropertyName("strDrink")]
public string StrDrink { get; set; } = "";
}
}
113 changes: 113 additions & 0 deletions DrinksInfo/Models/DrinkDetail.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
using System.Text.Json.Serialization;

namespace DrinksInfo.Models
{
internal class DrinkDetailObject
{
[JsonPropertyName("drinks")]
public List<DrinkDetail> DrinkDetailList { get; set; } = [];
}
internal class DrinkDetail
{
[JsonPropertyName("strDrink")]
public string StrDrink { get; set; } = "";
[JsonPropertyName("strDrinkAlternate")]
public string StrDrinkAlternate { get; set; } = "";
[JsonPropertyName("strTags")]
public string StrTags { get; set; } = "";
[JsonPropertyName("strVideo")]
public string StrVideo { get; set; } = "";
[JsonPropertyName("strCategory")]
public string StrCategory { get; set; } = "";
[JsonPropertyName("strIBA")]
public string StrIba { get; set; } = "";
[JsonPropertyName("strAlcoholic")]
public string StrAlcoholic { get; set; } = "";
[JsonPropertyName("strGlass")]
public string StrGlass { get; set; } = "";
[JsonPropertyName("strInstructions")]
public string StrInstructions { get; set; } = "";
[JsonPropertyName("strInstructionsES")]
public string StrInstructionsES { get; set; } = "";
[JsonPropertyName("strInstructionsDE")]
public string StrInstructionsDE { get; set; } = "";
[JsonPropertyName("strInstructionsFR")]
public string StrInstructionsFR { get; set; } = "";
[JsonPropertyName("strInstructionsIT")]
public string StrInstructionsIT { get; set; } = "";
[JsonPropertyName("strInstructionsZHHANS")]
public string StrInstructionsZhhans { get; set; } = "";
[JsonPropertyName("strInstructionsZHHANT")]
public string StrInstructionsZhhant { get; set; } = "";
[JsonPropertyName("strDrinkThumb")]
public string StrDrinkThumb { get; set; } = "";
[JsonPropertyName("strIngredient1")]
public string StrIngredient1 { get; set; } = "";
[JsonPropertyName("strIngredient2")]
public string StrIngredient2 { get; set; } = "";
[JsonPropertyName("strIngredient3")]
public string StrIngredient3 { get; set; } = "";
[JsonPropertyName("strIngredient4")]
public string StrIngredient4 { get; set; } = "";
[JsonPropertyName("strIngredient5")]
public string StrIngredient5 { get; set; } = "";
[JsonPropertyName("strIngredient6")]
public string StrIngredient6 { get; set; } = "";
[JsonPropertyName("strIngredient7")]
public string StrIngredient7 { get; set; } = "";
[JsonPropertyName("strIngredient8")]
public string StrIngredient8 { get; set; } = "";
[JsonPropertyName("strIngredient9")]
public string StrIngredient9 { get; set; } = "";
[JsonPropertyName("strIngredient10")]
public string StrIngredient10 { get; set; } = "";
[JsonPropertyName("strIngredient11")]
public string StrIngredient11 { get; set; } = "";
[JsonPropertyName("strIngredient12")]
public string StrIngredient12 { get; set; } = "";
[JsonPropertyName("strIngredient13")]
public string StrIngredient13 { get; set; } = "";
[JsonPropertyName("strIngredient14")]
public string StrIngredient14 { get; set; } = "";
[JsonPropertyName("strIngredient15")]
public string StrIngredient15 { get; set; } = "";
[JsonPropertyName("strMeasure1")]
public string StrMeasure1 { get; set; } = "";
[JsonPropertyName("strMeasure2")]
public string StrMeasure2 { get; set; } = "";
[JsonPropertyName("strMeasure3")]
public string StrMeasure3 { get; set; } = "";
[JsonPropertyName("strMeasure4")]
public string StrMeasure4 { get; set; } = "";
[JsonPropertyName("strMeasure5")]
public string StrMeasure5 { get; set; } = "";
[JsonPropertyName("strMeasure6")]
public string StrMeasure6 { get; set; } = "";
[JsonPropertyName("strMeasure7")]
public string StrMeasure7 { get; set; } = "";
[JsonPropertyName("strMeasure8")]
public string StrMeasure8 { get; set; } = "";
[JsonPropertyName("strMeasure9")]
public string StrMeasure9 { get; set; } = "";
[JsonPropertyName("strMeasure10")]
public string StrMeasure10 { get; set; } = "";
[JsonPropertyName("strMeasure11")]
public string StrMeasure11 { get; set; } = "";
[JsonPropertyName("strMeasure12")]
public string StrMeasure12 { get; set; } = "";
[JsonPropertyName("strMeasure13")]
public string StrMeasure13 { get; set; } = "";
[JsonPropertyName("strMeasure14")]
public string StrMeasure14 { get; set; } = "";
[JsonPropertyName("strMeasure15")]
public string StrMeasure15 { get; set; } = "";
[JsonPropertyName("strImageSource")]
public string StrImageSource { get; set; } = "";
[JsonPropertyName("strImageAttribution")]
public string StrImageAttribution { get; set; } = "";
[JsonPropertyName("strCreativeCommonsConfirmed")]
public string StrCreativeCommonsConfirmed { get; set; } = "";
[JsonPropertyName("dateModified")]
public string DateModified { get; set; } = "";
}
}
20 changes: 20 additions & 0 deletions DrinksInfo/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using DrinksInfo.Controllers;
using DrinksInfo.Services;
using Microsoft.Extensions.DependencyInjection;

namespace DrinksInfo;

class Program
{
static async Task Main()
{
IServiceCollection services = new ServiceCollection();
services.AddTransient<DrinksService>();
services.AddTransient<DrinksController>();
ServiceProvider serviceProvider = services.BuildServiceProvider();


var mainMenu = serviceProvider.GetService<DrinksController>()!;
await mainMenu.CategoryMenuScreen();
}
}
69 changes: 69 additions & 0 deletions DrinksInfo/Services/DrinksService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using DrinksInfo.Models;
using System.Text.Json;
using System.Web;

namespace DrinksInfo.Services
{
public class DrinksService
{
private readonly Uri Url = new Uri("http://www.thecocktaildb.com/api/json/v1/1/");
private readonly string GetCategoryUrl = "list.php?c=list";

public async Task<List<Category>> GetCategories()
{
using var client = new HttpClient { BaseAddress = Url };

var response = await client.GetAsync(GetCategoryUrl);
List<Category> categories = [];
if (response.IsSuccessStatusCode)
{
var rawResponse = response.Content;
var jsonText = await rawResponse.ReadAsStringAsync();
categories = JsonSerializer.Deserialize<Categories>(jsonText)!.CategoriesList;
}
else
{
throw new HttpRequestException("Error on the server, please try again in a few minutes");
}

return categories;
}

internal async Task<List<Drink>> GetDrinksByCategory(Category category)
{
using var client = new HttpClient { BaseAddress = Url };
var response = await client.GetAsync($"filter.php?c={HttpUtility.UrlEncode(category.StrCategory)}");
List<Drink> drinks = [];

if (response.IsSuccessStatusCode)
{
string rawResponse = await response.Content.ReadAsStringAsync();
var serialize = JsonSerializer.Deserialize<Drinks>(rawResponse);

drinks = serialize!.DrinksList;
}
else
{
throw new HttpRequestException("Error on the server, please try again in a few minutes");
}
return drinks;
}

internal async Task<DrinkDetail> GetDrink(string drinkId)
{
var client = new HttpClient { BaseAddress = Url };
var response = await client.GetAsync($"lookup.php?i={drinkId}");

if (response.IsSuccessStatusCode)
{
var strResponse = await response.Content.ReadAsStringAsync();
var drink = JsonSerializer.Deserialize<DrinkDetailObject>(strResponse).DrinkDetailList;
return drink[0];
}
else
{
throw new HttpRequestException("Error on the server, please try again in a few minutes");
}
}
}
}
15 changes: 15 additions & 0 deletions DrinksInfo/Utils/Shared.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Spectre.Console;

namespace DrinksInfo.Utils;

public static class Shared
{
public static readonly string goBackText = $"[{Styles.subtle}]Go Back[/]";
public static readonly string exitText = $"[{Styles.subtle}]Exit[/]";

public static void AskForKey(string message = "Press any key to continue...")
{
AnsiConsole.MarkupLine($"[{Styles.subtle}]{message}[/]");
Console.ReadKey();
}
}
Loading