Browse Source
			
			
			
			
				
		Reviewed-on: https://scm.barhendev.com/barhen/Biskilog_Accounting/pulls/7BISKI2023-18
				 30 changed files with 657 additions and 219 deletions
			
			
		| @ -0,0 +1,4 @@ | |||
| [*.cs] | |||
| 
 | |||
| # IDE0021: Use block body for constructor | |||
| csharp_style_expression_bodied_constructors = when_on_single_line | |||
| @ -0,0 +1,25 @@ | |||
| namespace Biskilog_Accounting.Client.Elements | |||
| { | |||
|     public partial class Sidebar | |||
|     { | |||
|         private double m_activeId = 1; | |||
|         private string m_class { get; set; } = "layout-menu"; | |||
| 
 | |||
|         private void HandleMenuClick(double a_selectedId) | |||
|         { | |||
|             m_activeId = a_selectedId; | |||
|             StateHasChanged(); | |||
|         } | |||
|         private void Collapse() | |||
|         { | |||
|             //if (m_class == "layout-menu")
 | |||
|             //{
 | |||
|             //    m_class = "layout-menu-collapsed";
 | |||
|             //}
 | |||
|             //else
 | |||
|             //{
 | |||
|             //    m_class = "layout-menu";
 | |||
|             //}
 | |||
|         } | |||
|     } | |||
| } | |||
| @ -0,0 +1,24 @@ | |||
| using System.Net.Http.Headers; | |||
| 
 | |||
| namespace Biskilog_Accounting.Client.Layouts | |||
| { | |||
|     public partial class MainLayout | |||
|     { | |||
| 
 | |||
|         protected override async Task OnInitializedAsync() | |||
|         { | |||
|             //Checks if user token is set else redirect user to login page
 | |||
|             if (!await m_tokenService.IsTokenSet()) | |||
|             { | |||
|                 m_navigationManager.NavigateTo("/login"); | |||
|             } | |||
|             else | |||
|             { | |||
|                 string token = await m_tokenService.GetToken(); | |||
|                 var authHeader = new AuthenticationHeaderValue("Bearer", token.Substring(6).Trim()); | |||
|                 m_http.DefaultRequestHeaders.Authorization = authHeader; | |||
|             } | |||
|             return; | |||
|         } | |||
|     } | |||
| } | |||
| @ -1,7 +1,112 @@ | |||
| namespace Biskilog_Accounting.Client.Pages.Auth | |||
| using Microsoft.AspNetCore.Components.Web; | |||
| using Microsoft.AspNetCore.Components; | |||
| using System.Net.Http.Headers; | |||
| using Biskilog_Accounting.Shared.ClientContractModels; | |||
| using Biskilog_Accounting.Shared.Interfaces; | |||
| using System.Net.Http.Json; | |||
| 
 | |||
| namespace Biskilog_Accounting.Client.Pages.Auth | |||
| { | |||
|     public partial class Login | |||
|     { | |||
|         private string m_email, m_password; | |||
|         private bool m_remember { get; set; } | |||
|         protected bool IsVisible { get; set; } | |||
|         //NotificationMessage notificationMessage = new NotificationMessage();
 | |||
|         private Userauth authenticatedUser; | |||
|         /// <summary>
 | |||
|         /// Handles the click or press event of the enter key
 | |||
|         /// </summary>
 | |||
|         /// <param name="e"></param>
 | |||
|         public async void Enter(KeyboardEventArgs e) | |||
|         { | |||
|             if (e.Code == "Enter" || e.Code == "NumpadEnter") | |||
|             { | |||
|                 await pagaAuth(); | |||
|             } | |||
|         } | |||
|         /// <summary>
 | |||
|         /// Authenticates the user and determines the type of page layout to show
 | |||
|         /// </summary>
 | |||
|         /// <returns></returns>
 | |||
|         async Task pagaAuth() | |||
|         { | |||
| 
 | |||
|             ShowSpinner(); | |||
|             try | |||
|             { | |||
|                 authenticatedUser = new Userauth | |||
|                 { | |||
|                     UserId = 0, | |||
|                     Username = m_email, | |||
|                     Email = m_email, | |||
|                     Passsword = m_password | |||
|                 }; | |||
|                 var responseMain = await m_http.PostAsJsonAsync("api/authentication/type-a", authenticatedUser); | |||
|                 if (responseMain.IsSuccessStatusCode) | |||
|                 { | |||
|                     string token = await responseMain.Content.ReadAsStringAsync(); | |||
|                     await m_tokenService.SetToken(token, m_remember); | |||
| 
 | |||
|                     var authHeader = new AuthenticationHeaderValue("Bearer", token); | |||
|                     m_http.DefaultRequestHeaders.Authorization = authHeader; | |||
| 
 | |||
|                     m_navigationManager.NavigateTo("/"); | |||
|                 } | |||
|                 else if (responseMain.StatusCode == System.Net.HttpStatusCode.BadRequest) | |||
|                 { | |||
|                 } | |||
|             } | |||
|             catch (Exception ex)  | |||
|             { | |||
|                 Console.WriteLine(ex.ToString()); | |||
|             } | |||
|             HideSpinner(); | |||
|         } | |||
|         /// <summary>
 | |||
|         /// Shows the loading spinner
 | |||
|         /// </summary>
 | |||
|         public void ShowSpinner() | |||
|         { | |||
|             IsVisible = true; | |||
|             StateHasChanged(); | |||
|         } | |||
|         /// <summary>
 | |||
|         /// Hides the loading spinner
 | |||
|         /// </summary>
 | |||
|         public void HideSpinner() | |||
|         { | |||
|             IsVisible = false; | |||
|             StateHasChanged(); | |||
|         } | |||
|         /// <summary>
 | |||
|         /// Shows a notification message
 | |||
|         /// </summary>
 | |||
|         /// <param name="message"></param>
 | |||
|         /// <returns></returns>
 | |||
|         //async Task ShowNotification(NotificationMessage message)
 | |||
|         //{
 | |||
|         //    notificationService.Notify(message);
 | |||
| 
 | |||
|         //    await InvokeAsync(() => { StateHasChanged(); });
 | |||
|         //}
 | |||
|         /// <summary>
 | |||
|         /// Sets the username value
 | |||
|         /// </summary>
 | |||
|         /// <param name="value"></param>
 | |||
|         void usernameInput(string value) | |||
|         { | |||
|             m_email = value; | |||
|             StateHasChanged(); | |||
|         } | |||
|         /// <summary>
 | |||
|         /// Sets the password value
 | |||
|         /// </summary>
 | |||
|         /// <param name="value"></param>
 | |||
|         void passwordInput(string value) | |||
|         { | |||
|             m_password = value; | |||
|             StateHasChanged(); | |||
|         } | |||
|     } | |||
| } | |||
| @ -0,0 +1,41 @@ | |||
| using Biskilog_Accounting.Shared.CustomModels; | |||
| using System.Net.Http.Json; | |||
| using System.Text.Json; | |||
| 
 | |||
| namespace Biskilog_Accounting.Client.Pages.Dashboard | |||
| { | |||
|     public partial class Dashboard | |||
|     { | |||
|         private TradeSummary m_tradeSummary { get; set; } = new TradeSummary(); | |||
|         private string m_username { get; set; } = string.Empty; | |||
|         protected override async Task OnInitializedAsync() | |||
|         { | |||
|             m_username = m_tokenService.GetUserNameFromToken(await m_tokenService.GetToken())!; | |||
|             await GetSummary(); | |||
|             return; | |||
|         } | |||
|         | |||
|         /// <summary>
 | |||
|         /// Gets the tade summary
 | |||
|         /// </summary>
 | |||
|         /// <returns></returns>
 | |||
|         async Task GetSummary() | |||
|         { | |||
|             try | |||
|             { | |||
|                 var response = await m_http.GetAsync("api/analytics/tradesummary"); | |||
|                 if (response.IsSuccessStatusCode) | |||
|                 { | |||
|                     var jsonContent = await response.Content.ReadAsStringAsync(); | |||
|                     var options = new JsonSerializerOptions { PropertyNameCaseInsensitive = true }; | |||
|                     var tradeSummary = JsonSerializer.Deserialize<TradeSummary>(jsonContent, options); | |||
|                     m_tradeSummary = tradeSummary; | |||
|                     StateHasChanged(); | |||
|                 } | |||
|             }catch (Exception ex) | |||
|             { | |||
|                 Console.WriteLine(ex.Message); | |||
|             } | |||
|         } | |||
|     } | |||
| } | |||
| @ -0,0 +1,28 @@ | |||
| <div class="card"> | |||
|     <div class="card-body"> | |||
|         <div class="card-title d-flex align-items-start justify-content-between"> | |||
|             <div class="avatar flex-shrink-0"> | |||
|                 <img src="@Icon" | |||
|                      alt="chart success" | |||
|                      class="rounded" /> | |||
|             </div> | |||
|             <div class="dropdown"> | |||
|                 <button class="btn p-0" | |||
|                         type="button" | |||
|                         id="cardOpt3" | |||
|                         data-bs-toggle="dropdown" | |||
|                         aria-haspopup="true" | |||
|                         aria-expanded="false"> | |||
|                     <i class="bx bx-dots-vertical-rounded"></i> | |||
|                 </button> | |||
|                 <div class="dropdown-menu dropdown-menu-end" aria-labelledby="cardOpt3"> | |||
|                     <a class="dropdown-item" href="javascript:void(0);">View More</a> | |||
|                     <a class="dropdown-item" href="javascript:void(0);">Delete</a> | |||
|                 </div> | |||
|             </div> | |||
|         </div> | |||
|         <span class="fw-semibold d-block mb-1">@Title</span> | |||
|         <h3 class="card-title mb-2">@Value</h3> | |||
|         <small class="@(Percentage > 0 ? "text-success" : Percentage == 0 ? "bx-forward-arrow-alt" : "text-danger") fw-semibold"><i class="bx @(Percentage > 0 ? "bx-up-arrow-alt" : Percentage == 0 ? "bx-forward-arrow-alt" : "bx-down-arrow-alt")"></i> @Percentage %</small> | |||
|     </div> | |||
| </div> | |||
| @ -0,0 +1,16 @@ | |||
| using Microsoft.AspNetCore.Components; | |||
| 
 | |||
| namespace Biskilog_Accounting.Client.Pages.Dashboard.Elements | |||
| { | |||
|     public partial class AnalyticsItemSmall | |||
|     { | |||
|         [Parameter] | |||
|         public string Icon { get; set; } = string.Empty; | |||
|         [Parameter] | |||
|         public string Title { get; set; }= string.Empty; | |||
|         [Parameter] | |||
|         public double Value{ get; set; } | |||
|         [Parameter] | |||
|         public double Percentage { get;set; } | |||
|     } | |||
| } | |||
| @ -0,0 +1,25 @@ | |||
| @using Biskilog_Accounting.Shared.Interfaces; | |||
| @inject ICalculator m_calculator; | |||
| 
 | |||
| <div class="card"> | |||
|     <div class="d-flex align-items-end row"> | |||
|         <div class="col-sm-7"> | |||
|             <div class="card-body"> | |||
|                 <h5 class="card-title text-primary">@(CurrentTradeSales > PreviousTradeSales ? "Congratulations 🎉" : PreviousTradeSales > CurrentTradeSales ? "Tough shift there" : "Well Done") @Username!</h5> | |||
|                 <p class="mb-4"> | |||
|                     @m_remarks | |||
|                 </p> | |||
|                 <a href="javascript:;" class="btn btn-sm btn-outline-primary">View Trade Summary</a> | |||
|             </div> | |||
|         </div> | |||
|         <div class="col-sm-5 text-center text-sm-left"> | |||
|             <div class="card-body pb-0 px-0 px-md-4"> | |||
|                 <img src="../assets/img/illustrations/man-with-laptop-light.png" | |||
|                      height="140" | |||
|                      alt="View Badge User" | |||
|                      data-app-dark-img="illustrations/man-with-laptop-dark.png" | |||
|                      data-app-light-img="illustrations/man-with-laptop-light.png" /> | |||
|             </div> | |||
|         </div> | |||
|     </div> | |||
| </div> | |||
| @ -0,0 +1,41 @@ | |||
| using Microsoft.AspNetCore.Components; | |||
| 
 | |||
| namespace Biskilog_Accounting.Client.Pages.Dashboard.Elements | |||
| { | |||
|     public partial class WelcomeCard | |||
|     { | |||
|         [Parameter] | |||
|         public string Username { get; set; } = string.Empty; | |||
| 
 | |||
|         [Parameter] | |||
|         public double CurrentTradeSales { get; set; } = 0; | |||
|         [Parameter] | |||
|         public double PreviousTradeSales { get; set; } = 0; | |||
| 
 | |||
|         private string m_remarks { get; set; } = ""; | |||
| 
 | |||
|         protected override void OnParametersSet() | |||
|         { | |||
|             CalculateStatistic(); | |||
|         } | |||
|         private void CalculateStatistic() | |||
|         { | |||
|             double change = ((CurrentTradeSales - PreviousTradeSales) / PreviousTradeSales) * 100; | |||
|             if (CurrentTradeSales > PreviousTradeSales) | |||
|             { | |||
|                 string changePercent = change.ToString("0.00") + "%"; | |||
|                 m_remarks = $"You made a total of {m_calculator.FormatMoneyWithCurrency(CurrentTradeSales)} in the current trade, {changePercent} more than the previous trade sales"; | |||
|             } | |||
|             else if (PreviousTradeSales > CurrentTradeSales) | |||
|             { | |||
|                 string changePercent = (change * -1).ToString("0.00") + "%"; | |||
|                 m_remarks = $"You made a total of {m_calculator.FormatMoneyWithCurrency(CurrentTradeSales)} in the current trade, {changePercent} less than the previous trade sales"; | |||
|             } | |||
|             else | |||
|             { | |||
|                 m_remarks = $"You made a total of {m_calculator.FormatMoneyWithCurrency(CurrentTradeSales)} in the current trade, same as the previous trade sales"; | |||
|             } | |||
|             StateHasChanged(); | |||
|         } | |||
|     } | |||
| } | |||
| @ -0,0 +1,16 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| 
 | |||
| namespace Biskilog_Accounting.Shared.CustomModels | |||
| { | |||
|     public class TradeSummary | |||
|     { | |||
|         public DateTime CurrentTradeDate { get; set; } = DateTime.Now; | |||
|         public DateTime LastTradeDate { get; set; } = DateTime.Now.AddDays(-1); | |||
|         public double CurrentTradeSales { get; set; } = 0; | |||
|         public double LastTradeSales { get; set; } = 0; | |||
|     } | |||
| } | |||
| @ -0,0 +1,16 @@ | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Globalization; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| 
 | |||
| namespace Biskilog_Accounting.Shared.Interfaces | |||
| { | |||
|     public interface ICalculator | |||
|     { | |||
|         double CalculatePercentage(); | |||
|         string FormatMoneyWithCurrency(double a_amount); | |||
|         NumberFormatInfo GetCurrencyCode(); | |||
|     } | |||
| } | |||
| @ -0,0 +1,39 @@ | |||
| using Biskilog_Accounting.Shared.Interfaces; | |||
| using System; | |||
| using System.Collections.Generic; | |||
| using System.Globalization; | |||
| using System.Linq; | |||
| using System.Text; | |||
| using System.Threading.Tasks; | |||
| 
 | |||
| namespace Biskilog_Accounting.Shared.ServiceRepo | |||
| { | |||
|     public class CalculatorService : ICalculator | |||
|     { | |||
|         public double CalculatePercentage() | |||
|         { | |||
|             throw new NotImplementedException(); | |||
|         } | |||
| 
 | |||
|         public string FormatMoneyWithCurrency(double a_amount) | |||
|         { | |||
|             return string.Format(GetCurrencyCode(), " {0:C2}", a_amount); | |||
|         } | |||
| 
 | |||
|         public NumberFormatInfo GetCurrencyCode() | |||
|         { | |||
|             //TODO have a better implementation
 | |||
| 
 | |||
|             // Specify the locale for Ghana
 | |||
|             string locale = "en-GH"; | |||
| 
 | |||
|             // Get the NumberFormatInfo for the specified locale
 | |||
|             NumberFormatInfo numberFormatInfo = new CultureInfo(locale).NumberFormat; | |||
| 
 | |||
|             // Set the currency symbol to Ghanaian cedi
 | |||
|             numberFormatInfo.CurrencySymbol = "GH₵"; | |||
| 
 | |||
|             return numberFormatInfo; | |||
|         } | |||
|     } | |||
| } | |||
					Loading…
					
					
				
		Reference in new issue