Init
							
								
								
									
										49
									
								
								drinkMe.sln
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					Microsoft Visual Studio Solution File, Format Version 12.00
 | 
				
			||||||
 | 
					# Visual Studio Version 16
 | 
				
			||||||
 | 
					VisualStudioVersion = 16.0.31129.286
 | 
				
			||||||
 | 
					MinimumVisualStudioVersion = 10.0.40219.1
 | 
				
			||||||
 | 
					Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "drinkMe.Server", "drinkMe\Server\drinkMe.Server.csproj", "{4347ED6F-C6EC-44D2-A718-68490CBFFDF0}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "drinkMe.Client", "drinkMe\Client\drinkMe.Client.csproj", "{33E45585-7F5D-428D-8A27-FAB29A1A2E61}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "drinkMe.Shared", "drinkMe\Shared\drinkMe.Shared.csproj", "{85CCE095-22AC-434E-B77C-75998FF8DAD3}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "drinkMe.Client.Models", "drinkMe\drinkMe.Client.Models\drinkMe.Client.Models.csproj", "{7C00959D-3C7F-4617-B1DA-7909E5879C08}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
 | 
					Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "drinkMe.Server.Models", "drinkMe\drinkMe.Server.Models\drinkMe.Server.Models.csproj", "{EC73DC9D-FD40-4505-989D-83B49018401D}"
 | 
				
			||||||
 | 
					EndProject
 | 
				
			||||||
 | 
					Global
 | 
				
			||||||
 | 
						GlobalSection(SolutionConfigurationPlatforms) = preSolution
 | 
				
			||||||
 | 
							Debug|Any CPU = Debug|Any CPU
 | 
				
			||||||
 | 
							Release|Any CPU = Release|Any CPU
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
						GlobalSection(ProjectConfigurationPlatforms) = postSolution
 | 
				
			||||||
 | 
							{4347ED6F-C6EC-44D2-A718-68490CBFFDF0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{4347ED6F-C6EC-44D2-A718-68490CBFFDF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{4347ED6F-C6EC-44D2-A718-68490CBFFDF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{4347ED6F-C6EC-44D2-A718-68490CBFFDF0}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{33E45585-7F5D-428D-8A27-FAB29A1A2E61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{33E45585-7F5D-428D-8A27-FAB29A1A2E61}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{33E45585-7F5D-428D-8A27-FAB29A1A2E61}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{33E45585-7F5D-428D-8A27-FAB29A1A2E61}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{85CCE095-22AC-434E-B77C-75998FF8DAD3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{85CCE095-22AC-434E-B77C-75998FF8DAD3}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{85CCE095-22AC-434E-B77C-75998FF8DAD3}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{85CCE095-22AC-434E-B77C-75998FF8DAD3}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{7C00959D-3C7F-4617-B1DA-7909E5879C08}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{7C00959D-3C7F-4617-B1DA-7909E5879C08}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{7C00959D-3C7F-4617-B1DA-7909E5879C08}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{7C00959D-3C7F-4617-B1DA-7909E5879C08}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
							{EC73DC9D-FD40-4505-989D-83B49018401D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
 | 
				
			||||||
 | 
							{EC73DC9D-FD40-4505-989D-83B49018401D}.Debug|Any CPU.Build.0 = Debug|Any CPU
 | 
				
			||||||
 | 
							{EC73DC9D-FD40-4505-989D-83B49018401D}.Release|Any CPU.ActiveCfg = Release|Any CPU
 | 
				
			||||||
 | 
							{EC73DC9D-FD40-4505-989D-83B49018401D}.Release|Any CPU.Build.0 = Release|Any CPU
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
						GlobalSection(SolutionProperties) = preSolution
 | 
				
			||||||
 | 
							HideSolutionNode = FALSE
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
						GlobalSection(ExtensibilityGlobals) = postSolution
 | 
				
			||||||
 | 
							SolutionGuid = {AB58BAA9-F7FC-4BF0-BC33-174BAB7F8320}
 | 
				
			||||||
 | 
						EndGlobalSection
 | 
				
			||||||
 | 
					EndGlobal
 | 
				
			||||||
							
								
								
									
										10
									
								
								drinkMe/Client/App.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					<Router AppAssembly="@typeof(Program).Assembly" PreferExactMatches="@true">
 | 
				
			||||||
 | 
					    <Found Context="routeData">
 | 
				
			||||||
 | 
					        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
 | 
				
			||||||
 | 
					    </Found>
 | 
				
			||||||
 | 
					    <NotFound>
 | 
				
			||||||
 | 
					        <LayoutView Layout="@typeof(MainLayout)">
 | 
				
			||||||
 | 
					            <p>Sorry, there's nothing at this address.</p>
 | 
				
			||||||
 | 
					        </LayoutView>
 | 
				
			||||||
 | 
					    </NotFound>
 | 
				
			||||||
 | 
					</Router>
 | 
				
			||||||
							
								
								
									
										35
									
								
								drinkMe/Client/Components/PurchaseSteps.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					<section class="section has-content-centered">
 | 
				
			||||||
 | 
						<ul class="steps is-centered has-content-centered is-medium">
 | 
				
			||||||
 | 
							<li class="steps-segment @VUtilities.IfTrueThen(PurchaseStep == PurchaseStep.ChoosingProducts, ActiveClass, InactiveClass)">
 | 
				
			||||||
 | 
								<span class="steps-marker is-primary">
 | 
				
			||||||
 | 
									<i class="fad fa-cart-plus"></i>
 | 
				
			||||||
 | 
								</span>
 | 
				
			||||||
 | 
								<div class="steps-content">
 | 
				
			||||||
 | 
									<p class="is-size-4">Choose drinks</p>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</li>
 | 
				
			||||||
 | 
							<li class="steps-segment @VUtilities.IfTrueThen(PurchaseStep == PurchaseStep.PaymentSetup, ActiveClass, InactiveClass)">
 | 
				
			||||||
 | 
								<span class="steps-marker @VUtilities.IfTrueThen(PurchaseStep is PurchaseStep.PaymentSetup or PurchaseStep.SuccessfulPurchase, PrimaryClass)">
 | 
				
			||||||
 | 
									<i class="fad fa-money-bill-wave"></i>
 | 
				
			||||||
 | 
								</span>
 | 
				
			||||||
 | 
								<div class="steps-content">
 | 
				
			||||||
 | 
									<p class="is-size-4">Payment</p>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</li>
 | 
				
			||||||
 | 
							<li class="steps-segment @VUtilities.IfTrueThen(PurchaseStep == PurchaseStep.SuccessfulPurchase, ActiveClass, InactiveClass)">
 | 
				
			||||||
 | 
								<span class="steps-marker @VUtilities.IfTrueThen(PurchaseStep == PurchaseStep.SuccessfulPurchase, PrimaryClass)">
 | 
				
			||||||
 | 
									<i class="fad fa-check-double"></i>
 | 
				
			||||||
 | 
								</span>
 | 
				
			||||||
 | 
								<div class="steps-content">
 | 
				
			||||||
 | 
									<p class="is-size-4">Done!</p>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</li>
 | 
				
			||||||
 | 
						</ul>
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@code {
 | 
				
			||||||
 | 
						[Parameter] public PurchaseStep PurchaseStep { get; set; }
 | 
				
			||||||
 | 
						const string ActiveClass = "is-active has-gaps";
 | 
				
			||||||
 | 
						const string InactiveClass = "is-primary has-gaps";
 | 
				
			||||||
 | 
						const string PrimaryClass = "is-primary";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								drinkMe/Client/Helpers/VUtilities.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					namespace drinkMe.Client.Helpers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public static class VUtilities
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public static T IfTrueThen<T>(bool conditionIsTrue, T ifTrue, T ifFalse = default)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (conditionIsTrue)
 | 
				
			||||||
 | 
									return ifTrue;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									return ifFalse;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										23
									
								
								drinkMe/Client/Pages/Done.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,23 @@
 | 
				
			|||||||
 | 
					@page "/done"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<PurchaseSteps PurchaseStep="PurchaseStep.SuccessfulPurchase" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<section class="section">
 | 
				
			||||||
 | 
						<div class="container">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<div class="columns">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<div class="column">
 | 
				
			||||||
 | 
									<div class="box">
 | 
				
			||||||
 | 
										<h1 class="title has-text-centered">
 | 
				
			||||||
 | 
											<span>🎉</span>
 | 
				
			||||||
 | 
											<span>Purchase completed with success!</span>
 | 
				
			||||||
 | 
											<span>🎉</span>
 | 
				
			||||||
 | 
										</h1>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
							
								
								
									
										163
									
								
								drinkMe/Client/Pages/Index.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,163 @@
 | 
				
			|||||||
 | 
					@page "/"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<PurchaseSteps PurchaseStep="PurchaseStep.ChoosingProducts" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<section class="section">
 | 
				
			||||||
 | 
						<div class="container">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<div class="columns">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<div class="column is-half">
 | 
				
			||||||
 | 
									<div class="columns is-multiline">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										@foreach (var drink in AvailableDrinks)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											<div @key="drink.Id" class="column is-full">
 | 
				
			||||||
 | 
												<div class="box">
 | 
				
			||||||
 | 
													<article class="media">
 | 
				
			||||||
 | 
														<div class="media-left">
 | 
				
			||||||
 | 
															<figure class="image is-64x64">
 | 
				
			||||||
 | 
																<img src="images/drinks/@drink.PictureName" alt="drink image">
 | 
				
			||||||
 | 
															</figure>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
														<div class="media-content">
 | 
				
			||||||
 | 
															<div class="content">
 | 
				
			||||||
 | 
																<p>
 | 
				
			||||||
 | 
																	<strong>@drink.Name</strong>
 | 
				
			||||||
 | 
																	<br>
 | 
				
			||||||
 | 
																	<span>@drink.Description</span>
 | 
				
			||||||
 | 
																</p>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
															<div class="level">
 | 
				
			||||||
 | 
																<div class="level-left">
 | 
				
			||||||
 | 
																	<div class="level-item">
 | 
				
			||||||
 | 
																		<strong>@drink.Price €</strong>
 | 
				
			||||||
 | 
																	</div>
 | 
				
			||||||
 | 
																</div>
 | 
				
			||||||
 | 
																<div class="level-right mt-2-mobile">
 | 
				
			||||||
 | 
																	<div class="level-item has-text-centered">
 | 
				
			||||||
 | 
																		<button class="button is-small is-primary has-icons-left"
 | 
				
			||||||
 | 
																						disabled="@drink.IsInTheCart" @onclick="async () => await AddToCart(drink)">
 | 
				
			||||||
 | 
																			<span class="icon"><i class="fad fa-cart-arrow-down"></i></span>
 | 
				
			||||||
 | 
																			<span>Add to cart</span>
 | 
				
			||||||
 | 
																		</button>
 | 
				
			||||||
 | 
																	</div>
 | 
				
			||||||
 | 
																</div>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
													</article>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<div class="column is-half">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									<div class="box">
 | 
				
			||||||
 | 
										@if (CartDrinks.Count == 0)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											<h1 class="has-text-centered">
 | 
				
			||||||
 | 
												<span class="icon-text">
 | 
				
			||||||
 | 
													<span class="icon">
 | 
				
			||||||
 | 
														<i class="fad fa-shopping-cart"></i>
 | 
				
			||||||
 | 
													</span>
 | 
				
			||||||
 | 
													<span>Empty cart</span>
 | 
				
			||||||
 | 
												</span>
 | 
				
			||||||
 | 
											</h1>
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											<div class="drinkCartList">
 | 
				
			||||||
 | 
												@foreach (var cartDrink in CartDrinks)
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													<div class="drinkCartItem">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
														<div class="drinkCartName"><strong>@cartDrink.Name</strong></div>
 | 
				
			||||||
 | 
														<div class="drinkCartQuantity">
 | 
				
			||||||
 | 
															<div class="field has-addons">
 | 
				
			||||||
 | 
																<p class="control">
 | 
				
			||||||
 | 
																	<button class="button is-small is-danger" @onclick="async () => await SubtractQuantity(cartDrink)">
 | 
				
			||||||
 | 
																		<span class="icon"><i class="fad fa-minus"></i></span>
 | 
				
			||||||
 | 
																	</button>
 | 
				
			||||||
 | 
																</p>
 | 
				
			||||||
 | 
																<p class="control">
 | 
				
			||||||
 | 
																	<input class="input is-small has-text-centered" type="text" readonly @bind-value="cartDrink.Quantity" />
 | 
				
			||||||
 | 
																</p>
 | 
				
			||||||
 | 
																<p class="control">
 | 
				
			||||||
 | 
																	<button class="button is-small is-success" @onclick="async () => await AddQuantity(cartDrink)">
 | 
				
			||||||
 | 
																		<span class="icon"><i class="fad fa-plus"></i></span>
 | 
				
			||||||
 | 
																	</button>
 | 
				
			||||||
 | 
																</p>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
														<div class="drinkCartCross has-text-centered">
 | 
				
			||||||
 | 
															<span class="icon">
 | 
				
			||||||
 | 
																<i class="fad fa-times"></i>
 | 
				
			||||||
 | 
															</span>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
														<div class="drinkCartPrice has-text-centered">@cartDrink.Price €</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<hr />
 | 
				
			||||||
 | 
											<EditForm Model="DiscountForm" OnValidSubmit="TryAddDiscount">
 | 
				
			||||||
 | 
												<DataAnnotationsValidator />
 | 
				
			||||||
 | 
												<label class="label" for="discount">
 | 
				
			||||||
 | 
													<span>Any discount?</span>
 | 
				
			||||||
 | 
												</label>
 | 
				
			||||||
 | 
												<div class="field has-addons">
 | 
				
			||||||
 | 
													<p class="control is-expanded has-icons-left">
 | 
				
			||||||
 | 
														<span class="icon is-left"><i class="fad fa-tags"></i></span>
 | 
				
			||||||
 | 
														<input class="input" type="text" id="discount" placeholder="discount code" @onchange="OnChangeDiscountCode">
 | 
				
			||||||
 | 
													</p>
 | 
				
			||||||
 | 
													<p class="control">
 | 
				
			||||||
 | 
														<button type="submit" class="button is-primary has-icons-left">
 | 
				
			||||||
 | 
															<span class="icon is-left">
 | 
				
			||||||
 | 
																<i class="fad fa-badge-dollar"></i>
 | 
				
			||||||
 | 
															</span>
 | 
				
			||||||
 | 
															<span>Add discount</span>
 | 
				
			||||||
 | 
														</button>
 | 
				
			||||||
 | 
													</p>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<p class="help is-danger">
 | 
				
			||||||
 | 
													<ValidationMessage For="() => DiscountForm.DiscountCode" />
 | 
				
			||||||
 | 
													@InvalidDiscountCodeError
 | 
				
			||||||
 | 
												</p>
 | 
				
			||||||
 | 
												<ul>
 | 
				
			||||||
 | 
													@foreach (var discountCode in DiscountCodes)
 | 
				
			||||||
 | 
													{
 | 
				
			||||||
 | 
														<li class="has-text-right">
 | 
				
			||||||
 | 
															<span class="tag is-dark">@discountCode.Code</span>
 | 
				
			||||||
 | 
															<span class="tag is-success">-@discountCode.DiscountPercentage %</span>
 | 
				
			||||||
 | 
														</li>
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												</ul>
 | 
				
			||||||
 | 
											</EditForm>
 | 
				
			||||||
 | 
											<hr />
 | 
				
			||||||
 | 
											<div class="level">
 | 
				
			||||||
 | 
												<div class="level-left">
 | 
				
			||||||
 | 
													<h2><strong>Totale price</strong></h2>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div class="level-right">
 | 
				
			||||||
 | 
													<h2>
 | 
				
			||||||
 | 
														<strong>@(Math.Round(TotalPrice, 2)) €</strong>
 | 
				
			||||||
 | 
													</h2>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											<hr />
 | 
				
			||||||
 | 
											<div class="buttons is-right">
 | 
				
			||||||
 | 
												<NavLink href="payment" class="button is-primary has-icons-left">
 | 
				
			||||||
 | 
													<span class="icon"><i class="fad fa-money-bill-wave"></i></span>
 | 
				
			||||||
 | 
													<span>Go to payment</span>
 | 
				
			||||||
 | 
												</NavLink>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										106
									
								
								drinkMe/Client/Pages/Index.razor.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					using Blazored.LocalStorage;
 | 
				
			||||||
 | 
					using drinkMe.Client.Models;
 | 
				
			||||||
 | 
					using drinkMe.Client.Services.Interfaces;
 | 
				
			||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Components;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.ComponentModel.DataAnnotations;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Pages
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public partial class Index : ComponentBase
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							[Inject] ILocalStorageService LocalStorage { get; set; }
 | 
				
			||||||
 | 
							[Inject] IPriceService PriceService { get; set; }
 | 
				
			||||||
 | 
							[Inject] IDataService DataService { get; set; }
 | 
				
			||||||
 | 
							protected List<DrinkViewModel> AvailableDrinks { get; set; } = new List<DrinkViewModel>();
 | 
				
			||||||
 | 
							protected List<DiscountCodeViewModel> DiscountCodes { get; set; } = new List<DiscountCodeViewModel>();
 | 
				
			||||||
 | 
							protected List<DrinkViewModel> CartDrinks { get; set; } = new List<DrinkViewModel>();
 | 
				
			||||||
 | 
							protected string GetDrinksError { get; set; }
 | 
				
			||||||
 | 
							protected string InvalidDiscountCodeError { get; set; }
 | 
				
			||||||
 | 
							protected DiscountForm DiscountForm { get; set; } = new DiscountForm();
 | 
				
			||||||
 | 
							protected float TotalPrice { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							protected override async Task OnInitializedAsync()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var getDrinksResult = await DataService.GetDrinks();
 | 
				
			||||||
 | 
								if (!getDrinksResult.IsValid)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									GetDrinksError = getDrinksResult.ErrorMessage;
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								AvailableDrinks = (List<DrinkViewModel>)getDrinksResult.Data;
 | 
				
			||||||
 | 
								DiscountCodes = await LocalStorage.GetItemAsync<List<DiscountCodeViewModel>>(nameof(DiscountCodes)) ?? new List<DiscountCodeViewModel>();
 | 
				
			||||||
 | 
								CartDrinks = await LocalStorage.GetItemAsync<List<DrinkViewModel>>(nameof(CartDrinks)) ?? new List<DrinkViewModel>();
 | 
				
			||||||
 | 
								if (CartDrinks.Count > 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
 | 
				
			||||||
 | 
									AvailableDrinks.ForEach(ad => ad.IsInTheCart = CartDrinks.Any(cd => cd.Id == ad.Id));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							protected async Task AddQuantity(DrinkViewModel drink)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								drink.Quantity = drink.Quantity is > 0 and < 20 ? ++drink.Quantity : drink.Quantity;
 | 
				
			||||||
 | 
								await LocalStorage.SetItemAsync(nameof(CartDrinks), CartDrinks);
 | 
				
			||||||
 | 
								TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							protected async Task SubtractQuantity(DrinkViewModel drink)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (drink.Quantity - 1 == 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									var availableDrink = AvailableDrinks.First(ad => ad.Id == drink.Id);
 | 
				
			||||||
 | 
									availableDrink.IsInTheCart = false;
 | 
				
			||||||
 | 
									CartDrinks.Remove(drink);
 | 
				
			||||||
 | 
									await LocalStorage.SetItemAsync(nameof(CartDrinks), CartDrinks);
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								drink.Quantity = drink.Quantity is > 1 and < 21 ? --drink.Quantity : drink.Quantity;
 | 
				
			||||||
 | 
								await LocalStorage.SetItemAsync(nameof(CartDrinks), CartDrinks);
 | 
				
			||||||
 | 
								TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							protected async Task AddToCart(DrinkViewModel drink)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								drink.IsInTheCart = true;
 | 
				
			||||||
 | 
								CartDrinks.Add(drink);
 | 
				
			||||||
 | 
								await LocalStorage.SetItemAsync(nameof(CartDrinks), CartDrinks);
 | 
				
			||||||
 | 
								TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							protected async Task TryAddDiscount()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								InvalidDiscountCodeError = default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (DiscountCodes.Any(dc => dc.Code == DiscountForm.DiscountCode))
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									InvalidDiscountCodeError = "Discount code already added.";
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var validationResult = await DataService.IsValidDiscountCode(DiscountForm.DiscountCode);
 | 
				
			||||||
 | 
								if (!validationResult.IsValid)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									InvalidDiscountCodeError = validationResult.ErrorMessage;
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								var discount = validationResult.Data as DiscountCodeViewModel;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								DiscountCodes.Add(discount);
 | 
				
			||||||
 | 
								await LocalStorage.SetItemAsync(nameof(DiscountCodes), DiscountCodes);
 | 
				
			||||||
 | 
								TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							protected void OnChangeDiscountCode(ChangeEventArgs changeEvent)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								InvalidDiscountCodeError = default;
 | 
				
			||||||
 | 
								DiscountForm.DiscountCode = (string)changeEvent.Value;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										172
									
								
								drinkMe/Client/Pages/Payment.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,172 @@
 | 
				
			|||||||
 | 
					@page "/payment"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<PurchaseSteps PurchaseStep="PurchaseStep.PaymentSetup" />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<section class="section">
 | 
				
			||||||
 | 
						<div class="container">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<div class="columns">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<div class="column is-half">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									<div class="box">
 | 
				
			||||||
 | 
										@if (CartDrinks.Count == 0)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											<h1 class="has-text-centered">
 | 
				
			||||||
 | 
												<span class="icon-text">
 | 
				
			||||||
 | 
													<span class="icon">
 | 
				
			||||||
 | 
														<i class="fad fa-shopping-cart"></i>
 | 
				
			||||||
 | 
													</span>
 | 
				
			||||||
 | 
													<span>Empty cart</span>
 | 
				
			||||||
 | 
												</span>
 | 
				
			||||||
 | 
											</h1>
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											<div class="drinkCartList">
 | 
				
			||||||
 | 
												@foreach (var cartDrink in CartDrinks)
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													<div class="drinkCartPItem">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
														<div class="drinkCartName"><strong>@cartDrink.Name</strong></div>
 | 
				
			||||||
 | 
														<div class="drinkCartQuantity has-text-centered">
 | 
				
			||||||
 | 
															<div class="field">
 | 
				
			||||||
 | 
																<p class="control">
 | 
				
			||||||
 | 
																	@cartDrink.Quantity
 | 
				
			||||||
 | 
																</p>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
														<div class="drinkCartCross has-text-centered">
 | 
				
			||||||
 | 
															<span class="icon">
 | 
				
			||||||
 | 
																<i class="fad fa-times"></i>
 | 
				
			||||||
 | 
															</span>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
														<div class="drinkCartPrice has-text-centered">@cartDrink.Price €</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
											if (DiscountCodes.Count > 0)
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												<hr />
 | 
				
			||||||
 | 
												<ul>
 | 
				
			||||||
 | 
													@foreach (var discountCode in DiscountCodes)
 | 
				
			||||||
 | 
													{
 | 
				
			||||||
 | 
														<li class="has-text-right">
 | 
				
			||||||
 | 
															<span class="tag is-dark">@discountCode.Code</span>
 | 
				
			||||||
 | 
															<span class="tag is-success">-@discountCode.DiscountPercentage %</span>
 | 
				
			||||||
 | 
														</li>
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												</ul>
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											<hr />
 | 
				
			||||||
 | 
											<div class="level">
 | 
				
			||||||
 | 
												<div class="level-left">
 | 
				
			||||||
 | 
													<h2><strong>Totale price</strong></h2>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div class="level-right">
 | 
				
			||||||
 | 
													<h2>
 | 
				
			||||||
 | 
														<strong>@(Math.Round(TotalPrice, 2)) €</strong>
 | 
				
			||||||
 | 
													</h2>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								<div class="column is-half">
 | 
				
			||||||
 | 
									<div class="box">
 | 
				
			||||||
 | 
										<EditForm Model="CreditCardForm" OnValidSubmit="Pay">
 | 
				
			||||||
 | 
											<DataAnnotationsValidator />
 | 
				
			||||||
 | 
											<InputRadioGroup Name="PaymentMethod" @bind-Value="PaymentMethod">
 | 
				
			||||||
 | 
												<div class="field">
 | 
				
			||||||
 | 
													<div class="control">
 | 
				
			||||||
 | 
														<label class="radio">
 | 
				
			||||||
 | 
															<InputRadio Name="PaymentMethod" Value="PaymentMethod.Cash" disabled="@(TotalPrice > 10f)" />
 | 
				
			||||||
 | 
															<span class="icon-text"><span class="icon"><i class="fad fa-money-bill-wave"></i></span> <span>I'm going with cash</span></span>
 | 
				
			||||||
 | 
														</label>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div class="is-divider" data-content="OR"></div>
 | 
				
			||||||
 | 
												<div class="field">
 | 
				
			||||||
 | 
													<div class="control">
 | 
				
			||||||
 | 
														<label class="radio">
 | 
				
			||||||
 | 
															<InputRadio Name="PaymentMethod" Value="PaymentMethod.CreditCard" />
 | 
				
			||||||
 | 
															<span class="icon-text"><span class="icon"><i class="fad fa-credit-card-front"></i></span> <span>Here goes the card</span></span>
 | 
				
			||||||
 | 
														</label>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
											</InputRadioGroup>
 | 
				
			||||||
 | 
											<fieldset class="@VUtilities.IfTrueThen(PaymentMethod == PaymentMethod.Cash, "is-hidden")" disabled="@(PaymentMethod != PaymentMethod.CreditCard)">
 | 
				
			||||||
 | 
												<div class="field">
 | 
				
			||||||
 | 
													<label class="label">Credit card number</label>
 | 
				
			||||||
 | 
													<div class="control has-icons-left">
 | 
				
			||||||
 | 
														<span class="icon is-left"><i class="fad fa-credit-card-front"></i></span>
 | 
				
			||||||
 | 
														<input @bind-value="CreditCardForm.Number" class="input" placeholder="">
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
													<p class="help is-danger">
 | 
				
			||||||
 | 
														<ValidationMessage For="() => CreditCardForm.Number" />
 | 
				
			||||||
 | 
													</p>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												<div class="columns">
 | 
				
			||||||
 | 
													<div class="column is-half">
 | 
				
			||||||
 | 
														<label class="label">Expiration month / year</label>
 | 
				
			||||||
 | 
														<div class="field has-addons has-addons-right">
 | 
				
			||||||
 | 
															<div class="control">
 | 
				
			||||||
 | 
																<input @bind-value="CreditCardForm.ExpirationMonth" class="input has-text-centered" placeholder="01">
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
															<div class="control">
 | 
				
			||||||
 | 
																<input class="input has-text-centered" value="/" readonly disabled>
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
															<div class="control">
 | 
				
			||||||
 | 
																<input @bind-value="CreditCardForm.ExpirationYear" class="input has-text-centered" placeholder="@((DateTime.Now.Year + 1).ToString().Substring(2,2))">
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
														<p class="help is-danger">
 | 
				
			||||||
 | 
															<ValidationMessage For="() => CreditCardForm.ExpirationMonth" />
 | 
				
			||||||
 | 
															<ValidationMessage For="() => CreditCardForm.ExpirationYear" />
 | 
				
			||||||
 | 
														</p>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
													<div class="column is-half">
 | 
				
			||||||
 | 
														<div class="field">
 | 
				
			||||||
 | 
															<label class="label">CVV code</label>
 | 
				
			||||||
 | 
															<div class="control has-icons-left">
 | 
				
			||||||
 | 
																<span class="icon is-left"><i class="fad fa-key"></i></span>
 | 
				
			||||||
 | 
																<input type="text" @bind-value="CreditCardForm.CVVCode" class="input has-text-centered" placeholder="***" />
 | 
				
			||||||
 | 
															</div>
 | 
				
			||||||
 | 
															<p class="help is-danger">
 | 
				
			||||||
 | 
																<ValidationMessage For="() => CreditCardForm.CVVCode" />
 | 
				
			||||||
 | 
															</p>
 | 
				
			||||||
 | 
														</div>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												</div>
 | 
				
			||||||
 | 
												@if (PaymentMethod == PaymentMethod.CreditCard)
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													<div class="field has-text-right">
 | 
				
			||||||
 | 
														<button type="submit" class="button is-primary has-icons-left">
 | 
				
			||||||
 | 
															<span class="icon"><i class="fad fa-credit-card-blank"></i></span>
 | 
				
			||||||
 | 
															<span>Pay</span>
 | 
				
			||||||
 | 
														</button>
 | 
				
			||||||
 | 
													</div>
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											</fieldset>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										</EditForm>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										@if (PaymentMethod == PaymentMethod.Cash)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											<div class="field mt-5 has-text-right">
 | 
				
			||||||
 | 
												<button class="button is-primary has-icons-left" @onclick="Pay">
 | 
				
			||||||
 | 
													<span class="icon"><i class="fad fa-money-bill-wave"></i></span>
 | 
				
			||||||
 | 
													<span>Pay at checkout</span>
 | 
				
			||||||
 | 
												</button>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
								</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										69
									
								
								drinkMe/Client/Pages/Payment.razor.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					using Blazored.LocalStorage;
 | 
				
			||||||
 | 
					using drinkMe.Client.Models;
 | 
				
			||||||
 | 
					using drinkMe.Client.Services.Interfaces;
 | 
				
			||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Components;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Pages
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public partial class Payment : ComponentBase
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							[Inject] ILocalStorageService LocalStorage { get; set; }
 | 
				
			||||||
 | 
							[Inject] IPriceService PriceService { get; set; }
 | 
				
			||||||
 | 
							[Inject] IPaymentService PaymentService { get; set; }
 | 
				
			||||||
 | 
							[Inject] NavigationManager Navigation { get; set; }
 | 
				
			||||||
 | 
							protected List<DrinkViewModel> CartDrinks { get; set; } = new List<DrinkViewModel>();
 | 
				
			||||||
 | 
							protected List<DiscountCodeViewModel> DiscountCodes { get; set; } = new List<DiscountCodeViewModel>();
 | 
				
			||||||
 | 
							protected CreditCardForm CreditCardForm { get; set; } = new CreditCardForm();
 | 
				
			||||||
 | 
							protected PaymentMethod PaymentMethod { get; set; } = PaymentMethod.Undefined;
 | 
				
			||||||
 | 
							protected float TotalPrice { get; set; }
 | 
				
			||||||
 | 
							protected string PaymentError { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							protected override async Task OnInitializedAsync()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								CartDrinks = await LocalStorage.GetItemAsync<List<DrinkViewModel>>(nameof(CartDrinks));
 | 
				
			||||||
 | 
								DiscountCodes = await LocalStorage.GetItemAsync<List<DiscountCodeViewModel>>(nameof(DiscountCodes)) ?? new List<DiscountCodeViewModel>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								TotalPrice = PriceService.GetTotalPrice(DiscountCodes, CartDrinks);
 | 
				
			||||||
 | 
								if (TotalPrice > 10f)
 | 
				
			||||||
 | 
									PaymentMethod = PaymentMethod.CreditCard;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							protected async Task Pay()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								PaymentError = default;
 | 
				
			||||||
 | 
								var paymentCart = new PurchaseCart();
 | 
				
			||||||
 | 
								paymentCart.Discounts = DiscountCodes;
 | 
				
			||||||
 | 
								paymentCart.PurchasingItems = CartDrinks.Select(cd => new CartItem
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									Id = cd.Id,
 | 
				
			||||||
 | 
									Quantity = cd.Quantity
 | 
				
			||||||
 | 
								}).ToList();
 | 
				
			||||||
 | 
								paymentCart.IsPayedWithCash = PaymentMethod == PaymentMethod.Cash;
 | 
				
			||||||
 | 
								if (!paymentCart.IsPayedWithCash)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									paymentCart.CreditCardNumber = CreditCardForm.Number;
 | 
				
			||||||
 | 
									paymentCart.CreditCardExpirationMonth = CreditCardForm.ExpirationMonth;
 | 
				
			||||||
 | 
									paymentCart.CreditCardExpirationYear = CreditCardForm.ExpirationYear;
 | 
				
			||||||
 | 
									paymentCart.CreditCardCVVCode = CreditCardForm.CVVCode;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								var paymentResult = await PaymentService.Pay(paymentCart);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!paymentResult.IsValid)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									PaymentError = paymentResult.ErrorMessage;
 | 
				
			||||||
 | 
									return;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								await LocalStorage.RemoveItemAsync(nameof(CartDrinks));
 | 
				
			||||||
 | 
								await LocalStorage.RemoveItemAsync(nameof(DiscountCodes));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								Navigation.NavigateTo("done");
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										39
									
								
								drinkMe/Client/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,39 @@
 | 
				
			|||||||
 | 
					using drinkMe.Client.Services;
 | 
				
			||||||
 | 
					using drinkMe.Client.Services.Interfaces;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					using Blazored.LocalStorage;
 | 
				
			||||||
 | 
					using System.Text.Json;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class Program
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public static async Task Main(string[] args)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var builder = WebAssemblyHostBuilder.CreateDefault(args);
 | 
				
			||||||
 | 
								builder.RootComponents.Add<App>("#app");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) })
 | 
				
			||||||
 | 
									.AddScoped<IDataService, DataService>()
 | 
				
			||||||
 | 
									.AddScoped<IPriceService, PriceService>()
 | 
				
			||||||
 | 
									.AddScoped<IPaymentService, PaymentService>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								builder.Services.AddBlazoredLocalStorage(config =>
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									config.JsonSerializerOptions.WriteIndented = false;
 | 
				
			||||||
 | 
									config.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
 | 
				
			||||||
 | 
									config.JsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								await builder.Build().RunAsync();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								drinkMe/Client/Properties/launchSettings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "iisSettings": {
 | 
				
			||||||
 | 
					    "windowsAuthentication": false,
 | 
				
			||||||
 | 
					    "anonymousAuthentication": true,
 | 
				
			||||||
 | 
					    "iisExpress": {
 | 
				
			||||||
 | 
					      "applicationUrl": "http://localhost:14962",
 | 
				
			||||||
 | 
					      "sslPort": 44321
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "profiles": {
 | 
				
			||||||
 | 
					    "IIS Express": {
 | 
				
			||||||
 | 
					      "commandName": "IISExpress",
 | 
				
			||||||
 | 
					      "launchBrowser": true,
 | 
				
			||||||
 | 
					      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
 | 
				
			||||||
 | 
					      "environmentVariables": {
 | 
				
			||||||
 | 
					        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "drinkMe": {
 | 
				
			||||||
 | 
					      "commandName": "Project",
 | 
				
			||||||
 | 
					      "dotnetRunMessages": "true",
 | 
				
			||||||
 | 
					      "launchBrowser": true,
 | 
				
			||||||
 | 
					      "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
 | 
				
			||||||
 | 
					      "applicationUrl": "https://localhost:5001;http://localhost:5000",
 | 
				
			||||||
 | 
					      "environmentVariables": {
 | 
				
			||||||
 | 
					        "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										6
									
								
								drinkMe/Client/SCSS/all.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					@import "variables.scss";
 | 
				
			||||||
 | 
					@import "mixins.scss";
 | 
				
			||||||
 | 
					@import "framework-override.scss";
 | 
				
			||||||
 | 
					@import "neomorph.scss";
 | 
				
			||||||
 | 
					@import "base.scss";
 | 
				
			||||||
 | 
					@import "chooseDrinks.scss";
 | 
				
			||||||
							
								
								
									
										41
									
								
								drinkMe/Client/SCSS/base.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					html {
 | 
				
			||||||
 | 
						scrollbar-width: thin;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*, ::after, ::before {
 | 
				
			||||||
 | 
						scrollbar-width: inherit;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar {
 | 
				
			||||||
 | 
						width: 8px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-button {
 | 
				
			||||||
 | 
						width: 8px;
 | 
				
			||||||
 | 
						height: 5px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-track {
 | 
				
			||||||
 | 
						background: transparent;
 | 
				
			||||||
 | 
						border: thin solid transparent;
 | 
				
			||||||
 | 
						box-shadow: none;
 | 
				
			||||||
 | 
						border-radius: 10px;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-thumb {
 | 
				
			||||||
 | 
						border: thin solid transparent;
 | 
				
			||||||
 | 
						border-radius: 10px;
 | 
				
			||||||
 | 
						background: var(--primary-color);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					body {
 | 
				
			||||||
 | 
						background-image: url("/images/background.jpg");
 | 
				
			||||||
 | 
						background-size: cover;
 | 
				
			||||||
 | 
						min-height: 100vh
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.loading {
 | 
				
			||||||
 | 
						height: 100vh;
 | 
				
			||||||
 | 
						justify-content: center;
 | 
				
			||||||
 | 
						flex-direction: column;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										55
									
								
								drinkMe/Client/SCSS/chooseDrinks.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,55 @@
 | 
				
			|||||||
 | 
					.drinkCart {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&List {
 | 
				
			||||||
 | 
							display: flex;
 | 
				
			||||||
 | 
							flex-direction: column;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Item {
 | 
				
			||||||
 | 
							display: grid;
 | 
				
			||||||
 | 
							grid-template-areas: "drinkName drinkQuantity drinkCross drinkPrice";
 | 
				
			||||||
 | 
							grid-template-columns: 1fr minmax(100px, 20%) 5% 10%;
 | 
				
			||||||
 | 
							grid-template-rows: 100%;
 | 
				
			||||||
 | 
							grid-gap: 5px;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:not(:last-child) {
 | 
				
			||||||
 | 
								margin-bottom: 1rem;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&PItem {
 | 
				
			||||||
 | 
							display: grid;
 | 
				
			||||||
 | 
							grid-template-areas: "drinkName drinkQuantity drinkCross drinkPrice";
 | 
				
			||||||
 | 
							grid-template-columns: 1fr 10% 5% 10%;
 | 
				
			||||||
 | 
							grid-template-rows: 100%;
 | 
				
			||||||
 | 
							grid-gap: 5px;
 | 
				
			||||||
 | 
							align-items: center;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:not(:last-child) {
 | 
				
			||||||
 | 
								margin-bottom: 1rem;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Name {
 | 
				
			||||||
 | 
							grid-area: drinkName;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Cross {
 | 
				
			||||||
 | 
							grid-area: drinkCross;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Quantity {
 | 
				
			||||||
 | 
							grid-area: drinkQuantity;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Price {
 | 
				
			||||||
 | 
							grid-area: drinkPrice;
 | 
				
			||||||
 | 
							white-space: nowrap;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.column>.box>.title{
 | 
				
			||||||
 | 
						padding: 10%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										16
									
								
								drinkMe/Client/SCSS/framework-override.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,16 @@
 | 
				
			|||||||
 | 
					html {
 | 
				
			||||||
 | 
						overflow-y: auto;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					.steps {
 | 
				
			||||||
 | 
						list-style-type: none !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@include MediaQuery(phone) {
 | 
				
			||||||
 | 
						.mt-2-mobile {
 | 
				
			||||||
 | 
							margin-top: .5rem !important;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.control.has-icons-left .icon, .control.has-icons-right .icon {
 | 
				
			||||||
 | 
						z-index: 5;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								drinkMe/Client/SCSS/mixins.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					//MEDIA QUERY MANAGER
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*$breakpoint argument choices:
 | 
				
			||||||
 | 
					- phone
 | 
				
			||||||
 | 
					- tab-port
 | 
				
			||||||
 | 
					- tab-land
 | 
				
			||||||
 | 
					- desk
 | 
				
			||||||
 | 
					- big-desktop
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@mixin MediaQuery($breakpoint) {
 | 
				
			||||||
 | 
						@if $breakpoint==phone {
 | 
				
			||||||
 | 
							@media screen and (max-width: 768px) {
 | 
				
			||||||
 | 
								@content
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@if $breakpoint==tab-p {
 | 
				
			||||||
 | 
							@media screen and (min-width: 768px) and (max-width: 900px) {
 | 
				
			||||||
 | 
								@content
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@if $breakpoint==tab-l {
 | 
				
			||||||
 | 
							@media screen and (min-width: 901px) and (max-width: 1200px) {
 | 
				
			||||||
 | 
								@content
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@if $breakpoint==laptop {
 | 
				
			||||||
 | 
							@media screen and (min-width: 1201px) and (max-width: 1366px) {
 | 
				
			||||||
 | 
								@content
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@if $breakpoint==desk {
 | 
				
			||||||
 | 
							@media screen and (min-width: 1201px) and (max-width: 1800px) {
 | 
				
			||||||
 | 
								@content
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@if $breakpoint==big-d {
 | 
				
			||||||
 | 
							@media screen and (min-width: 1801px) and (max-width: 4000px) {
 | 
				
			||||||
 | 
								@content
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										155
									
								
								drinkMe/Client/SCSS/neomorph.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,155 @@
 | 
				
			|||||||
 | 
					.neomorph {
 | 
				
			||||||
 | 
						box-shadow: -8px -8px 16px var(--light-shadow), 8px 8px 16px var(--dark-shadow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Small {
 | 
				
			||||||
 | 
							box-shadow: -6px -6px 12px var(--light-shadow), 6px 6px 12px var(--dark-shadow);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&XSmall {
 | 
				
			||||||
 | 
							box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&XXSmall {
 | 
				
			||||||
 | 
							box-shadow: -2px -2px 4px var(--light-shadow), 2px 2px 4px var(--dark-shadow);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Bottom {
 | 
				
			||||||
 | 
							filter: drop-shadow(8px 8px 14px var(--primary-color-dark));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Inset {
 | 
				
			||||||
 | 
							box-shadow: inset 8px 8px 16px var(--dark-shadow), inset -8px -8px 16px var(--light-shadow);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&Small {
 | 
				
			||||||
 | 
								box-shadow: inset 6px 6px 12px var(--dark-shadow), inset -6px -6px 12px var(--light-shadow);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&XSmall {
 | 
				
			||||||
 | 
								box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&XXSmall {
 | 
				
			||||||
 | 
								box-shadow: inset 2px 2px 4px var(--dark-shadow), inset -2px -2px 4px var(--light-shadow);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.neo {
 | 
				
			||||||
 | 
						&Btn {
 | 
				
			||||||
 | 
							background: linear-gradient(145deg,var(--primary-gradiend-light),var(--primary-gradiend-dark));
 | 
				
			||||||
 | 
							box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow);
 | 
				
			||||||
 | 
							border: none !important;
 | 
				
			||||||
 | 
							-webkit-backface-visibility: hidden;
 | 
				
			||||||
 | 
							backface-visibility: hidden;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:focus {
 | 
				
			||||||
 | 
								box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow) !important;
 | 
				
			||||||
 | 
								border: none !important;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&InsetPlain {
 | 
				
			||||||
 | 
								background: linear-gradient(145deg,var(--primary-gradiend-dark),var(--primary-gradiend-light));
 | 
				
			||||||
 | 
								box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow);
 | 
				
			||||||
 | 
								border: none !important;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:focus {
 | 
				
			||||||
 | 
									box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow) !important;
 | 
				
			||||||
 | 
									border: none !important;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&Small {
 | 
				
			||||||
 | 
								background: linear-gradient(145deg,var(--primary-gradiend-light),var(--primary-gradiend-dark));
 | 
				
			||||||
 | 
								box-shadow: -2px -2px 4px var(--light-shadow), 2px 2px 4px var(--dark-shadow);
 | 
				
			||||||
 | 
								border: none !important;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&:focus {
 | 
				
			||||||
 | 
									box-shadow: -2px -2px 4px var(--light-shadow), 2px 2px 4px var(--dark-shadow);
 | 
				
			||||||
 | 
									border: none !important;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:not(:active) {
 | 
				
			||||||
 | 
										box-shadow: -2px -2px 4px var(--light-shadow), 2px 2px 4px var(--dark-shadow);
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&InsetPlain {
 | 
				
			||||||
 | 
									background: linear-gradient(145deg,var(--primary-gradiend-dark),var(--primary-gradiend-light));
 | 
				
			||||||
 | 
									box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow);
 | 
				
			||||||
 | 
									border: none !important;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:focus {
 | 
				
			||||||
 | 
										box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow) !important;
 | 
				
			||||||
 | 
										border: none !important;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&XInsetPlain {
 | 
				
			||||||
 | 
									background: linear-gradient(145deg,var(--primary-gradiend-dark),var(--primary-gradiend-light));
 | 
				
			||||||
 | 
									box-shadow: inset 2px 2px 4px var(--dark-shadow), inset -2px -2px 4px var(--light-shadow);
 | 
				
			||||||
 | 
									border: none !important;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:focus {
 | 
				
			||||||
 | 
										box-shadow: inset 2px 2px 4px var(--dark-shadow), inset -2px -2px 4px var(--light-shadow) !important;
 | 
				
			||||||
 | 
										border: none !important;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								&Plain {
 | 
				
			||||||
 | 
									box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow);
 | 
				
			||||||
 | 
									border: none !important;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									&:focus {
 | 
				
			||||||
 | 
										box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow) !important;
 | 
				
			||||||
 | 
										border: none !important;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&File {
 | 
				
			||||||
 | 
							box-shadow: 0px 0px 0px var(--light-shadow), 0px 0px 0px var(--dark-shadow) !important;
 | 
				
			||||||
 | 
							transition: all .2s linear;
 | 
				
			||||||
 | 
							-webkit-backface-visibility: hidden !important;
 | 
				
			||||||
 | 
							backface-visibility: hidden !important;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							@include MediaQuery(phone) {
 | 
				
			||||||
 | 
								box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow) !important;
 | 
				
			||||||
 | 
								background: var(--primary-color) !important;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:hover {
 | 
				
			||||||
 | 
								box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow) !important;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&.isSelected {
 | 
				
			||||||
 | 
								background: linear-gradient(145deg,var(--primary-gradiend-dark),var(--primary-gradiend-light));
 | 
				
			||||||
 | 
								box-shadow: inset 3px 3px 6px var(--dark-shadow),inset -3px -3px 6px var(--light-shadow) !important;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&.is-active, &.active {
 | 
				
			||||||
 | 
								box-shadow: inset 3px 3px 6px var(--dark-shadow),inset -3px -3px 6px var(--light-shadow) !important;
 | 
				
			||||||
 | 
								color: var(--black) !important;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Input {
 | 
				
			||||||
 | 
							box-shadow: inset 2px 2px 4px var(--dark-shadow),inset -2px -2px 4px var(--light-shadow) !important;
 | 
				
			||||||
 | 
							background: linear-gradient(145deg,var(--primary-gradiend-dark),var(--primary-gradiend-light));
 | 
				
			||||||
 | 
							border: none !important;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:focus {
 | 
				
			||||||
 | 
								border: none !important;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						&Select > select {
 | 
				
			||||||
 | 
							box-shadow: inset 2px 2px 4px var(--dark-shadow),inset -2px -2px 4px var(--light-shadow) !important;
 | 
				
			||||||
 | 
							background: linear-gradient(145deg,var(--primary-gradiend-dark),var(--primary-gradiend-light)) !important;
 | 
				
			||||||
 | 
							border: none !important;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							&:focus {
 | 
				
			||||||
 | 
								border: none !important;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										56
									
								
								drinkMe/Client/SCSS/variables.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,56 @@
 | 
				
			|||||||
 | 
					$main-pc: hsl(25,84,88); //#fbe9d7;
 | 
				
			||||||
 | 
					$main-gradient-light: hsl(25,84,92);
 | 
				
			||||||
 | 
					$main-gradient-dark: hsl(25,84,84);
 | 
				
			||||||
 | 
					$main-light-pc: lighten($main-pc,15%);
 | 
				
			||||||
 | 
					$main-dark-pc: darken($main-pc,25%);
 | 
				
			||||||
 | 
					$main-sc: #f6d5f7;
 | 
				
			||||||
 | 
					$main-light-sc: lighten($main-sc,15%);
 | 
				
			||||||
 | 
					$main-dark-sc: darken($main-sc,15%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$icon-primary: hsl(0,96,25);
 | 
				
			||||||
 | 
					$icon-secondary: hsl(0,100,55);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$text-color: darken($main-pc,70%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$black: hsl(0, 0%, 4%) !default;
 | 
				
			||||||
 | 
					$black-bis: hsl(0, 0%, 7%) !default;
 | 
				
			||||||
 | 
					$black-ter: hsl(0, 0%, 14%) !default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$grey-darker: hsl(0, 0%, 21%) !default;
 | 
				
			||||||
 | 
					$grey-dark: hsl(0, 0%, 29%) !default;
 | 
				
			||||||
 | 
					$grey: hsl(0, 0%, 48%) !default;
 | 
				
			||||||
 | 
					$grey-light: hsl(0, 0%, 71%) !default;
 | 
				
			||||||
 | 
					$grey-lighter: hsl(0, 0%, 86%) !default;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					$white-ter: hsl(0, 4%, 96%) !default;
 | 
				
			||||||
 | 
					$white-bis: hsl(0, 4%, 98%) !default;
 | 
				
			||||||
 | 
					$white: hsl(0, 4%, 99.8%) !default;
 | 
				
			||||||
 | 
					$danger: hsl(0, 82%, 91%);
 | 
				
			||||||
 | 
					$warning: hsl(48, 82%, 91%);
 | 
				
			||||||
 | 
					$info: hsl(196, 82%, 91%);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:root {
 | 
				
			||||||
 | 
						--background: $main-pc;
 | 
				
			||||||
 | 
						--text-color: $text-color;
 | 
				
			||||||
 | 
						--black: $black;
 | 
				
			||||||
 | 
						--black-bis: $black-bis;
 | 
				
			||||||
 | 
						--black-ter: $black-ter;
 | 
				
			||||||
 | 
						--white: $white;
 | 
				
			||||||
 | 
						--primary-color: $main-pc;
 | 
				
			||||||
 | 
						--primary-color-light: $main-light-pc;
 | 
				
			||||||
 | 
						--primary-color-dark: $main-dark-pc;
 | 
				
			||||||
 | 
						--primary-gradiend-light: $main-gradient-light;
 | 
				
			||||||
 | 
						--primary-gradiend-dark: $main-gradient-dark;
 | 
				
			||||||
 | 
						--secondary-color: $main-sc;
 | 
				
			||||||
 | 
						--secondary-color-light: $main-light-sc;
 | 
				
			||||||
 | 
						--secondary-color-dark: $main-dark-sc;
 | 
				
			||||||
 | 
						--light-shadow: rgba($main-light-pc, .5);
 | 
				
			||||||
 | 
						--dark-shadow: rgba($main-dark-pc, .5);
 | 
				
			||||||
 | 
					/*	--fa-primary-color: $text-color;
 | 
				
			||||||
 | 
						--fa-secondary-color: $main-dark-pc;
 | 
				
			||||||
 | 
						--fa-primary-opacity: 0.80;
 | 
				
			||||||
 | 
						--fa-secondary-opacity: 0.80;*/
 | 
				
			||||||
 | 
						--danger-color: $danger;
 | 
				
			||||||
 | 
						--warning-color: $warning;
 | 
				
			||||||
 | 
						--info-color: $info;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								drinkMe/Client/Services/DataService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					using collAnon.Pub.Shared;
 | 
				
			||||||
 | 
					using drinkMe.Client.Services.Interfaces;
 | 
				
			||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Text.Json;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class DataService : IDataService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							readonly HttpClient HttpClient;
 | 
				
			||||||
 | 
							public DataService(HttpClient httpClient)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								HttpClient = httpClient;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public async Task<WebResult> IsValidDiscountCode(string code)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var result = new WebResult();
 | 
				
			||||||
 | 
								var httpResponse = await HttpClient.GetAsync($"api/Drinks/{nameof(IsValidDiscountCode)}?{nameof(code)}={code}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!httpResponse.IsSuccessStatusCode)
 | 
				
			||||||
 | 
									return result.Invalidate(JsonSerializer.Deserialize<WebResult>(await httpResponse.Content.ReadAsStringAsync(), new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								result.Data = JsonSerializer.Deserialize<DiscountCodeViewModel>(await httpResponse.Content.ReadAsStringAsync(), new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public async Task<WebResult> GetDrinks()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var result = new WebResult();
 | 
				
			||||||
 | 
								var httpResponse = await HttpClient.GetAsync($"api/Drinks/{nameof(GetDrinks)}");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!httpResponse.IsSuccessStatusCode)
 | 
				
			||||||
 | 
									return result.Invalidate(JsonSerializer.Deserialize<WebResult>(await httpResponse.Content.ReadAsStringAsync(), new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								result.Data = JsonSerializer.Deserialize<List<DrinkViewModel>>(await httpResponse.Content.ReadAsStringAsync(), new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								drinkMe/Client/Services/Interfaces/IDataService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					using collAnon.Pub.Shared;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Services.Interfaces
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public interface IDataService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Task<WebResult> GetDrinks();
 | 
				
			||||||
 | 
							Task<WebResult> IsValidDiscountCode(string code);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								drinkMe/Client/Services/Interfaces/IPaymentService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					using collAnon.Pub.Shared;
 | 
				
			||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Services.Interfaces
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public interface IPaymentService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Task<WebResult> Pay(PurchaseCart purchaseCart);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								drinkMe/Client/Services/Interfaces/IPriceService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Services.Interfaces
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public interface IPriceService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							float GetTotalPrice(List<DiscountCodeViewModel> discountCodes, List<DrinkViewModel> drinks);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										33
									
								
								drinkMe/Client/Services/PaymentService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,33 @@
 | 
				
			|||||||
 | 
					using collAnon.Pub.Shared;
 | 
				
			||||||
 | 
					using drinkMe.Client.Services.Interfaces;
 | 
				
			||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Net.Http;
 | 
				
			||||||
 | 
					using System.Net.Http.Json;
 | 
				
			||||||
 | 
					using System.Text.Json;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class PaymentService : IPaymentService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							readonly HttpClient HttpClient;
 | 
				
			||||||
 | 
							public PaymentService(HttpClient httpClient)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								HttpClient = httpClient;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public async Task<WebResult> Pay(PurchaseCart purchaseCart)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var result = new WebResult();
 | 
				
			||||||
 | 
								var httpResponse = await HttpClient.PostAsync($"api/Drinks/{nameof(Pay)}", JsonContent.Create(purchaseCart));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (!httpResponse.IsSuccessStatusCode)
 | 
				
			||||||
 | 
									return result.Invalidate(JsonSerializer.Deserialize<WebResult>(await httpResponse.Content.ReadAsStringAsync(), new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										34
									
								
								drinkMe/Client/Services/PriceService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					using Blazored.LocalStorage;
 | 
				
			||||||
 | 
					using drinkMe.Client.Services.Interfaces;
 | 
				
			||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class PriceService : IPriceService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public float GetTotalPrice(List<DiscountCodeViewModel> discountCodes, List<DrinkViewModel> cartDrinks)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var total = default(float);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if (discountCodes.Count == 0)
 | 
				
			||||||
 | 
									foreach (var cartDrink in cartDrinks)
 | 
				
			||||||
 | 
										total += cartDrink.Price * cartDrink.Quantity;
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									foreach (var cartDrink in cartDrinks)
 | 
				
			||||||
 | 
										if (discountCodes.Any(d => d.ApplicableProducts.Contains(cartDrink.Id)))
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											var discountPercentage = discountCodes.First(d => d.ApplicableProducts.Contains(cartDrink.Id)).DiscountPercentage / 100;
 | 
				
			||||||
 | 
											var discountedPricePortion = cartDrink.Price * discountPercentage;
 | 
				
			||||||
 | 
											total += (cartDrink.Price - discountedPricePortion) * cartDrink.Quantity;
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										else
 | 
				
			||||||
 | 
											total += cartDrink.Price * cartDrink.Quantity;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								return total;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								drinkMe/Client/Shared/MainLayout.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					@inherits LayoutComponentBase
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<NavMenu />
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<section class="section">
 | 
				
			||||||
 | 
							<div class="container">
 | 
				
			||||||
 | 
								@Body
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</section>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
							
								
								
									
										37
									
								
								drinkMe/Client/Shared/NavMenu.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					<nav class="navbar" role="navigation" aria-label="main navigation">
 | 
				
			||||||
 | 
						<div class="navbar-brand">
 | 
				
			||||||
 | 
							<NavLink class="navbar-item" href="/">
 | 
				
			||||||
 | 
								<img src="/images/drinkMe-logo.png" alt="logo">
 | 
				
			||||||
 | 
							</NavLink>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<a role="button" class="navbar-burger @IsActive" aria-label="menu" aria-expanded="false" data-target="navbarBasicExample"
 | 
				
			||||||
 | 
								 @onclick="OpenCloseMenu">
 | 
				
			||||||
 | 
								<span aria-hidden="true"></span>
 | 
				
			||||||
 | 
								<span aria-hidden="true"></span>
 | 
				
			||||||
 | 
								<span aria-hidden="true"></span>
 | 
				
			||||||
 | 
							</a>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						<div id="navbarBasicExample" class="navbar-menu @IsActive">
 | 
				
			||||||
 | 
							<div class="navbar-start">
 | 
				
			||||||
 | 
								<NavLink class="navbar-item" href="/">
 | 
				
			||||||
 | 
									<span class="icon-text">
 | 
				
			||||||
 | 
										<span class="icon"><i class="fad fa-home"></i></span>
 | 
				
			||||||
 | 
										<span>Home</span>
 | 
				
			||||||
 | 
									</span>
 | 
				
			||||||
 | 
								</NavLink>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</nav>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@code{
 | 
				
			||||||
 | 
						string IsActive { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						void OpenCloseMenu()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (string.IsNullOrEmpty(IsActive))
 | 
				
			||||||
 | 
								IsActive = "is-active";
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								IsActive = default;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								drinkMe/Client/_Imports.razor
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					@using System.Net.Http
 | 
				
			||||||
 | 
					@using System.Net.Http.Json
 | 
				
			||||||
 | 
					@using Microsoft.AspNetCore.Components.Forms
 | 
				
			||||||
 | 
					@using Microsoft.AspNetCore.Components.Routing
 | 
				
			||||||
 | 
					@using Microsoft.AspNetCore.Components.Web
 | 
				
			||||||
 | 
					@using Microsoft.AspNetCore.Components.Web.Virtualization
 | 
				
			||||||
 | 
					@using Microsoft.AspNetCore.Components.WebAssembly.Http
 | 
				
			||||||
 | 
					@using Microsoft.JSInterop
 | 
				
			||||||
 | 
					@using drinkMe.Client
 | 
				
			||||||
 | 
					@using drinkMe.Client.Models
 | 
				
			||||||
 | 
					@using drinkMe.Client.Helpers
 | 
				
			||||||
 | 
					@using drinkMe.Client.Components
 | 
				
			||||||
 | 
					@using drinkMe.Client.Shared
 | 
				
			||||||
							
								
								
									
										6
									
								
								drinkMe/Client/compilerconfig.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					[
 | 
				
			||||||
 | 
					  {
 | 
				
			||||||
 | 
					    "outputFile": "wwwroot/css/style.css",
 | 
				
			||||||
 | 
					    "inputFile": "SCSS/all.scss"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					]
 | 
				
			||||||
							
								
								
									
										63
									
								
								drinkMe/Client/compilerconfig.json.defaults
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,63 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "compilers": {
 | 
				
			||||||
 | 
					    "less": {
 | 
				
			||||||
 | 
					      "autoPrefix": "",
 | 
				
			||||||
 | 
					      "cssComb": "none",
 | 
				
			||||||
 | 
					      "ieCompat": true,
 | 
				
			||||||
 | 
					      "strictMath": false,
 | 
				
			||||||
 | 
					      "strictUnits": false,
 | 
				
			||||||
 | 
					      "relativeUrls": true,
 | 
				
			||||||
 | 
					      "rootPath": "",
 | 
				
			||||||
 | 
					      "sourceMapRoot": "",
 | 
				
			||||||
 | 
					      "sourceMapBasePath": "",
 | 
				
			||||||
 | 
					      "sourceMap": false
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "sass": {
 | 
				
			||||||
 | 
					      "autoPrefix": "",
 | 
				
			||||||
 | 
					      "includePath": "",
 | 
				
			||||||
 | 
					      "indentType": "space",
 | 
				
			||||||
 | 
					      "indentWidth": 2,
 | 
				
			||||||
 | 
					      "outputStyle": "nested",
 | 
				
			||||||
 | 
					      "Precision": 5,
 | 
				
			||||||
 | 
					      "relativeUrls": true,
 | 
				
			||||||
 | 
					      "sourceMapRoot": "",
 | 
				
			||||||
 | 
					      "lineFeed": "",
 | 
				
			||||||
 | 
					      "sourceMap": false
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "stylus": {
 | 
				
			||||||
 | 
					      "sourceMap": false
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "babel": {
 | 
				
			||||||
 | 
					      "sourceMap": false
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "coffeescript": {
 | 
				
			||||||
 | 
					      "bare": false,
 | 
				
			||||||
 | 
					      "runtimeMode": "node",
 | 
				
			||||||
 | 
					      "sourceMap": false
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "handlebars": {
 | 
				
			||||||
 | 
					      "root": "",
 | 
				
			||||||
 | 
					      "noBOM": false,
 | 
				
			||||||
 | 
					      "name": "",
 | 
				
			||||||
 | 
					      "namespace": "",
 | 
				
			||||||
 | 
					      "knownHelpersOnly": false,
 | 
				
			||||||
 | 
					      "forcePartial": false,
 | 
				
			||||||
 | 
					      "knownHelpers": [],
 | 
				
			||||||
 | 
					      "commonjs": "",
 | 
				
			||||||
 | 
					      "amd": false,
 | 
				
			||||||
 | 
					      "sourceMap": false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					  "minifiers": {
 | 
				
			||||||
 | 
					    "css": {
 | 
				
			||||||
 | 
					      "enabled": true,
 | 
				
			||||||
 | 
					      "termSemicolons": true,
 | 
				
			||||||
 | 
					      "gzip": false
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "javascript": {
 | 
				
			||||||
 | 
					      "enabled": true,
 | 
				
			||||||
 | 
					      "termSemicolons": true,
 | 
				
			||||||
 | 
					      "gzip": false
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										43
									
								
								drinkMe/Client/drinkMe.Client.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
 | 
					    <TargetFramework>net5.0</TargetFramework>
 | 
				
			||||||
 | 
					    <ServiceWorkerAssetsManifest>service-worker-assets.js</ServiceWorkerAssetsManifest>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <Content Remove="compilerconfig.json" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <_ContentIncludedByDefault Remove="wwwroot\css\style.css" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <None Include="compilerconfig.json" />
 | 
				
			||||||
 | 
					    <None Include="wwwroot\webfonts\fa-duotone-900.svg" />
 | 
				
			||||||
 | 
					    <None Include="wwwroot\webfonts\fa-duotone-900.woff2" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <PackageReference Include="Blazored.LocalStorage" Version="3.0.0" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Blazored.Modal" Version="6.0.1" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="5.0.5" />
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="5.0.5" PrivateAssets="all" />
 | 
				
			||||||
 | 
					    <PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\drinkMe.Client.Models\drinkMe.Client.Models.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\Shared\drinkMe.Shared.csproj" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ServiceWorker Include="wwwroot\service-worker.js" PublishedContent="wwwroot\service-worker.published.js" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <Folder Include="wwwroot\images\drinks\" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
							
								
								
									
										1
									
								
								drinkMe/Client/wwwroot/css/bulma-divider.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1466
									
								
								drinkMe/Client/wwwroot/css/bulma-steps.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										3
									
								
								drinkMe/Client/wwwroot/css/bulma-steps.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										11705
									
								
								drinkMe/Client/wwwroot/css/bulma.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										1
									
								
								drinkMe/Client/wwwroot/css/bulma.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										5605
									
								
								drinkMe/Client/wwwroot/css/duotone.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										5
									
								
								drinkMe/Client/wwwroot/css/duotone.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										7134
									
								
								drinkMe/Client/wwwroot/css/fontawesome.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										5
									
								
								drinkMe/Client/wwwroot/css/fontawesome.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										215
									
								
								drinkMe/Client/wwwroot/css/style.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,215 @@
 | 
				
			|||||||
 | 
					:root {
 | 
				
			||||||
 | 
					  --background: #fadcc7;
 | 
				
			||||||
 | 
					  --text-color: #542707;
 | 
				
			||||||
 | 
					  --black: #0a0a0a;
 | 
				
			||||||
 | 
					  --black-bis: #121212;
 | 
				
			||||||
 | 
					  --black-ter: #242424;
 | 
				
			||||||
 | 
					  --white: #fffefe;
 | 
				
			||||||
 | 
					  --primary-color: #fadcc7;
 | 
				
			||||||
 | 
					  --primary-color-light: white;
 | 
				
			||||||
 | 
					  --primary-color-dark: #f09351;
 | 
				
			||||||
 | 
					  --primary-gradiend-light: #fce8d9;
 | 
				
			||||||
 | 
					  --primary-gradiend-dark: #f8d0b4;
 | 
				
			||||||
 | 
					  --secondary-color: #f6d5f7;
 | 
				
			||||||
 | 
					  --secondary-color-light: white;
 | 
				
			||||||
 | 
					  --secondary-color-dark: #e895eb;
 | 
				
			||||||
 | 
					  --light-shadow: rgba(255, 255, 255, 0.5);
 | 
				
			||||||
 | 
					  --dark-shadow: rgba(240, 147, 81, 0.5);
 | 
				
			||||||
 | 
					  /*	--fa-primary-color: $text-color;
 | 
				
			||||||
 | 
						--fa-secondary-color: $main-dark-pc;
 | 
				
			||||||
 | 
						--fa-primary-opacity: 0.80;
 | 
				
			||||||
 | 
						--fa-secondary-opacity: 0.80;*/
 | 
				
			||||||
 | 
					  --danger-color: #fbd5d5;
 | 
				
			||||||
 | 
					  --warning-color: #fbf3d5;
 | 
				
			||||||
 | 
					  --info-color: #d5f1fb; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*$breakpoint argument choices:
 | 
				
			||||||
 | 
					- phone
 | 
				
			||||||
 | 
					- tab-port
 | 
				
			||||||
 | 
					- tab-land
 | 
				
			||||||
 | 
					- desk
 | 
				
			||||||
 | 
					- big-desktop
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					html {
 | 
				
			||||||
 | 
					  overflow-y: auto; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.steps {
 | 
				
			||||||
 | 
					  list-style-type: none !important; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media screen and (max-width: 768px) {
 | 
				
			||||||
 | 
					  .mt-2-mobile {
 | 
				
			||||||
 | 
					    margin-top: .5rem !important; } }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.control.has-icons-left .icon, .control.has-icons-right .icon {
 | 
				
			||||||
 | 
					  z-index: 5; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.neomorph {
 | 
				
			||||||
 | 
					  box-shadow: -8px -8px 16px var(--light-shadow), 8px 8px 16px var(--dark-shadow); }
 | 
				
			||||||
 | 
					  .neomorphSmall {
 | 
				
			||||||
 | 
					    box-shadow: -6px -6px 12px var(--light-shadow), 6px 6px 12px var(--dark-shadow); }
 | 
				
			||||||
 | 
					  .neomorphXSmall {
 | 
				
			||||||
 | 
					    box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow); }
 | 
				
			||||||
 | 
					  .neomorphXXSmall {
 | 
				
			||||||
 | 
					    box-shadow: -2px -2px 4px var(--light-shadow), 2px 2px 4px var(--dark-shadow); }
 | 
				
			||||||
 | 
					  .neomorphBottom {
 | 
				
			||||||
 | 
					    filter: drop-shadow(8px 8px 14px var(--primary-color-dark)); }
 | 
				
			||||||
 | 
					  .neomorphInset {
 | 
				
			||||||
 | 
					    box-shadow: inset 8px 8px 16px var(--dark-shadow), inset -8px -8px 16px var(--light-shadow); }
 | 
				
			||||||
 | 
					    .neomorphInsetSmall {
 | 
				
			||||||
 | 
					      box-shadow: inset 6px 6px 12px var(--dark-shadow), inset -6px -6px 12px var(--light-shadow); }
 | 
				
			||||||
 | 
					    .neomorphInsetXSmall {
 | 
				
			||||||
 | 
					      box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow); }
 | 
				
			||||||
 | 
					    .neomorphInsetXXSmall {
 | 
				
			||||||
 | 
					      box-shadow: inset 2px 2px 4px var(--dark-shadow), inset -2px -2px 4px var(--light-shadow); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.neoBtn {
 | 
				
			||||||
 | 
					  background: linear-gradient(145deg, var(--primary-gradiend-light), var(--primary-gradiend-dark));
 | 
				
			||||||
 | 
					  box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow);
 | 
				
			||||||
 | 
					  border: none !important;
 | 
				
			||||||
 | 
					  -webkit-backface-visibility: hidden;
 | 
				
			||||||
 | 
					  backface-visibility: hidden; }
 | 
				
			||||||
 | 
					  .neoBtn:focus {
 | 
				
			||||||
 | 
					    box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow) !important;
 | 
				
			||||||
 | 
					    border: none !important; }
 | 
				
			||||||
 | 
					  .neoBtnInsetPlain {
 | 
				
			||||||
 | 
					    background: linear-gradient(145deg, var(--primary-gradiend-dark), var(--primary-gradiend-light));
 | 
				
			||||||
 | 
					    box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow);
 | 
				
			||||||
 | 
					    border: none !important; }
 | 
				
			||||||
 | 
					    .neoBtnInsetPlain:focus {
 | 
				
			||||||
 | 
					      box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow) !important;
 | 
				
			||||||
 | 
					      border: none !important; }
 | 
				
			||||||
 | 
					  .neoBtnSmall {
 | 
				
			||||||
 | 
					    background: linear-gradient(145deg, var(--primary-gradiend-light), var(--primary-gradiend-dark));
 | 
				
			||||||
 | 
					    box-shadow: -2px -2px 4px var(--light-shadow), 2px 2px 4px var(--dark-shadow);
 | 
				
			||||||
 | 
					    border: none !important; }
 | 
				
			||||||
 | 
					    .neoBtnSmall:focus {
 | 
				
			||||||
 | 
					      box-shadow: -2px -2px 4px var(--light-shadow), 2px 2px 4px var(--dark-shadow);
 | 
				
			||||||
 | 
					      border: none !important; }
 | 
				
			||||||
 | 
					      .neoBtnSmall:focus:not(:active) {
 | 
				
			||||||
 | 
					        box-shadow: -2px -2px 4px var(--light-shadow), 2px 2px 4px var(--dark-shadow); }
 | 
				
			||||||
 | 
					    .neoBtnSmallInsetPlain {
 | 
				
			||||||
 | 
					      background: linear-gradient(145deg, var(--primary-gradiend-dark), var(--primary-gradiend-light));
 | 
				
			||||||
 | 
					      box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow);
 | 
				
			||||||
 | 
					      border: none !important; }
 | 
				
			||||||
 | 
					      .neoBtnSmallInsetPlain:focus {
 | 
				
			||||||
 | 
					        box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow) !important;
 | 
				
			||||||
 | 
					        border: none !important; }
 | 
				
			||||||
 | 
					    .neoBtnSmallXInsetPlain {
 | 
				
			||||||
 | 
					      background: linear-gradient(145deg, var(--primary-gradiend-dark), var(--primary-gradiend-light));
 | 
				
			||||||
 | 
					      box-shadow: inset 2px 2px 4px var(--dark-shadow), inset -2px -2px 4px var(--light-shadow);
 | 
				
			||||||
 | 
					      border: none !important; }
 | 
				
			||||||
 | 
					      .neoBtnSmallXInsetPlain:focus {
 | 
				
			||||||
 | 
					        box-shadow: inset 2px 2px 4px var(--dark-shadow), inset -2px -2px 4px var(--light-shadow) !important;
 | 
				
			||||||
 | 
					        border: none !important; }
 | 
				
			||||||
 | 
					    .neoBtnSmallPlain {
 | 
				
			||||||
 | 
					      box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow);
 | 
				
			||||||
 | 
					      border: none !important; }
 | 
				
			||||||
 | 
					      .neoBtnSmallPlain:focus {
 | 
				
			||||||
 | 
					        box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow) !important;
 | 
				
			||||||
 | 
					        border: none !important; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.neoFile {
 | 
				
			||||||
 | 
					  box-shadow: 0px 0px 0px var(--light-shadow), 0px 0px 0px var(--dark-shadow) !important;
 | 
				
			||||||
 | 
					  transition: all .2s linear;
 | 
				
			||||||
 | 
					  -webkit-backface-visibility: hidden !important;
 | 
				
			||||||
 | 
					  backface-visibility: hidden !important; }
 | 
				
			||||||
 | 
					  @media screen and (max-width: 768px) {
 | 
				
			||||||
 | 
					    .neoFile {
 | 
				
			||||||
 | 
					      box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow) !important;
 | 
				
			||||||
 | 
					      background: var(--primary-color) !important; } }
 | 
				
			||||||
 | 
					  .neoFile:hover {
 | 
				
			||||||
 | 
					    box-shadow: -3px -3px 6px var(--light-shadow), 3px 3px 6px var(--dark-shadow) !important; }
 | 
				
			||||||
 | 
					  .neoFile.isSelected {
 | 
				
			||||||
 | 
					    background: linear-gradient(145deg, var(--primary-gradiend-dark), var(--primary-gradiend-light));
 | 
				
			||||||
 | 
					    box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow) !important; }
 | 
				
			||||||
 | 
					  .neoFile.is-active, .neoFile.active {
 | 
				
			||||||
 | 
					    box-shadow: inset 3px 3px 6px var(--dark-shadow), inset -3px -3px 6px var(--light-shadow) !important;
 | 
				
			||||||
 | 
					    color: var(--black) !important; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.neoInput {
 | 
				
			||||||
 | 
					  box-shadow: inset 2px 2px 4px var(--dark-shadow), inset -2px -2px 4px var(--light-shadow) !important;
 | 
				
			||||||
 | 
					  background: linear-gradient(145deg, var(--primary-gradiend-dark), var(--primary-gradiend-light));
 | 
				
			||||||
 | 
					  border: none !important; }
 | 
				
			||||||
 | 
					  .neoInput:focus {
 | 
				
			||||||
 | 
					    border: none !important; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.neoSelect > select {
 | 
				
			||||||
 | 
					  box-shadow: inset 2px 2px 4px var(--dark-shadow), inset -2px -2px 4px var(--light-shadow) !important;
 | 
				
			||||||
 | 
					  background: linear-gradient(145deg, var(--primary-gradiend-dark), var(--primary-gradiend-light)) !important;
 | 
				
			||||||
 | 
					  border: none !important; }
 | 
				
			||||||
 | 
					  .neoSelect > select:focus {
 | 
				
			||||||
 | 
					    border: none !important; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					html {
 | 
				
			||||||
 | 
					  scrollbar-width: thin; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*, ::after, ::before {
 | 
				
			||||||
 | 
					  scrollbar-width: inherit; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar {
 | 
				
			||||||
 | 
					  width: 8px; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-button {
 | 
				
			||||||
 | 
					  width: 8px;
 | 
				
			||||||
 | 
					  height: 5px; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-track {
 | 
				
			||||||
 | 
					  background: transparent;
 | 
				
			||||||
 | 
					  border: thin solid transparent;
 | 
				
			||||||
 | 
					  box-shadow: none;
 | 
				
			||||||
 | 
					  border-radius: 10px; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					::-webkit-scrollbar-thumb {
 | 
				
			||||||
 | 
					  border: thin solid transparent;
 | 
				
			||||||
 | 
					  border-radius: 10px;
 | 
				
			||||||
 | 
					  background: var(--primary-color); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					body {
 | 
				
			||||||
 | 
					  background-image: url("/images/background.jpg");
 | 
				
			||||||
 | 
					  background-size: cover;
 | 
				
			||||||
 | 
					  min-height: 100vh; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.loading {
 | 
				
			||||||
 | 
					  height: 100vh;
 | 
				
			||||||
 | 
					  justify-content: center;
 | 
				
			||||||
 | 
					  flex-direction: column; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.drinkCartList {
 | 
				
			||||||
 | 
					  display: flex;
 | 
				
			||||||
 | 
					  flex-direction: column; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.drinkCartItem {
 | 
				
			||||||
 | 
					  display: grid;
 | 
				
			||||||
 | 
					  grid-template-areas: "drinkName drinkQuantity drinkCross drinkPrice";
 | 
				
			||||||
 | 
					  grid-template-columns: 1fr minmax(100px, 20%) 5% 10%;
 | 
				
			||||||
 | 
					  grid-template-rows: 100%;
 | 
				
			||||||
 | 
					  grid-gap: 5px;
 | 
				
			||||||
 | 
					  align-items: center; }
 | 
				
			||||||
 | 
					  .drinkCartItem:not(:last-child) {
 | 
				
			||||||
 | 
					    margin-bottom: 1rem; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.drinkCartPItem {
 | 
				
			||||||
 | 
					  display: grid;
 | 
				
			||||||
 | 
					  grid-template-areas: "drinkName drinkQuantity drinkCross drinkPrice";
 | 
				
			||||||
 | 
					  grid-template-columns: 1fr 10% 5% 10%;
 | 
				
			||||||
 | 
					  grid-template-rows: 100%;
 | 
				
			||||||
 | 
					  grid-gap: 5px;
 | 
				
			||||||
 | 
					  align-items: center; }
 | 
				
			||||||
 | 
					  .drinkCartPItem:not(:last-child) {
 | 
				
			||||||
 | 
					    margin-bottom: 1rem; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.drinkCartName {
 | 
				
			||||||
 | 
					  grid-area: drinkName; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.drinkCartCross {
 | 
				
			||||||
 | 
					  grid-area: drinkCross; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.drinkCartQuantity {
 | 
				
			||||||
 | 
					  grid-area: drinkQuantity; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.drinkCartPrice {
 | 
				
			||||||
 | 
					  grid-area: drinkPrice;
 | 
				
			||||||
 | 
					  white-space: nowrap; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.column > .box > .title {
 | 
				
			||||||
 | 
					  padding: 10%; }
 | 
				
			||||||
							
								
								
									
										1
									
								
								drinkMe/Client/wwwroot/css/style.min.css
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/favicon.ico
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.3 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/icon-512.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 8.0 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/images/background.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 1.4 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/images/drinkMe-logo.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 5.8 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/images/drinks/american-coffee.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 103 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/images/drinks/chocolate.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 40 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/images/drinks/italian-coffee.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 107 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/images/drinks/missing.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 15 KiB  | 
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/images/drinks/tea.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 923 KiB  | 
							
								
								
									
										30
									
								
								drinkMe/Client/wwwroot/index.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					<!DOCTYPE html>
 | 
				
			||||||
 | 
					<html>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<head>
 | 
				
			||||||
 | 
						<meta charset="utf-8" />
 | 
				
			||||||
 | 
						<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
 | 
				
			||||||
 | 
						<title>drinkMe</title>
 | 
				
			||||||
 | 
						<base href="/" />
 | 
				
			||||||
 | 
						<link href="css/bulma.min.css" rel="stylesheet" />
 | 
				
			||||||
 | 
						<link href="css/bulma-steps.min.css" rel="stylesheet" />
 | 
				
			||||||
 | 
						<link href="css/bulma-divider.min.css" rel="stylesheet" />
 | 
				
			||||||
 | 
						<link href="css/fontawesome.min.css" rel="stylesheet" />
 | 
				
			||||||
 | 
						<link href="css/duotone.min.css" rel="stylesheet" />
 | 
				
			||||||
 | 
						<link href="css/style.min.css" rel="stylesheet" />
 | 
				
			||||||
 | 
						<link href="manifest.json" rel="manifest" />
 | 
				
			||||||
 | 
						<link rel="apple-touch-icon" sizes="512x512" href="icon-512.png" />
 | 
				
			||||||
 | 
					</head>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<body>
 | 
				
			||||||
 | 
						<div id="app">
 | 
				
			||||||
 | 
							<div class="is-flex is-align-items-center loading">
 | 
				
			||||||
 | 
								<p><img src="images/drinkMe-logo.png" alt="loading logo" /></p>
 | 
				
			||||||
 | 
								<h1 class="title">Loading...</h1>
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
						<script src="_framework/blazor.webassembly.js"></script>
 | 
				
			||||||
 | 
						<script>navigator.serviceWorker.register('service-worker.js');</script>
 | 
				
			||||||
 | 
					</body>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</html>
 | 
				
			||||||
							
								
								
									
										15
									
								
								drinkMe/Client/wwwroot/manifest.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "name": "drinkMe",
 | 
				
			||||||
 | 
					  "short_name": "drinkMe",
 | 
				
			||||||
 | 
					  "start_url": "./",
 | 
				
			||||||
 | 
					  "display": "standalone",
 | 
				
			||||||
 | 
					  "background_color": "#ffffff",
 | 
				
			||||||
 | 
					  "theme_color": "#03173d",
 | 
				
			||||||
 | 
					  "icons": [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      "src": "icon-512.png",
 | 
				
			||||||
 | 
					      "type": "image/png",
 | 
				
			||||||
 | 
					      "sizes": "512x512"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										4
									
								
								drinkMe/Client/wwwroot/service-worker.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					// In development, always fetch from the network and do not enable offline support.
 | 
				
			||||||
 | 
					// This is because caching would make development more difficult (changes would not
 | 
				
			||||||
 | 
					// be reflected on the first load after each change).
 | 
				
			||||||
 | 
					self.addEventListener('fetch', () => { });
 | 
				
			||||||
							
								
								
									
										48
									
								
								drinkMe/Client/wwwroot/service-worker.published.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					// Caution! Be sure you understand the caveats before publishing an application with
 | 
				
			||||||
 | 
					// offline support. See https://aka.ms/blazor-offline-considerations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					self.importScripts('./service-worker-assets.js');
 | 
				
			||||||
 | 
					self.addEventListener('install', event => event.waitUntil(onInstall(event)));
 | 
				
			||||||
 | 
					self.addEventListener('activate', event => event.waitUntil(onActivate(event)));
 | 
				
			||||||
 | 
					self.addEventListener('fetch', event => event.respondWith(onFetch(event)));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const cacheNamePrefix = 'offline-cache-';
 | 
				
			||||||
 | 
					const cacheName = `${cacheNamePrefix}${self.assetsManifest.version}`;
 | 
				
			||||||
 | 
					const offlineAssetsInclude = [ /\.dll$/, /\.pdb$/, /\.wasm/, /\.html/, /\.js$/, /\.json$/, /\.css$/, /\.woff$/, /\.png$/, /\.jpe?g$/, /\.gif$/, /\.ico$/, /\.blat$/, /\.dat$/ ];
 | 
				
			||||||
 | 
					const offlineAssetsExclude = [ /^service-worker\.js$/ ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function onInstall(event) {
 | 
				
			||||||
 | 
					    console.info('Service worker: Install');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Fetch and cache all matching items from the assets manifest
 | 
				
			||||||
 | 
					    const assetsRequests = self.assetsManifest.assets
 | 
				
			||||||
 | 
					        .filter(asset => offlineAssetsInclude.some(pattern => pattern.test(asset.url)))
 | 
				
			||||||
 | 
					        .filter(asset => !offlineAssetsExclude.some(pattern => pattern.test(asset.url)))
 | 
				
			||||||
 | 
					        .map(asset => new Request(asset.url, { integrity: asset.hash }));
 | 
				
			||||||
 | 
					    await caches.open(cacheName).then(cache => cache.addAll(assetsRequests));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function onActivate(event) {
 | 
				
			||||||
 | 
					    console.info('Service worker: Activate');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Delete unused caches
 | 
				
			||||||
 | 
					    const cacheKeys = await caches.keys();
 | 
				
			||||||
 | 
					    await Promise.all(cacheKeys
 | 
				
			||||||
 | 
					        .filter(key => key.startsWith(cacheNamePrefix) && key !== cacheName)
 | 
				
			||||||
 | 
					        .map(key => caches.delete(key)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					async function onFetch(event) {
 | 
				
			||||||
 | 
					    let cachedResponse = null;
 | 
				
			||||||
 | 
					    if (event.request.method === 'GET') {
 | 
				
			||||||
 | 
					        // For all navigation requests, try to serve index.html from cache
 | 
				
			||||||
 | 
					        // If you need some URLs to be server-rendered, edit the following check to exclude those URLs
 | 
				
			||||||
 | 
					        const shouldServeIndexHtml = event.request.mode === 'navigate';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const request = shouldServeIndexHtml ? 'index.html' : event.request;
 | 
				
			||||||
 | 
					        const cache = await caches.open(cacheName);
 | 
				
			||||||
 | 
					        cachedResponse = await cache.match(request);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return cachedResponse || fetch(event.request);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/webfonts/fa-duotone-900.eot
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										15319
									
								
								drinkMe/Client/wwwroot/webfonts/fa-duotone-900.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
		 After Width: | Height: | Size: 2.5 MiB  | 
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/webfonts/fa-duotone-900.ttf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/webfonts/fa-duotone-900.woff
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								drinkMe/Client/wwwroot/webfonts/fa-duotone-900.woff2
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										95
									
								
								drinkMe/Server/Controllers/DrinksController.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,95 @@
 | 
				
			|||||||
 | 
					using collAnon.Pub.Shared;
 | 
				
			||||||
 | 
					using drinkMe.Server.Models;
 | 
				
			||||||
 | 
					using drinkMe.Server.Services.Interfaces;
 | 
				
			||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Mvc;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Server.Controllers
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						[ApiController]
 | 
				
			||||||
 | 
						[Route("api/[controller]/[action]")]
 | 
				
			||||||
 | 
						public class DrinksController : ControllerBase
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							readonly IDataService DataService;
 | 
				
			||||||
 | 
							readonly IPaymentService PaymentService;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public DrinksController(IDataService dataService, IPaymentService paymentService)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								DataService = dataService;
 | 
				
			||||||
 | 
								PaymentService = paymentService;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[HttpGet]
 | 
				
			||||||
 | 
							public async Task<IActionResult> IsValidDiscountCode([FromQuery] string code)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									var validationResult = await DataService.IsValidDiscountCode(code);
 | 
				
			||||||
 | 
									if (!validationResult.IsValid)
 | 
				
			||||||
 | 
										return StatusCode(validationResult.StatusCode, validationResult);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									var validationData = validationResult.Data as DiscountCode;
 | 
				
			||||||
 | 
									var resultData = new DiscountCodeViewModel
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Code = validationData.Code,
 | 
				
			||||||
 | 
										ApplicableProducts = validationData.ApplicableProducts,
 | 
				
			||||||
 | 
										DiscountPercentage = validationData.DiscountPercentage
 | 
				
			||||||
 | 
									};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return Ok(resultData);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception ex)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									return BadRequest(new WebResult().Invalidate($"Error at ${nameof(IsValidDiscountCode)}", default, ex));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[HttpGet]
 | 
				
			||||||
 | 
							public async Task<IActionResult> GetDrinks()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									var drinks = DataService.GetDrinks();
 | 
				
			||||||
 | 
									if (drinks.Count == 0)
 | 
				
			||||||
 | 
										return NotFound(new WebResult().Invalidate("No drinks available.", StatusCodes.Status404NotFound));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									var viewDrinks = drinks.Select(d => new DrinkViewModel
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
										Id = d.Id,
 | 
				
			||||||
 | 
										Name = d.Name,
 | 
				
			||||||
 | 
										Description = d.Description,
 | 
				
			||||||
 | 
										Price = d.Price,
 | 
				
			||||||
 | 
										PictureName = d.PictureName
 | 
				
			||||||
 | 
									}).ToArray();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return Ok(viewDrinks);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception ex)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									return BadRequest(new WebResult().Invalidate($"Error at ${nameof(GetDrinks)}", default, ex));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							[HttpPost]
 | 
				
			||||||
 | 
							public async Task<IActionResult> Pay(PurchaseCart purchaseCart)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									var successfulPayment = await PaymentService.Pay(purchaseCart);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									if (!successfulPayment)
 | 
				
			||||||
 | 
										return BadRequest(new WebResult().Invalidate("Payment failed.", StatusCodes.Status400BadRequest));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									return Ok();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (Exception ex)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									return BadRequest(new WebResult().Invalidate($"Error at ${nameof(Pay)}", default, ex));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										26
									
								
								drinkMe/Server/Program.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Logging;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Server
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class Program
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public static void Main(string[] args)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								CreateHostBuilder(args).Build().Run();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public static IHostBuilder CreateHostBuilder(string[] args) =>
 | 
				
			||||||
 | 
									Host.CreateDefaultBuilder(args)
 | 
				
			||||||
 | 
											.ConfigureWebHostDefaults(webBuilder =>
 | 
				
			||||||
 | 
											{
 | 
				
			||||||
 | 
												webBuilder.UseStartup<Startup>();
 | 
				
			||||||
 | 
											});
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										30
									
								
								drinkMe/Server/Properties/launchSettings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					    "iisSettings": {
 | 
				
			||||||
 | 
					      "windowsAuthentication": false,
 | 
				
			||||||
 | 
					      "anonymousAuthentication": true,
 | 
				
			||||||
 | 
					      "iisExpress": {
 | 
				
			||||||
 | 
					        "applicationUrl": "http://localhost:14962",
 | 
				
			||||||
 | 
					        "sslPort": 44321
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "profiles": {
 | 
				
			||||||
 | 
					      "IIS Express": {
 | 
				
			||||||
 | 
					        "commandName": "IISExpress",
 | 
				
			||||||
 | 
					        "launchBrowser": true,
 | 
				
			||||||
 | 
					        "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
 | 
				
			||||||
 | 
					        "environmentVariables": {
 | 
				
			||||||
 | 
					          "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "drinkMe.Server": {
 | 
				
			||||||
 | 
					        "commandName": "Project",
 | 
				
			||||||
 | 
					        "dotnetRunMessages": "true",
 | 
				
			||||||
 | 
					        "launchBrowser": true,
 | 
				
			||||||
 | 
					        "inspectUri": "{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}",
 | 
				
			||||||
 | 
					        "applicationUrl": "https://localhost:5001;http://localhost:5000",
 | 
				
			||||||
 | 
					        "environmentVariables": {
 | 
				
			||||||
 | 
					          "ASPNETCORE_ENVIRONMENT": "Development"
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
							
								
								
									
										69
									
								
								drinkMe/Server/Services/DataService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					using collAnon.Pub.Shared;
 | 
				
			||||||
 | 
					using drinkMe.Server.Models;
 | 
				
			||||||
 | 
					using drinkMe.Server.Services.Interfaces;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Server.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class DataService : IDataService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							List<DiscountCode> DiscountCodes = new List<DiscountCode>
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								new DiscountCode{ Code ="ITS_M0NDAY", DiscountPercentage = 15, ApplicableProducts = new[] { 2 } },
 | 
				
			||||||
 | 
								new DiscountCode{ Code ="ITS_K1NDA_COLD", DiscountPercentage = 30, ApplicableProducts = new[] { 4 } },
 | 
				
			||||||
 | 
								new DiscountCode{ Code ="I_NEED_R3LAX", DiscountPercentage = 25, ApplicableProducts = new[] { 3 } },
 | 
				
			||||||
 | 
								new DiscountCode{ Code ="D1AMOND_HANDS", DiscountPercentage = 100, ApplicableProducts = new[] { 1 } }
 | 
				
			||||||
 | 
							};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public List<Drink> GetDrinks() =>
 | 
				
			||||||
 | 
								new List<Drink>
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									new Drink
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
											Id = 1,
 | 
				
			||||||
 | 
											Name = "Italian Coffee",
 | 
				
			||||||
 | 
											Description = "Short but strong.",
 | 
				
			||||||
 | 
											Price = 3.50f,
 | 
				
			||||||
 | 
											PictureName = "italian-coffee.jpg"
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									new Drink
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
											Id = 2,
 | 
				
			||||||
 | 
											Name = "American Coffee",
 | 
				
			||||||
 | 
											Description = "Dilluted in water to a cup size, not as strong as the italian one.",
 | 
				
			||||||
 | 
											Price = 3.0f,
 | 
				
			||||||
 | 
											PictureName = "american-coffee.jpg"
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									new Drink
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
											Id = 3,
 | 
				
			||||||
 | 
											Name = "Tea",
 | 
				
			||||||
 | 
											Description = "Black Earl Grey, good alternative to coffee from time to time.",
 | 
				
			||||||
 | 
											Price = 2.0f,
 | 
				
			||||||
 | 
											PictureName = "tea.png"
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									new Drink
 | 
				
			||||||
 | 
									{
 | 
				
			||||||
 | 
											Id = 4,
 | 
				
			||||||
 | 
											Name = "Chocolate",
 | 
				
			||||||
 | 
											Description = "Your dose of sugar and calories, just don't loose the hang.",
 | 
				
			||||||
 | 
											Price = 4.0f,
 | 
				
			||||||
 | 
											PictureName = "chocolate.jpg"
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public async Task<WebResult> IsValidDiscountCode(string code)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								var result = new WebResult();
 | 
				
			||||||
 | 
								if (!DiscountCodes.Any(dc => dc.Code == code))
 | 
				
			||||||
 | 
									return result.Invalidate("Invalid discount code.", StatusCodes.Status404NotFound);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								result.Data = DiscountCodes.First(dc => dc.Code == code);
 | 
				
			||||||
 | 
								return result;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								drinkMe/Server/Services/Interfaces/IDataService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					using collAnon.Pub.Shared;
 | 
				
			||||||
 | 
					using drinkMe.Server.Models;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Server.Services.Interfaces
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public interface IDataService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							List<Drink> GetDrinks();
 | 
				
			||||||
 | 
							Task<WebResult> IsValidDiscountCode(string code);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										13
									
								
								drinkMe/Server/Services/Interfaces/IPaymentService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,13 @@
 | 
				
			|||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Server.Services.Interfaces
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public interface IPaymentService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Task<bool> Pay(PurchaseCart purchaseCart);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								drinkMe/Server/Services/PaymentService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					using drinkMe.Server.Services.Interfaces;
 | 
				
			||||||
 | 
					using drinkMe.Shared;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Server.Services
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class PaymentService : IPaymentService
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public async Task<bool> Pay(PurchaseCart purchaseCart)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								//completing the purchase
 | 
				
			||||||
 | 
								return true;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										66
									
								
								drinkMe/Server/Startup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,66 @@
 | 
				
			|||||||
 | 
					using drinkMe.Server.Services;
 | 
				
			||||||
 | 
					using drinkMe.Server.Services.Interfaces;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Builder;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.Hosting;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.HttpsPolicy;
 | 
				
			||||||
 | 
					using Microsoft.AspNetCore.ResponseCompression;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Configuration;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.DependencyInjection;
 | 
				
			||||||
 | 
					using Microsoft.Extensions.Hosting;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Server
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class Startup
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public Startup(IConfiguration configuration)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Configuration = configuration;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public IConfiguration Configuration { get; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// This method gets called by the runtime. Use this method to add services to the container.
 | 
				
			||||||
 | 
							// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
 | 
				
			||||||
 | 
							public void ConfigureServices(IServiceCollection services)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								services.AddScoped<IDataService, DataService>()
 | 
				
			||||||
 | 
									.AddScoped<IPaymentService, PaymentService>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								services.AddControllers().AddJsonOptions(options =>
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									options.JsonSerializerOptions.IgnoreReadOnlyFields = true;
 | 
				
			||||||
 | 
									options.JsonSerializerOptions.IgnoreReadOnlyProperties = true;
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
								services.AddRazorPages();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
 | 
				
			||||||
 | 
							public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								if (env.IsDevelopment())
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									app.UseDeveloperExceptionPage();
 | 
				
			||||||
 | 
									app.UseWebAssemblyDebugging();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
 | 
				
			||||||
 | 
									app.UseHsts();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								app.UseHttpsRedirection();
 | 
				
			||||||
 | 
								app.UseBlazorFrameworkFiles();
 | 
				
			||||||
 | 
								app.UseStaticFiles();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								app.UseRouting();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								app.UseEndpoints(endpoints =>
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									endpoints.MapRazorPages();
 | 
				
			||||||
 | 
									endpoints.MapControllers();
 | 
				
			||||||
 | 
									endpoints.MapFallbackToFile("index.html");
 | 
				
			||||||
 | 
								});
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								drinkMe/Server/appsettings.Development.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "Logging": {
 | 
				
			||||||
 | 
					    "LogLevel": {
 | 
				
			||||||
 | 
					      "Default": "Information",
 | 
				
			||||||
 | 
					      "Microsoft": "Warning",
 | 
				
			||||||
 | 
					      "Microsoft.Hosting.Lifetime": "Information"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										10
									
								
								drinkMe/Server/appsettings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,10 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  "Logging": {
 | 
				
			||||||
 | 
					    "LogLevel": {
 | 
				
			||||||
 | 
					      "Default": "Information",
 | 
				
			||||||
 | 
					      "Microsoft": "Warning",
 | 
				
			||||||
 | 
					      "Microsoft.Hosting.Lifetime": "Information"
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  },
 | 
				
			||||||
 | 
					"AllowedHosts": "*"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								drinkMe/Server/drinkMe.Server.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					<Project Sdk="Microsoft.NET.Sdk.Web">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
 | 
					    <TargetFramework>net5.0</TargetFramework>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.Server" Version="5.0.5" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\Client\drinkMe.Client.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\drinkMe.Server.Models\drinkMe.Server.Models.csproj" />
 | 
				
			||||||
 | 
					    <ProjectReference Include="..\Shared\drinkMe.Shared.csproj" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
							
								
								
									
										14
									
								
								drinkMe/Shared/CartItem.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Shared
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class CartItem
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public int Id { get; set; }
 | 
				
			||||||
 | 
							public int Quantity { get; set; } = 1;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								drinkMe/Shared/DiscountCodeViewModel.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					namespace drinkMe.Shared
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class DiscountCodeViewModel
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public string Code { get; set; }
 | 
				
			||||||
 | 
							public float DiscountPercentage  { get; set; }
 | 
				
			||||||
 | 
							public int[] ApplicableProducts { get; set; }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								drinkMe/Shared/DrinkViewModel.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.ComponentModel.DataAnnotations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Shared
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class DrinkViewModel
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public int Id { get; set; }
 | 
				
			||||||
 | 
							public string Name { get; set; } = "Missing name";
 | 
				
			||||||
 | 
							public string Description { get; set; } = "Missing description";
 | 
				
			||||||
 | 
							public string PictureName { get; set; } = "missing.png";
 | 
				
			||||||
 | 
							[Range(1, 20)]
 | 
				
			||||||
 | 
							public int Quantity { get; set; } = 1;
 | 
				
			||||||
 | 
							public float Price { get; set; } = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public bool IsInTheCart { get; set; } = false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										15
									
								
								drinkMe/Shared/PurchaseCart.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Shared
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class PurchaseCart
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public bool IsPayedWithCash { get; set; } = false;
 | 
				
			||||||
 | 
							public List<CartItem> PurchasingItems { get; set; } = new List<CartItem>();
 | 
				
			||||||
 | 
							public List<DiscountCodeViewModel> Discounts { get; set; } = new List<DiscountCodeViewModel>();
 | 
				
			||||||
 | 
							public string CreditCardNumber { get; set; }
 | 
				
			||||||
 | 
							public string CreditCardExpirationMonth { get; set; }
 | 
				
			||||||
 | 
							public string CreditCardExpirationYear { get; set; }
 | 
				
			||||||
 | 
							public string CreditCardCVVCode { get; set; }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										47
									
								
								drinkMe/Shared/WebResult.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,47 @@
 | 
				
			|||||||
 | 
					using Microsoft.AspNetCore.Http;
 | 
				
			||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Text.Json.Serialization;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace collAnon.Pub.Shared
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class WebResult
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public WebResult Invalidate<T>(string errorMessage, int statusCode = StatusCodes.Status400BadRequest, Exception exception = null, T defaultData = default)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								IsValid = false;
 | 
				
			||||||
 | 
								ErrorMessage = errorMessage;
 | 
				
			||||||
 | 
								StatusCode = statusCode;
 | 
				
			||||||
 | 
								Exception = exception;
 | 
				
			||||||
 | 
								Data = defaultData;
 | 
				
			||||||
 | 
								return this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							public WebResult Invalidate(string errorMessage, int statusCode = StatusCodes.Status400BadRequest, Exception exception = null)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								IsValid = false;
 | 
				
			||||||
 | 
								ErrorMessage = errorMessage;
 | 
				
			||||||
 | 
								StatusCode = statusCode;
 | 
				
			||||||
 | 
								Exception = exception;
 | 
				
			||||||
 | 
								return this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public WebResult Invalidate(WebResult result)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								IsValid = result.IsValid;
 | 
				
			||||||
 | 
								ErrorMessage = result.ErrorMessage;
 | 
				
			||||||
 | 
								StatusCode = result.StatusCode;
 | 
				
			||||||
 | 
								Exception = result.Exception;
 | 
				
			||||||
 | 
								Data = result.Data;
 | 
				
			||||||
 | 
								return this;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public int StatusCode { get; set; } = StatusCodes.Status200OK;
 | 
				
			||||||
 | 
							public string ErrorMessage { get; set; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public bool IsValid { get; set; } = true;
 | 
				
			||||||
 | 
							[JsonIgnore]
 | 
				
			||||||
 | 
							public object Data { get; set; }
 | 
				
			||||||
 | 
							[JsonIgnore]
 | 
				
			||||||
 | 
							public Exception Exception { get; set; }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										14
									
								
								drinkMe/Shared/drinkMe.Shared.csproj
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					<Project Sdk="Microsoft.NET.Sdk">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
 | 
					    <TargetFramework>net5.0</TargetFramework>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <PackageReference Include="Microsoft.AspNetCore.Http.Abstractions" Version="2.2.0" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <ItemGroup>
 | 
				
			||||||
 | 
					    <SupportedPlatform Include="browser" />
 | 
				
			||||||
 | 
					  </ItemGroup>
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
							
								
								
									
										25
									
								
								drinkMe/drinkMe.Client.Models/CreditCardForm.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					using System;
 | 
				
			||||||
 | 
					using System.Collections.Generic;
 | 
				
			||||||
 | 
					using System.ComponentModel.DataAnnotations;
 | 
				
			||||||
 | 
					using System.Linq;
 | 
				
			||||||
 | 
					using System.Text;
 | 
				
			||||||
 | 
					using System.Threading.Tasks;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class CreditCardForm
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							[Required, Display(Name = "Credit card number"),
 | 
				
			||||||
 | 
								MaxLength(16), MinLength(16)]
 | 
				
			||||||
 | 
							public string Number { get; set; }
 | 
				
			||||||
 | 
							[Required, Display(Name = "Expiration month"),
 | 
				
			||||||
 | 
								Range(2, 2), RegularExpression(@"^((0[1-9])|(1[0-2]))$", ErrorMessage = "Invalid month")]
 | 
				
			||||||
 | 
							public string ExpirationMonth { get; set; }
 | 
				
			||||||
 | 
							[Required, Display(Name = "Expiration year"),
 | 
				
			||||||
 | 
								Range(2, 2), RegularExpression(@"^(\d{2})$", ErrorMessage = "Invalid year")]
 | 
				
			||||||
 | 
							public string ExpirationYear { get; set; }
 | 
				
			||||||
 | 
							[Required, Display(Name = "CVV code"),
 | 
				
			||||||
 | 
								Range(3, 3), RegularExpression(@"^(\d{3})$", ErrorMessage = "Invalid CVV code")]
 | 
				
			||||||
 | 
							public string CVVCode { get; set; }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								drinkMe/drinkMe.Client.Models/DiscountForm.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					using System.ComponentModel.DataAnnotations;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					namespace drinkMe.Client.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class DiscountForm
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							[Required,
 | 
				
			||||||
 | 
								Display(Name = "Discount code")]
 | 
				
			||||||
 | 
							public string DiscountCode { get; set; }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								drinkMe/drinkMe.Client.Models/PaymentMethod.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					namespace drinkMe.Client.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public enum PaymentMethod
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							Undefined,
 | 
				
			||||||
 | 
							Cash,
 | 
				
			||||||
 | 
							CreditCard
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										9
									
								
								drinkMe/drinkMe.Client.Models/PurchaseStep.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					namespace drinkMe.Client.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public enum PurchaseStep
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							ChoosingProducts,
 | 
				
			||||||
 | 
							PaymentSetup,
 | 
				
			||||||
 | 
							SuccessfulPurchase
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					<Project Sdk="Microsoft.NET.Sdk">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
 | 
					    <TargetFramework>net5.0</TargetFramework>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||
							
								
								
									
										9
									
								
								drinkMe/drinkMe.Server.Models/DiscountCode.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					namespace drinkMe.Server.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class DiscountCode
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public string Code { get; set; }
 | 
				
			||||||
 | 
							public float DiscountPercentage { get; set; }
 | 
				
			||||||
 | 
							public int[] ApplicableProducts { get; set; }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										11
									
								
								drinkMe/drinkMe.Server.Models/Drink.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						@@ -0,0 +1,11 @@
 | 
				
			|||||||
 | 
					namespace drinkMe.Server.Models
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						public class Drink
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							public int Id { get; set; }
 | 
				
			||||||
 | 
							public string Name { get; set; } = "Missing name";
 | 
				
			||||||
 | 
							public string Description { get; set; } = "Missing description";
 | 
				
			||||||
 | 
							public float Price { get; set; } = 0;
 | 
				
			||||||
 | 
							public string PictureName { get; set; } = "missing.png";
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					<Project Sdk="Microsoft.NET.Sdk">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  <PropertyGroup>
 | 
				
			||||||
 | 
					    <TargetFramework>net5.0</TargetFramework>
 | 
				
			||||||
 | 
					  </PropertyGroup>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</Project>
 | 
				
			||||||