Maxime ROCHER 2 months ago
commit 0e564f580b

@ -24,20 +24,20 @@ namespace WF_WebAdmin.Converter
public QuoteDTO(int id_quote,string content,int likes,string langue,bool isValide,string? reason,int? id_caracter,string name_charac,int? id_source,string title,DateTime date,int? id_user_verif,string name_user ,int? id_img,string img_path) public QuoteDTO(int id_quote,string content,int likes,string langue,bool isValide,string? reason,int? id_caracter,string name_charac,int? id_source,string title,DateTime date,int? id_user_verif,string name_user ,int? id_img,string img_path)
{ {
this.Id = id_quote; this.Id = id_quote;
this.Content = content; this.Content = content;
this.Likes = likes; this.Likes = likes;
this.Langue = langue; this.Langue = langue;
this.IsValide = isValide; this.IsValide = isValide;
this.Reason = reason; this.Reason = reason;
this.IdCaracter = id_caracter; this.IdCaracter = id_caracter;
this.NameCharac = name_charac; this.NameCharac = name_charac;
this.IdSource = id_source; this.IdSource = id_source;
this.TitleSrc = title; this.TitleSrc = title;
this.DateSrc = date; this.DateSrc = date;
this.IdUserVerif = id_user_verif; this.IdUserVerif = id_user_verif;
this.NameUser = name_user; this.NameUser = name_user;
this.IdImg = id_img; this.IdImg = id_img;
this.ImgPath =img_path; this.ImgPath =img_path;
} }
} }
} }

@ -10,7 +10,7 @@ namespace WF_WebAdmin.Converter
public DateTime DateCreation { get; set; } public DateTime DateCreation { get; set; }
public Boolean IsAdmin { get; set; } public Boolean IsAdmin { get; set; }
public List<Commentary> Comments { get; set; } public List<Commentary>? Comments { get; set; }
public UserDTO(string image, string name, string email, DateTime dateCreation) public UserDTO(string image, string name, string email, DateTime dateCreation)
{ {

@ -1,8 +1,8 @@
namespace WF_WebAdmin.Model namespace WF_WebAdmin.Model
{ {
public class Character public class Character
{ {
public int id_caracter { get; set; } public int id_caracter { get; set; }
public string caracter { get; set; } public string? caracter { get; set; }
} }
} }

@ -1,41 +1,25 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration.UserSecrets; using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.VisualBasic; using Microsoft.VisualBasic;
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.Security.Claims; using System.Security.Claims;
using WF_WebAdmin.Pages; using WF_WebAdmin.Pages;
using WF_WebAdmin.Service; using WF_WebAdmin.Service;
namespace WF_WebAdmin.Model namespace WF_WebAdmin.Model
{ {
public static partial class LoggerSaveStub public static partial class LoggerSaveStub
{ {
public static void Log(ILogger logs,LogLevel logLevel,string message) public static void Log(ILogger logs,LogLevel logLevel,string message)
{ {
ILogsService logsService = new LogsServiceStub(); ILogsService logsService = new LogsServiceStub();
logsService.addLogs( new Logs( logLevel , message ) ); logsService.addLogs( new Logs( logLevel , message ) );
logs.Log(logLevel, message ); logs.Log(logLevel, message );
} }
} }
} }
/*
[Inject]
public ILogger< Class > Logger { get; set; }
LoggerSaveStub.Log(Logger,LogLevel. level , message );
LogLevel:
Trace = 0,
Debug = 1,
Information = 2,
Warning = 3,
Error = 4,
Critical = 5,
None = 6,
*/

@ -3,7 +3,7 @@ namespace WF_WebAdmin.Model
public class Quiz public class Quiz
{ {
public int Id { get; set; } public int Id { get; set; }
public string Question { get; set; } public string? Question { get; set; }
public string AnswerA { get; set; } public string AnswerA { get; set; }
public string AnswerB { get; set; } public string AnswerB { get; set; }
public string AnswerC { get; set; } public string AnswerC { get; set; }
@ -25,8 +25,8 @@ namespace WF_WebAdmin.Model
UserProposition = userProposition; UserProposition = userProposition;
} }
public Quiz(int id, string question, string answerA, string answerB, string answerC, string answerD, string cAnswer) public Quiz(int id, string question, string answerA, string answerB, string answerC, string answerD, string cAnswer)
{ {
Id = id; Id = id;
Question = question; Question = question;
AnswerA = answerA; AnswerA = answerA;
@ -35,7 +35,7 @@ namespace WF_WebAdmin.Model
AnswerD = answerD; AnswerD = answerD;
CAnswer = cAnswer; CAnswer = cAnswer;
IsValid = true; IsValid = true;
UserProposition = "Admin"; UserProposition = "Admin";
} }
public Quiz() {} public Quiz() {}

@ -1,30 +1,30 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace WF_WebAdmin.Model namespace WF_WebAdmin.Model
{ {
public class QuizModel public class QuizModel
{ {
[Required] [Required]
[StringLength(200, ErrorMessage = "La question ne peut pas depasser les 200 caractère.")] [StringLength(200, ErrorMessage = "La question ne peut pas depasser les 200 caractère.")]
public string Question { get; set; } public string? Question { get; set; }
[Required] [Required]
[StringLength(50, ErrorMessage = "La réponse ne peut pas depasser les 50 caractère.")] [StringLength(50, ErrorMessage = "La réponse ne peut pas depasser les 50 caractère.")]
public string AnswerA { get; set; } public string? AnswerA { get; set; }
[Required] [Required]
[StringLength(50, ErrorMessage = "La réponse ne peut pas depasser les 50 caractère.")] [StringLength(50, ErrorMessage = "La réponse ne peut pas depasser les 50 caractère.")]
public string AnswerB { get; set; } public string? AnswerB { get; set; }
[Required] [Required]
[StringLength(50, ErrorMessage = "La réponse ne peut pas depasser les 50 caractère.")] [StringLength(50, ErrorMessage = "La réponse ne peut pas depasser les 50 caractère.")]
public string AnswerC { get; set; } public string? AnswerC { get; set; }
[Required] [Required]
[StringLength(50, ErrorMessage = "La réponse ne peut pas depasser les 50 caractère.")] [StringLength(50, ErrorMessage = "La réponse ne peut pas depasser les 50 caractère.")]
public string AnswerD { get; set; } public string? AnswerD { get; set; }
[Required] [Required]
public string CAnswer { get; set; } public string? CAnswer { get; set; }
} }
} }

@ -1,69 +1,33 @@
using Microsoft.AspNetCore.DataProtection.KeyManagement; using Microsoft.AspNetCore.DataProtection.KeyManagement;
namespace WF_WebAdmin.Model namespace WF_WebAdmin.Model
{ {
public class Quote public class Quote
{ {
public int Id { get; set; } public int Id { get; set; }
public string Content { get; set; } public string Content { get; set; }
public int Like { get; set; } public int Like { get; set; }
public string Langue { get; set; } public string Langue { get; set; }
public string Charac { get; set; } public string Charac { get; set; }
public string ImgPath { get; set; } public string ImgPath { get; set; }
public string TitleSrc { get; set; } public string TitleSrc { get; set; }
public DateTime DateSrc { get; set; } public DateTime DateSrc { get; set; }
public string UserProposition { get; set; } public string UserProposition { get; set; }
public bool IsValid { get; set; } public bool IsValid { get; set; }
public Quote(int id, string content, string charac, string imgPath, string titleSrc, DateTime dateSrc, int like, string langue, string userProposition, bool isvalid) public Quote(int id, string content, string charac, string imgPath, string titleSrc, DateTime dateSrc, int like, string langue, string userProposition, bool isvalid)
{ {
Id = id; Id = id;
Content = content; Content = content;
Charac = charac; Charac = charac;
ImgPath = imgPath; ImgPath = imgPath;
TitleSrc = titleSrc; TitleSrc = titleSrc;
DateSrc = dateSrc; DateSrc = dateSrc;
Like = like; Like = like;
Langue = langue; Langue = langue;
UserProposition = userProposition; UserProposition = userProposition;
IsValid = isvalid; IsValid = isvalid;
} }
/*
public int Id { get; set; } }
public string Content { get; set; } }
public int Likes { get; set; }
public string Langue { get; set; }
public bool IsValide { get; set; }
public string? Reason { get; set; }
public int IdCaracter { get; set; }
public int IdSource { get; set; }
public int? IdUserVerif { get; set; }
public Quote(int id, string content, int likes, string langue, bool isValide, string? reason, int idCaracter, int idSource, int idUserVerif)
{
Id = id;
Content = content;
Likes = likes;
Langue = langue;
IsValide = isValide;
Reason = reason;
IdCaracter = idCaracter;
IdSource = idSource;
IdUserVerif = idUserVerif;
}
public Quote(int id, string content, int likes, string langue, bool isValide, string? reason, int idCaracter, int idSource, int? idUserVerif)
{
Id = id;
Content = content;
Likes = likes;
Langue = langue;
IsValide = isValide;
Reason = reason;
IdCaracter = idCaracter;
IdSource = idSource;
IdUserVerif = idUserVerif;
}
*/
}
}

@ -1,27 +1,27 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
namespace WF_WebAdmin.Model namespace WF_WebAdmin.Model
{ {
public class QuoteModel public class QuoteModel
{ {
public int Id { get; set; } public int Id { get; set; }
[Required] [Required]
[StringLength(300, ErrorMessage = "La citation ne peut pas dépasser les 300 caractère.")] [StringLength(300, ErrorMessage = "La citation ne peut pas dépasser les 300 caractère.")]
public string Content { get; set; } public string? Content { get; set; }
public int Like { get; set; } public int Like { get; set; }
[Required] [Required]
[StringLength(2, ErrorMessage = "La langue ne peut pas dépasser 2 caractère.")] [StringLength(2, ErrorMessage = "La langue ne peut pas dépasser 2 caractère.")]
public string Langue { get; set; } public string? Langue { get; set; }
public string Charac { get; set; } public string? Charac { get; set; }
public string ImgPath { get; set; } public string? ImgPath { get; set; }
public string TitleSrc { get; set; } public string? TitleSrc { get; set; }
public DateTime DateSrc { get; set; } public DateTime DateSrc { get; set; }
public string UserProposition { get; set; } public string? UserProposition { get; set; }
public bool IsValid { get; set; } public bool IsValid { get; set; }
} }
} }

@ -1,11 +1,11 @@
namespace WF_WebAdmin.Model namespace WF_WebAdmin.Model
{ {
public class Source public class Source
{ {
public int id_source { get; set; } public int id_source { get; set; }
public string title { get; set; } public string? title { get; set; }
public int date { get; set; } public int date { get; set; }
} }
} }

@ -1,26 +1,26 @@
namespace WF_WebAdmin.Model namespace WF_WebAdmin.Model
{ {
public class User public class User
{ {
public int Id { get; set; } public int Id { get; set; }
public string Image { get; set; } public string? Image { get; set; }
public string Name { get; set; } public string Name { get; set; }
public string Email { get; set; } public string Email { get; set; }
public DateTime DateCreation { get; set; } public DateTime DateCreation { get; set; }
public Boolean IsAdmin { get; set; } public Boolean IsAdmin { get; set; }
public List<Commentary> Comments { get; set; } public List<Commentary>? Comments { get; set; }
public User(string image, string name, string email, DateTime dateCreation, bool isAdmin) public User(string image, string name, string email, DateTime dateCreation, bool isAdmin)
{ {
this.Image = image; this.Image = image;
this.Name = name; this.Name = name;
this.Email = email; this.Email = email;
this.DateCreation = dateCreation; this.DateCreation = dateCreation;
IsAdmin = isAdmin; IsAdmin = isAdmin;
} }
public User() { } public User() { }
} }
} }

@ -1,22 +1,22 @@
using System; using System;
namespace WF_WebAdmin.Model namespace WF_WebAdmin.Model
{ {
public class UserLogin public class UserLogin
{ {
public int Id { get; set; } public int Id { get; set; }
public string Image { get; set; } public string? Image { get; set; }
public string Name { get; set;} public string Name { get; set;}
public Boolean IsAdmin { get; set; } public Boolean IsAdmin { get; set; }
public string Mdp { get; set; } public string Mdp { get; set; }
public UserLogin(int id,string image, string name, bool isAdmin, string mdp) public UserLogin(int id,string image, string name, bool isAdmin, string mdp)
{ {
Id = id; Id = id;
this.Image = image; this.Image = image;
this.Name = name; this.Name = name;
this.IsAdmin = isAdmin; this.IsAdmin = isAdmin;
this.Mdp = mdp; this.Mdp = mdp;
} }
public UserLogin() { } public UserLogin() { }
} }
} }

@ -1,42 +1,42 @@
using Blazorise.DataGrid; using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using System.Security.Claims; using System.Security.Claims;
using WF_WebAdmin.Model; using WF_WebAdmin.Model;
namespace WF_WebAdmin.Pages namespace WF_WebAdmin.Pages
{ {
public partial class Accueil public partial class Accueil
{ {
private Quote[] Dailyquote; private Quote[]? Dailyquote;
[Inject] [Inject]
public ILogger<Accueil> Logger { get; set; } public ILogger<Accueil>? Logger { get; set; }
[Inject] [Inject]
public HttpClient Http { get; set; } public HttpClient? Http { get; set; }
[Inject] [Inject]
public NavigationManager NavigationManager { get; set; } public NavigationManager? NavigationManager { get; set; }
[Inject] [Inject]
public IStringLocalizer<Accueil> Localizer { get; set; } public IStringLocalizer<Accueil>? Localizer { get; set; }
/// <summary> /// <summary>
/// This method is called during the initialization of the Blazor component. /// This method is called during the initialization of the Blazor component.
/// It is asynchronous and is used to load data or perform actions before the component is rendered. /// It is asynchronous and is used to load data or perform actions before the component is rendered.
/// </summary> /// </summary>
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
Dailyquote = await Http.GetFromJsonAsync<Quote[]>($"{NavigationManager.BaseUri}fake-dataDailyQuote.json"); Dailyquote = await Http.GetFromJsonAsync<Quote[]>($"{NavigationManager.BaseUri}fake-dataDailyQuote.json");
} }
private void RandomDailyquote() private void RandomDailyquote()
{ {
//fonction a compléter //fonction a compléter
LoggerSaveStub.Log(Logger, LogLevel.Information, "Random change of quote of the day"); LoggerSaveStub.Log(Logger, LogLevel.Information, "Random change of quote of the day");
} }
} }
} }

@ -1,140 +1,140 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using WF_WebAdmin.Service; using WF_WebAdmin.Service;
using WF_WebAdmin.Model; using WF_WebAdmin.Model;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Security.Claims; using System.Security.Claims;
namespace WF_WebAdmin.Pages namespace WF_WebAdmin.Pages
{ {
public partial class AddQuiz public partial class AddQuiz
{ {
[Inject] [Inject]
public ILogger<AddQuiz> Logger { get; set; } public ILogger<AddQuiz> Logger { get; set; }
[Inject] [Inject]
public IStringLocalizer<AddQuiz> Localizer { get; set; } public IStringLocalizer<AddQuiz> Localizer { get; set; }
[Inject] [Inject]
private IQuizService quizService { get; set; } private IQuizService quizService { get; set; }
[Inject] [Inject]
public NavigationManager NavigationManager { get; set; } public NavigationManager NavigationManager { get; set; }
private QuizModel QuizModel = new(); private QuizModel QuizModel = new();
/// <summary> /// <summary>
/// Handles the valid submission of a quiz form. /// Handles the valid submission of a quiz form.
/// This method is triggered when the form is successfully validated and the user submits the quiz data. /// This method is triggered when the form is successfully validated and the user submits the quiz data.
/// It retrieves the current quiz count, increments it, and then adds a new quiz entry to the quiz service. /// It retrieves the current quiz count, increments it, and then adds a new quiz entry to the quiz service.
/// Finally, it navigates to the "modifquiz" page. /// Finally, it navigates to the "modifquiz" page.
/// </summary> /// </summary>
private async void HandleValidSubmit() private async Task HandleValidSubmit()
{ {
// Declare a variable to hold the ID of the new quiz. // Declare a variable to hold the ID of the new quiz.
int id; int id;
// Get the current number of quizzes from the quiz service. // Get the current number of quizzes from the quiz service.
id = await quizService.getNbQuiz(); id = await quizService.getNbQuiz();
// Increment the quiz ID for the new quiz. // Increment the quiz ID for the new quiz.
id++; id++;
// Create a new quiz and add it using the quiz service. // Create a new quiz and add it using the quiz service.
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Creation of the {QuizModel.Question} question"); LoggerSaveStub.Log(Logger, LogLevel.Information, $"Creation of the {QuizModel.Question} question");
await quizService.addQuiz(new Quiz( await quizService.addQuiz(new Quiz(
id, // New quiz ID id, // New quiz ID
validateInformation(QuizModel.Question), // Validated question validateInformation(QuizModel.Question), // Validated question
validateInformation(QuizModel.AnswerA), // Validated answer A validateInformation(QuizModel.AnswerA), // Validated answer A
validateInformation(QuizModel.AnswerB), // Validated answer B validateInformation(QuizModel.AnswerB), // Validated answer B
validateInformation(QuizModel.AnswerC), // Validated answer C validateInformation(QuizModel.AnswerC), // Validated answer C
validateInformation(QuizModel.AnswerD), // Validated answer D validateInformation(QuizModel.AnswerD), // Validated answer D
validateReponse(QuizModel.CAnswer) // Validated correct answer validateReponse(QuizModel.CAnswer) // Validated correct answer
)); ));
// Navigate to the "modifquiz" page after adding the quiz. // Navigate to the "modifquiz" page after adding the quiz.
NavigationManager.NavigateTo("modifquiz"); NavigationManager.NavigateTo("modifquiz");
} }
/// <summary> /// <summary>
/// Handles the change of the correct answer for the quiz. /// Handles the change of the correct answer for the quiz.
/// This method is triggered when the user selects or changes the correct answer for the quiz question. /// This method is triggered when the user selects or changes the correct answer for the quiz question.
/// It updates the QuizModel's Correct Answer property with the selected answer. /// It updates the QuizModel's Correct Answer property with the selected answer.
/// </summary> /// </summary>
/// <param name="item">The selected answer that will be marked as the correct answer.</param> /// <param name="item">The selected answer that will be marked as the correct answer.</param>
/// <param name="checkedValue">The value of the selected option, typically used for validation or additional logic.</param> /// <param name="checkedValue">The value of the selected option, typically used for validation or additional logic.</param>
private void OnCAwnserChange(string item, object checkedValue) private void OnCAwnserChange(string item, object checkedValue)
{ {
// Update the correct answer in the QuizModel with the selected answer. // Update the correct answer in the QuizModel with the selected answer.
QuizModel.CAnswer = item; QuizModel.CAnswer = item;
} }
/// <summary> /// <summary>
/// Validates the provided string item. /// Validates the provided string item.
/// This method is used to validate input data, but the validation logic is not yet implemented. /// This method is used to validate input data, but the validation logic is not yet implemented.
/// </summary> /// </summary>
/// <param name="item">The string input to be validated.</param> /// <param name="item">The string input to be validated.</param>
/// <returns> /// <returns>
/// Returns the input string as it is for now. The validation logic is yet to be implemented. /// Returns the input string as it is for now. The validation logic is yet to be implemented.
/// </returns> /// </returns>
private static string validateInformation(string item) private static string validateInformation(string item)
{ {
return item; // VALIDATION A FAIRE return item; // VALIDATION A FAIRE
} }
/// <summary> /// <summary>
/// Validates the provided answer item (A, B, C, or D) for the quiz. /// Validates the provided answer item (A, B, C, or D) for the quiz.
/// This method ensures that the input corresponds to one of the allowed values for the correct answer. /// This method ensures that the input corresponds to one of the allowed values for the correct answer.
/// If the input is invalid or null, it throws an exception and returns a default value ("A") in case of error. /// If the input is invalid or null, it throws an exception and returns a default value ("A") in case of error.
/// </summary> /// </summary>
/// <param name="item">The answer item (A, B, C, or D) to be validated.</param> /// <param name="item">The answer item (A, B, C, or D) to be validated.</param>
/// <returns> /// <returns>
/// Returns the input item if valid (A, B, C, or D). If the item is invalid or null, it returns a default value ("A"). /// Returns the input item if valid (A, B, C, or D). If the item is invalid or null, it returns a default value ("A").
/// </returns> /// </returns>
private static string validateReponse(string item) private static string validateReponse(string item)
{ {
try try
{ {
// Check if the item is not null or empty // Check if the item is not null or empty
if (!string.IsNullOrEmpty(item)) if (!string.IsNullOrEmpty(item))
{ {
// Validate that the item is one of the allowed values: A, B, C, or D // Validate that the item is one of the allowed values: A, B, C, or D
switch (item) switch (item)
{ {
case "A": case "A":
break; break;
case "B": case "B":
break; break;
case "C": case "C":
break; break;
case "D": case "D":
break; break;
default: default:
// Throw exception if the item is not one of the allowed answers // Throw exception if the item is not one of the allowed answers
throw new InvalidDataException("Invalid item (validateReponse) : item must be A,B,C or D " + item + " given."); throw new InvalidDataException("Invalid item (validateReponse) : item must be A,B,C or D " + item + " given.");
} }
} }
else else
{ {
// Throw exception if the item is null or empty // Throw exception if the item is null or empty
throw new ArgumentNullException("Invalid item (validateReponse): null given."); throw new ArgumentNullException("Invalid item (validateReponse): null given.");
} }
// Return the validated item // Return the validated item
return item; return item;
} }
catch (Exception ex) catch (Exception ex)
{ {
// In case of an exception, return a default answer ("A") // In case of an exception, return a default answer ("A")
return "A"; // Default Argument return "A"; // Default Argument
} }
} }
} }
} }

@ -0,0 +1,14 @@
@page "/graph"
@using Syncfusion.Blazor.Charts
<script src=https://cdn.syncfusion.com/blazor/22.1.38/syncfusion-blazor.min.js type="text/javascript"></script>
<SfChart>
<ChartPrimaryXAxis ValueType="Syncfusion.Blazor.Charts.ValueType.Category"></ChartPrimaryXAxis>
<ChartSeriesCollection>
<ChartSeries DataSource="@Sales" Opacity="1" Fill="blue" XName="Month" YName="SalesValue" Type="ChartSeriesType.Column" ColumnSpacing="0.2" ColumnWidth="0.8">
</ChartSeries>
</ChartSeriesCollection>
</SfChart>

@ -0,0 +1,92 @@
using Microsoft.AspNetCore.Components;
using MudBlazor;
using Syncfusion.Blazor.Charts.Chart.Internal;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using WF_WebAdmin.Model;
using WF_WebAdmin.Service;
namespace WF_WebAdmin.Pages
{
public class SalesInfo
{
public string Month { get; set; }
public double SalesValue { get; set; }
}
public partial class ComposentComplex : ComponentBase
{
[Inject] public ICommentaryService CommentaryService { get; set; } = default!;
public List<string> Labels { get; set; } = new();
public List<double[]> ChartData { get; set; } = new();
public List<int> AvailableYears { get; set; } = new();
public int SelectedYear { get; set; }
private List<Commentary> AllComments = new();
public List<SalesInfo> Sales = new List<SalesInfo>
{
new SalesInfo { Month = "Jan", SalesValue = 35 },
new SalesInfo { Month = "Feb", SalesValue = 28 },
new SalesInfo { Month = "Mar", SalesValue = 34 },
new SalesInfo { Month = "Apr", SalesValue = 28 },
new SalesInfo { Month = "May", SalesValue = 40 },
new SalesInfo { Month = "Jun", SalesValue = 32 },
new SalesInfo { Month = "Jul", SalesValue = 35 },
new SalesInfo { Month = "Aug", SalesValue = 55 },
new SalesInfo { Month = "Sep", SalesValue = 38 },
new SalesInfo { Month = "Oct", SalesValue = 30 },
new SalesInfo { Month = "Nov", SalesValue = 25 },
new SalesInfo { Month = "Dec", SalesValue = 32 }
};
protected override async Task OnInitializedAsync()
{
// Charger tous les commentaires
AllComments = await CommentaryService.GetCommentsAsync();
if (!AllComments.Any())
{
Labels = new List<string> { "Aucun commentaire" };
ChartData = new List<double[]> { new double[] { 0 } };
return;
}
AvailableYears = AllComments
.Select(c => c.DateCreation.Year)
.Distinct()
.OrderBy(y => y)
.ToList();
SelectedYear = AvailableYears.Max();
UpdateChartData(SelectedYear);
}
private void UpdateChartData(int newYear)
{
SelectedYear = newYear;
var filteredComments = AllComments
.Where(c => c.DateCreation.Year == SelectedYear)
.ToList();
if (!filteredComments.Any())
{
Labels = new List<string> { "Aucun commentaire" };
ChartData = new List<double[]> { new double[] { 0 } };
return;
}
foreach (var sale in Sales)
{
sale.SalesValue = filteredComments.Count(c => c.DateCreation.Month.ToString("MMM", CultureInfo.InvariantCulture) == sale.Month);
}
}
}
}

@ -1,7 +1,7 @@
using Blazorise.DataGrid; using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration.UserSecrets; using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using System.Collections.Generic; using System.Collections.Generic;
using WF_WebAdmin.Model; using WF_WebAdmin.Model;
@ -11,12 +11,12 @@ namespace WF_WebAdmin.Pages
{ {
public partial class DeleteUser public partial class DeleteUser
{ {
[Inject] [Inject]
public ILogger<DeleteUser> Logger { get; set; } public ILogger<DeleteUser> Logger { get; set; }
private List<User> users;
private List<User> users;
private bool showDeletePopup = false;
private bool showModifyPopup = false; private bool showModifyPopup = false;
private User userToDelete = null; private User userToDelete = null;
private User selectedUser; private User selectedUser;
@ -37,180 +37,180 @@ namespace WF_WebAdmin.Pages
[Inject] [Inject]
private IUserService userService { get; set; } private IUserService userService { get; set; }
[Inject] [Inject]
public IStringLocalizer<DeleteUser> Localizer { get; set; } public IStringLocalizer<DeleteUser> Localizer { get; set; }
/// <summary> /// <summary>
/// This method is called when the component is initialized. /// This method is called when the component is initialized.
/// It is an asynchronous method that retrieves a list of users from the user service. /// It is an asynchronous method that retrieves a list of users from the user service.
/// The method fetches a subset of users with a specified maximum value and page number (1 in this case). /// The method fetches a subset of users with a specified maximum value and page number (1 in this case).
/// </summary> /// </summary>
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
// Retrieve a list of users using the user service. The number of users and page number are specified. // Retrieve a list of users using the user service. The number of users and page number are specified.
// MaxValue determines how many users to retrieve, and '1' refers to the first page of results. // MaxValue determines how many users to retrieve, and '1' refers to the first page of results.
users = await userService.getSomeUser(MaxValue, 1); users = await userService.getSomeUser(MaxValue, 1);
} }
/// <summary> /// <summary>
/// Handles the event when data is read in the data grid. /// Handles the event when data is read in the data grid.
/// This method is triggered during pagination or when data is loaded into the grid. /// This method is triggered during pagination or when data is loaded into the grid.
/// It asynchronously fetches a page of users based on the requested page size and page number, /// It asynchronously fetches a page of users based on the requested page size and page number,
/// and updates the list of users and total item count if the operation is not cancelled. /// and updates the list of users and total item count if the operation is not cancelled.
/// </summary> /// </summary>
/// <param name="e">The event arguments containing pagination details (page size and page number) and a cancellation token.</param> /// <param name="e">The event arguments containing pagination details (page size and page number) and a cancellation token.</param>
private async Task OnReadData(DataGridReadDataEventArgs<User> e) private async Task OnReadData(DataGridReadDataEventArgs<User> e)
{ {
// If the cancellation token is requested, exit the method without processing the request. // If the cancellation token is requested, exit the method without processing the request.
if (e.CancellationToken.IsCancellationRequested) if (e.CancellationToken.IsCancellationRequested)
{ {
return; return;
} }
// Fetch a page of users from the user service using the page size and page number provided by the event arguments. // Fetch a page of users from the user service using the page size and page number provided by the event arguments.
var response = await userService.getSomeUser(e.PageSize, e.Page); var response = await userService.getSomeUser(e.PageSize, e.Page);
// If the operation is not cancelled, update the total number of users and the list of users. // If the operation is not cancelled, update the total number of users and the list of users.
if (!e.CancellationToken.IsCancellationRequested) if (!e.CancellationToken.IsCancellationRequested)
{ {
totalItem = await userService.getNbUser(); // Get the total number of users totalItem = await userService.getNbUser(); // Get the total number of users
users = new List<User>(response.ToArray()); // Store the retrieved users in the users list users = new List<User>(response.ToArray()); // Store the retrieved users in the users list
page = e.Page; // Update the current page number page = e.Page; // Update the current page number
} }
} }
// ------- Popup remove user ------- // ------- Popup remove user -------
/// <summary> /// <summary>
/// Displays a confirmation popup to confirm the deletion of a user. /// Displays a confirmation popup to confirm the deletion of a user.
/// This method is triggered when the user intends to delete a user, /// This method is triggered when the user intends to delete a user,
/// and it sets the user to be deleted and shows the confirmation popup. /// and it sets the user to be deleted and shows the confirmation popup.
/// </summary> /// </summary>
/// <param name="user">The user to be deleted, which is passed to the method for confirmation.</param> /// <param name="user">The user to be deleted, which is passed to the method for confirmation.</param>
private void ShowConfirmation(User user) private void ShowConfirmation(User user)
{ {
// Set the user to be deleted and show the confirmation popup. // Set the user to be deleted and show the confirmation popup.
userToDelete = user; // Store the user to be deleted in a variable userToDelete = user; // Store the user to be deleted in a variable
showPopupDelete = true; // Display the confirmation popup showPopupDelete = true; // Display the confirmation popup
} }
/// <summary> /// <summary>
/// Displays a confirmation popup for modifying a user's information. /// Displays a confirmation popup for modifying a user's information.
/// This method is triggered when the user intends to modify a specific user's data, /// This method is triggered when the user intends to modify a specific user's data,
/// and it sets the selected user and shows the modification confirmation popup. /// and it sets the selected user and shows the modification confirmation popup.
/// </summary> /// </summary>
/// <param name="user">The user whose information is to be modified, passed to the method for confirmation.</param> /// <param name="user">The user whose information is to be modified, passed to the method for confirmation.</param>
private void ShowModifyConfirmation(User user) private void ShowModifyConfirmation(User user)
{ {
// Set the selected user and show the modification confirmation popup. // Set the selected user and show the modification confirmation popup.
selectedUser = user; // Store the user to be modified selectedUser = user; // Store the user to be modified
showModifyPopup = true; // Display the confirmation popup for modification showModifyPopup = true; // Display the confirmation popup for modification
} }
/// <summary> /// <summary>
/// Removes the specified user from the system. /// Removes the specified user from the system.
/// This method is triggered when the user confirms the deletion of a user. /// This method is triggered when the user confirms the deletion of a user.
/// It calls the user service to remove the user, closes the confirmation popup, /// It calls the user service to remove the user, closes the confirmation popup,
/// and then refreshes the list of users by fetching the updated data. /// and then refreshes the list of users by fetching the updated data.
/// </summary> /// </summary>
private async Task RemoveUser() private async Task RemoveUser()
{ {
// Check if there is a user to delete // Check if there is a user to delete
if (userToDelete != null) if (userToDelete != null)
{ {
// Remove the selected user from the system using the user service // Remove the selected user from the system using the user service
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Delete user {userToDelete.Name}"); LoggerSaveStub.Log(Logger, LogLevel.Information, $"Delete user {userToDelete.Name}");
await userService.removeUser(userToDelete); await userService.removeUser(userToDelete);
// Close the confirmation popup after the deletion // Close the confirmation popup after the deletion
ClosePopup(); ClosePopup();
// Refresh the list of users by fetching the updated data from the user service // Refresh the list of users by fetching the updated data from the user service
var response = await userService.getSomeUser(MaxValue, page); var response = await userService.getSomeUser(MaxValue, page);
// Update the users list with the latest data // Update the users list with the latest data
users = new List<User>(response.ToArray()); users = new List<User>(response.ToArray());
} }
} }
/// <summary> /// <summary>
/// Modifies the selected user's information. /// Modifies the selected user's information.
/// This method is triggered when the user confirms the modification of a user's details. /// This method is triggered when the user confirms the modification of a user's details.
/// It calls the user service to update the user's information and then closes the modification popup. /// It calls the user service to update the user's information and then closes the modification popup.
/// </summary> /// </summary>
private async Task ModifyUser() private async Task ModifyUser()
{ {
// Update the selected user's information using the user service // Update the selected user's information using the user service
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Modification of user {selectedUser.Name}"); LoggerSaveStub.Log(Logger, LogLevel.Information, $"Modification of user {selectedUser.Name}");
await userService.updateUser(selectedUser); await userService.updateUser(selectedUser);
// Close the modification popup after the update is complete // Close the modification popup after the update is complete
ClosePopup(); ClosePopup();
} }
/// <summary> /// <summary>
/// Closes all open popups in the UI by setting their visibility flags to false. /// Closes all open popups in the UI by setting their visibility flags to false.
/// This method is typically called after an action (like deleting or modifying a user) /// This method is typically called after an action (like deleting or modifying a user)
/// to hide any active popups and reset the UI state. /// to hide any active popups and reset the UI state.
/// </summary> /// </summary>
private void ClosePopup() private void ClosePopup()
{ {
// Set all popup visibility flags to false to hide the popups // Set all popup visibility flags to false to hide the popups
showDeletePopup = false; // Close the delete confirmation popup showDeletePopup = false; // Close the delete confirmation popup
showModifyPopup = false; // Close the modify confirmation popup showModifyPopup = false; // Close the modify confirmation popup
showPopupDelete = false; // Close any additional delete popups showPopupDelete = false; // Close any additional delete popups
showPopupAdmin = false; // Close the admin-related popup (if any) showPopupAdmin = false; // Close the admin-related popup (if any)
} }
// ------- Popup admin ------- // ------- Popup admin -------
/// <summary> /// <summary>
/// Displays a confirmation popup to confirm the promotion of a user to admin status. /// Displays a confirmation popup to confirm the promotion of a user to admin status.
/// This method is triggered when the user intends to promote a specific user to admin. /// This method is triggered when the user intends to promote a specific user to admin.
/// It sets the selected user to be promoted and shows the confirmation popup for admin promotion. /// It sets the selected user to be promoted and shows the confirmation popup for admin promotion.
/// </summary> /// </summary>
/// <param name="user">The user to be promoted to admin, passed to the method for confirmation.</param> /// <param name="user">The user to be promoted to admin, passed to the method for confirmation.</param>
private void ShowConfirmationAdmin(User user) private void ShowConfirmationAdmin(User user)
{ {
// Set the user to be promoted to admin and show the confirmation popup. // Set the user to be promoted to admin and show the confirmation popup.
userToAdmin = user; // Store the user to be promoted userToAdmin = user; // Store the user to be promoted
showPopupAdmin = true; // Display the confirmation popup for admin promotion showPopupAdmin = true; // Display the confirmation popup for admin promotion
} }
/// <summary> /// <summary>
/// Toggles the admin status of the selected user. /// Toggles the admin status of the selected user.
/// This method checks the current admin status of the user, and if the user is not an admin, /// This method checks the current admin status of the user, and if the user is not an admin,
/// it promotes them to admin. If the user is already an admin, it demotes them. /// it promotes them to admin. If the user is already an admin, it demotes them.
/// After the change, the user's information is updated, and the confirmation popup is closed. /// After the change, the user's information is updated, and the confirmation popup is closed.
/// </summary> /// </summary>
private async Task setAdmin() private async Task setAdmin()
{ {
// Check if the user is not already an admin // Check if the user is not already an admin
if (!userToAdmin.IsAdmin) if (!userToAdmin.IsAdmin)
{ {
// Promote the user to admin // Promote the user to admin
LoggerSaveStub.Log(Logger, LogLevel.Information, $"User {userToAdmin.Name} is now administrator"); LoggerSaveStub.Log(Logger, LogLevel.Information, $"User {userToAdmin.Name} is now administrator");
userToAdmin.IsAdmin = true; userToAdmin.IsAdmin = true;
await userService.updateUser(userToAdmin); // Update the user status in the service await userService.updateUser(userToAdmin); // Update the user status in the service
ClosePopup(); // Close the confirmation popup ClosePopup(); // Close the confirmation popup
} }
else else
{ {
// Demote the user from admin to normal user // Demote the user from admin to normal user
LoggerSaveStub.Log(Logger, LogLevel.Information, $"User {userToAdmin.Name} is no longer an administator"); LoggerSaveStub.Log(Logger, LogLevel.Information, $"User {userToAdmin.Name} is no longer an administator");
userToAdmin.IsAdmin = false; userToAdmin.IsAdmin = false;
await userService.updateUser(userToAdmin); // Update the user status in the service await userService.updateUser(userToAdmin); // Update the user status in the service
ClosePopup(); // Close the confirmation popup ClosePopup(); // Close the confirmation popup
} }
} }

@ -1,100 +1,100 @@
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using System.Security.Claims; using System.Security.Claims;
using WF_WebAdmin.Model; using WF_WebAdmin.Model;
using WF_WebAdmin.Service; using WF_WebAdmin.Service;
namespace WF_WebAdmin.Pages namespace WF_WebAdmin.Pages
{ {
public partial class Edit public partial class Edit
{ {
[Parameter] [Parameter]
public int Id { get; set; } public int Id { get; set; }
[Inject] [Inject]
public ILogger<Edit> Logger { get; set; } public ILogger<Edit> Logger { get; set; }
[Inject] [Inject]
private IQuoteService quoteService { get; set; } private IQuoteService quoteService { get; set; }
[Inject] [Inject]
public NavigationManager NavigationManager { get; set; } public NavigationManager NavigationManager { get; set; }
private Quote q{ get; set; } private Quote q{ get; set; }
private QuoteModel quoteModel = new(); private QuoteModel quoteModel = new();
private List<Character> charac = new List<Character>(); private List<Character> charac = new List<Character>();
private List<Source> src = new List<Source>(); private List<Source> src = new List<Source>();
/// <summary> /// <summary>
/// Asynchronously initializes the component by loading data related to a quote. /// Asynchronously initializes the component by loading data related to a quote.
/// This method fetches a specific quote based on the provided ID and populates the `quoteModel` /// This method fetches a specific quote based on the provided ID and populates the `quoteModel`
/// with the quote's content, language, character, source, and other associated data. /// with the quote's content, language, character, source, and other associated data.
/// It also loads additional data such as character and source information for the quote. /// It also loads additional data such as character and source information for the quote.
/// </summary> /// </summary>
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
// Fetch the quote data based on the provided ID. // Fetch the quote data based on the provided ID.
q = await quoteService.getOnequote(Id); q = await quoteService.getOnequote(Id);
// Populate the quoteModel with the data from the retrieved quote. // Populate the quoteModel with the data from the retrieved quote.
quoteModel.Content = q.Content; quoteModel.Content = q.Content;
quoteModel.Langue = q.Langue; quoteModel.Langue = q.Langue;
quoteModel.Charac = q.Charac; quoteModel.Charac = q.Charac;
quoteModel.TitleSrc = q.TitleSrc; quoteModel.TitleSrc = q.TitleSrc;
quoteModel.Id = q.Id; quoteModel.Id = q.Id;
quoteModel.Like = q.Like; quoteModel.Like = q.Like;
quoteModel.ImgPath = q.ImgPath; quoteModel.ImgPath = q.ImgPath;
quoteModel.DateSrc = q.DateSrc; quoteModel.DateSrc = q.DateSrc;
quoteModel.UserProposition = q.UserProposition; quoteModel.UserProposition = q.UserProposition;
quoteModel.IsValid = q.IsValid; quoteModel.IsValid = q.IsValid;
// Fetch additional data related to the quote, such as character and source. // Fetch additional data related to the quote, such as character and source.
charac = await quoteService.getChar(); charac = await quoteService.getChar();
src = await quoteService.getSrc(); src = await quoteService.getSrc();
} }
/// <summary> /// <summary>
/// Handles the submission of a valid form for updating a quote. /// Handles the submission of a valid form for updating a quote.
/// This method takes the data from `quoteModel`, updates the selected quote (`q`) with the new values, /// This method takes the data from `quoteModel`, updates the selected quote (`q`) with the new values,
/// and then calls the `quoteService.updateQuote` method to persist the changes. /// and then calls the `quoteService.updateQuote` method to persist the changes.
/// After updating, it navigates to the "modifquote" page. /// After updating, it navigates to the "modifquote" page.
/// </summary> /// </summary>
protected async void HandleValidSubmit() protected async Task HandleValidSubmit()
{ {
// Update the properties of the selected quote (`q`) with the data from `quoteModel`. // Update the properties of the selected quote (`q`) with the data from `quoteModel`.
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Editing the quote {q.Content}"); LoggerSaveStub.Log(Logger, LogLevel.Information, $"Editing the quote {q.Content}");
q.Content = quoteModel.Content; q.Content = quoteModel.Content;
q.Langue = quoteModel.Langue; q.Langue = quoteModel.Langue;
q.TitleSrc = quoteModel.TitleSrc; q.TitleSrc = quoteModel.TitleSrc;
q.Charac = quoteModel.Charac; q.Charac = quoteModel.Charac;
// Call the quote service to update the quote in the data source. // Call the quote service to update the quote in the data source.
await quoteService.updateQuote(q); await quoteService.updateQuote(q);
// Navigate to the "modifquote" page after updating the quote. // Navigate to the "modifquote" page after updating the quote.
NavigationManager.NavigateTo("modifquote"); NavigationManager.NavigateTo("modifquote");
} }
/// <summary> /// <summary>
/// Handles the language change event for the quote. /// Handles the language change event for the quote.
/// This method updates the `Langue` property of the `quoteModel` based on the selected language (`item`). /// This method updates the `Langue` property of the `quoteModel` based on the selected language (`item`).
/// It only accepts "fr" (French) or "en" (English) as valid language options. /// It only accepts "fr" (French) or "en" (English) as valid language options.
/// </summary> /// </summary>
/// <param name="item">The selected language ("fr" or "en") passed to the method.</param> /// <param name="item">The selected language ("fr" or "en") passed to the method.</param>
/// <param name="checkedValue">The checked value (unused in this method but may be used for other purposes).</param> /// <param name="checkedValue">The checked value (unused in this method but may be used for other purposes).</param>
private void OnlangChange(string item, object checkedValue) private void OnlangChange(string item, object checkedValue)
{ {
// Check if the selected language is either "fr" or "en" // Check if the selected language is either "fr" or "en"
if (item == "fr" || item == "en") if (item == "fr" || item == "en")
{ {
// Update the Langue property of the quoteModel with the selected language // Update the Langue property of the quoteModel with the selected language
quoteModel.Langue = item; quoteModel.Langue = item;
} }
} }
} }
} }

@ -1,42 +1,42 @@
@page @page
@model WF_WebAdmin.Pages.ErrorModel @model WF_WebAdmin.Pages.ErrorModel
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>Error</title> <title>error</title>
<link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet" /> <link href="~/css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="~/css/site.css" rel="stylesheet" asp-append-version="true" /> <link href="~/css/site.css" rel="stylesheet" asp-append-version="true" />
</head> </head>
<body> <body>
<div class="main"> <div class="main">
<div class="content px-4"> <div class="content px-4">
<h1 class="text-danger">Error.</h1> <h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2> <h2 class="text-danger">An error occurred while processing your request.</h2>
@if (Model.ShowRequestId) @if (Model.ShowRequestId)
{ {
<p> <p>
<strong>Request ID:</strong> <code>@Model.RequestId</code> <strong>Request ID:</strong> <code>@Model.RequestId</code>
</p> </p>
} }
<h3>Development Mode</h3> <h3>Development Mode</h3>
<p> <p>
Swapping to the <strong>Development</strong> environment displays detailed information about the error that occurred. Swapping to the <strong>development</strong> environment displays detailed information about the error that occurred.
</p> </p>
<p> <p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong> <strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users. It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong> For local debugging, enable the <strong>development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app. and restarting the app.
</p> </p>
</div> </div>
</div> </div>
</body> </body>
</html> </html>

@ -1,40 +1,40 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Diagnostics; using System.Diagnostics;
namespace WF_WebAdmin.Pages namespace WF_WebAdmin.Pages
{ {
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken] [IgnoreAntiforgeryToken]
public class ErrorModel : PageModel public class ErrorModel : PageModel
{ {
public string? RequestId { get; set; } public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
private readonly ILogger<ErrorModel> _logger;
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="ErrorModel"/> class. /// Initializes a new instance of the <see cref="ErrorModel"/> class.
/// This constructor is used to inject the <see cref="ILogger{ErrorModel}"/> into the model for logging purposes. /// This constructor is used to inject the <see cref="ILogger{ErrorModel}"/> into the model for logging purposes.
/// </summary> /// </summary>
/// <param name="logger">An instance of the <see cref="ILogger{ErrorModel}"/> used for logging error-related information.</param> /// <param name="logger">An instance of the <see cref="ILogger{ErrorModel}"/> used for logging error-related information.</param>
public ErrorModel(ILogger<ErrorModel> logger) public ErrorModel(ILogger<ErrorModel> logger)
{ {
_logger = logger; _logger = logger;
} }
/// <summary> /// <summary>
/// Handles the GET request for the page or endpoint. /// Handles the GET request for the page or endpoint.
/// This method retrieves the request ID for tracing purposes, using the `Activity.Current?.Id` /// This method retrieves the request ID for tracing purposes, using the `Activity.Current?.Id`
/// if it's available, or the `HttpContext.TraceIdentifier` as a fallback if no current activity ID is present. /// if it's available, or the `HttpContext.TraceIdentifier` as a fallback if no current activity ID is present.
/// </summary> /// </summary>
public void OnGet() public void OnGet()
{ {
// Retrieve the current request ID for tracing // Retrieve the current request ID for tracing
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier; RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
} }
} }
} }

@ -1,162 +1,162 @@
using Blazorise.DataGrid; using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using System.Security.Claims; using System.Security.Claims;
using WF_WebAdmin.Model; using WF_WebAdmin.Model;
using WF_WebAdmin.Service; using WF_WebAdmin.Service;
namespace WF_WebAdmin.Pages namespace WF_WebAdmin.Pages
{ {
public partial class ModifQuiz public partial class ModifQuiz
{ {
private Quiz[] quiz; private Quiz[] quiz;
private int MaxValue = 5; private int MaxValue = 5;
private int totalItem; private int totalItem;
private bool showEditQuiz = false; private bool showEditQuiz = false;
private Quiz? selectedQuiz; private Quiz? selectedQuiz;
private bool showPopupDelete = false; private bool showPopupDelete = false;
private int page = 1; private int page = 1;
[Inject] [Inject]
public ILogger<ModifQuiz> Logger { get; set; } public ILogger<ModifQuiz> Logger { get; set; }
[Inject] [Inject]
public IStringLocalizer<ModifQuiz> Localizer { get; set; } public IStringLocalizer<ModifQuiz> Localizer { get; set; }
[Inject] [Inject]
public IQuizService QuizService { get; set; } public IQuizService QuizService { get; set; }
/// <summary> /// <summary>
/// Handles the data reading event for a data grid, fetching quiz data based on the specified page and page size. /// Handles the data reading event for a data grid, fetching quiz data based on the specified page and page size.
/// This method makes an asynchronous call to retrieve a specific page of quizzes and updates the `quiz` list and pagination details. /// This method makes an asynchronous call to retrieve a specific page of quizzes and updates the `quiz` list and pagination details.
/// If the cancellation token is requested, it exits early without making further calls or updates. /// If the cancellation token is requested, it exits early without making further calls or updates.
/// </summary> /// </summary>
/// <param name="e">The event arguments containing pagination details such as page size and page number.</param> /// <param name="e">The event arguments containing pagination details such as page size and page number.</param>
private async Task OnReadData(DataGridReadDataEventArgs<Quiz> e) private async Task OnReadData(DataGridReadDataEventArgs<Quiz> e)
{ {
// Check if the cancellation token has been requested // Check if the cancellation token has been requested
if (e.CancellationToken.IsCancellationRequested) if (e.CancellationToken.IsCancellationRequested)
{ {
return; return;
} }
// Fetch the quiz data for the specified page and page size // Fetch the quiz data for the specified page and page size
var response = await QuizService.getSommeQuiz(e.PageSize, e.Page); var response = await QuizService.getSommeQuiz(e.PageSize, e.Page);
// If cancellation hasn't been requested, process the data // If cancellation hasn't been requested, process the data
if (!e.CancellationToken.IsCancellationRequested) if (!e.CancellationToken.IsCancellationRequested)
{ {
// Get the total number of quizzes for pagination purposes // Get the total number of quizzes for pagination purposes
totalItem = await QuizService.getNbQuiz(); totalItem = await QuizService.getNbQuiz();
// Update the quiz data for the current page // Update the quiz data for the current page
quiz = response.ToArray(); quiz = response.ToArray();
// Update the current page number // Update the current page number
page = e.Page; page = e.Page;
} }
} }
/// <summary> /// <summary>
/// Handles the event when the "Edit" button is clicked for a quiz. /// Handles the event when the "Edit" button is clicked for a quiz.
/// This method checks if a valid quiz is passed. If so, it sets the `selectedQuiz` to the clicked quiz and shows the quiz edit modal. /// This method checks if a valid quiz is passed. If so, it sets the `selectedQuiz` to the clicked quiz and shows the quiz edit modal.
/// </summary> /// </summary>
/// <param name="quiz">The quiz object that was clicked for editing.</param> /// <param name="quiz">The quiz object that was clicked for editing.</param>
private void OnEditButtonClicked(Quiz quiz) private void OnEditButtonClicked(Quiz quiz)
{ {
// If the quiz is null, return early // If the quiz is null, return early
if (quiz == null) return; if (quiz == null) return;
// Set the selected quiz to the one clicked by the user // Set the selected quiz to the one clicked by the user
selectedQuiz = quiz; selectedQuiz = quiz;
// Show the modal or UI for editing the quiz // Show the modal or UI for editing the quiz
showEditQuiz = true; showEditQuiz = true;
} }
/// <summary> /// <summary>
/// Closes the open popups and resets any related states. /// Closes the open popups and resets any related states.
/// This method hides the quiz edit popup, the delete confirmation popup, and resets the selected quiz to `null`. /// This method hides the quiz edit popup, the delete confirmation popup, and resets the selected quiz to `null`.
/// </summary> /// </summary>
private void ClosePopup() private void ClosePopup()
{ {
// Hide the edit quiz popup // Hide the edit quiz popup
showEditQuiz = false; showEditQuiz = false;
// Hide the delete confirmation popup // Hide the delete confirmation popup
showPopupDelete = false; showPopupDelete = false;
// Reset the selected quiz to null // Reset the selected quiz to null
selectedQuiz = null; selectedQuiz = null;
} }
/// <summary> /// <summary>
/// Edits the selected quiz by updating it in the quiz service. /// Edits the selected quiz by updating it in the quiz service.
/// This method asynchronously sends the updated quiz data to the service for persistence. /// This method asynchronously sends the updated quiz data to the service for persistence.
/// After updating the quiz, it clears the selected quiz and closes any open popups. /// After updating the quiz, it clears the selected quiz and closes any open popups.
/// </summary> /// </summary>
private async Task EditQuiz() private async Task EditQuiz()
{ {
// Update the quiz in the service // Update the quiz in the service
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Editing the question {selectedQuiz.Question}"); LoggerSaveStub.Log(Logger, LogLevel.Information, $"Editing the question {selectedQuiz.Question}");
await QuizService.updateQuiz(selectedQuiz); await QuizService.updateQuiz(selectedQuiz);
// Clear the selected quiz after successful update // Clear the selected quiz after successful update
selectedQuiz = null; selectedQuiz = null;
// Close the popups after the edit operation // Close the popups after the edit operation
ClosePopup(); ClosePopup();
} }
/// <summary> /// <summary>
/// Handles the event when the delete action is triggered for a quiz. /// Handles the event when the delete action is triggered for a quiz.
/// This method sets the selected quiz to the one passed as a parameter and shows the delete confirmation popup. /// This method sets the selected quiz to the one passed as a parameter and shows the delete confirmation popup.
/// </summary> /// </summary>
/// <param name="q">The quiz to be deleted.</param> /// <param name="q">The quiz to be deleted.</param>
private void OnDelete(Quiz q) private void OnDelete(Quiz q)
{ {
// Set the selected quiz to the one passed in // Set the selected quiz to the one passed in
selectedQuiz = q; selectedQuiz = q;
// Show the delete confirmation popup // Show the delete confirmation popup
showPopupDelete = true; showPopupDelete = true;
} }
/// <summary> /// <summary>
/// Removes the selected quiz from the quiz service and updates the quiz list. /// Removes the selected quiz from the quiz service and updates the quiz list.
/// This method first checks if a quiz is selected, and if so, it deletes the quiz by calling the service. /// This method first checks if a quiz is selected, and if so, it deletes the quiz by calling the service.
/// After removal, it clears the `selectedQuiz`, updates the quiz list, and closes the delete confirmation popup. /// After removal, it clears the `selectedQuiz`, updates the quiz list, and closes the delete confirmation popup.
/// </summary> /// </summary>
private async void RemoveQuote() private async Task RemoveQuote()
{ {
// Check if a quiz is selected for deletion // Check if a quiz is selected for deletion
if (selectedQuiz != null) if (selectedQuiz != null)
{ {
// Remove the selected quiz from the service by its ID // Remove the selected quiz from the service by its ID
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Delete the question {selectedQuiz.Question}"); LoggerSaveStub.Log(Logger, LogLevel.Information, $"Delete the question {selectedQuiz.Question}");
await QuizService.removeQuiz(selectedQuiz.Id); await QuizService.removeQuiz(selectedQuiz.Id);
// Clear the selected quiz after successful removal // Clear the selected quiz after successful removal
selectedQuiz = null; selectedQuiz = null;
// Update the quiz list by fetching the latest data // Update the quiz list by fetching the latest data
var response = await QuizService.getSommeQuiz(MaxValue, page); var response = await QuizService.getSommeQuiz(MaxValue, page);
quiz = response.ToArray(); quiz = response.ToArray();
} }
// Close the delete confirmation popup // Close the delete confirmation popup
showPopupDelete = false; showPopupDelete = false;
} }
} }
} }

@ -1,135 +1,135 @@
using Blazorise.DataGrid; using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using System.Security.Claims; using System.Security.Claims;
using WF_WebAdmin.Model; using WF_WebAdmin.Model;
using WF_WebAdmin.Service; using WF_WebAdmin.Service;
namespace WF_WebAdmin.Pages namespace WF_WebAdmin.Pages
{ {
public partial class ModifQuote public partial class ModifQuote
{ {
private Quote[] quotes; private Quote[] quotes;
private int MaxValue = 5; private int MaxValue = 5;
private int totalItem; private int totalItem;
/*private bool showEditQuote = false;*/ /*private bool showEditQuote = false;*/
private Quote? selectedQuote; private Quote? selectedQuote;
private bool showPopupDelete = false; private bool showPopupDelete = false;
private int page = 1; private int page = 1;
[Inject] [Inject]
public ILogger<ModifQuote> Logger { get; set; } public ILogger<ModifQuote> Logger { get; set; }
[Inject] [Inject]
public IStringLocalizer<ModifQuote> Localizer { get; set; } public IStringLocalizer<ModifQuote> Localizer { get; set; }
[Inject] [Inject]
public IQuoteService QuoteService { get; set; } public IQuoteService QuoteService { get; set; }
/// <summary> /// <summary>
/// Handles the data reading event for a data grid, fetching quote data based on the specified page and page size. /// Handles the data reading event for a data grid, fetching quote data based on the specified page and page size.
/// This method makes an asynchronous call to retrieve a specific page of quotes and updates the `quotes` list and pagination details. /// This method makes an asynchronous call to retrieve a specific page of quotes and updates the `quotes` list and pagination details.
/// If the cancellation token is requested, it exits early without making further calls or updates. /// If the cancellation token is requested, it exits early without making further calls or updates.
/// </summary> /// </summary>
/// <param name="e">The event arguments containing pagination details such as page size and page number.</param> /// <param name="e">The event arguments containing pagination details such as page size and page number.</param>
private async Task OnReadData(DataGridReadDataEventArgs<Quote> e) private async Task OnReadData(DataGridReadDataEventArgs<Quote> e)
{ {
// Check if the cancellation token has been requested // Check if the cancellation token has been requested
if (e.CancellationToken.IsCancellationRequested) if (e.CancellationToken.IsCancellationRequested)
{ {
return; return;
} }
// Fetch the quote data for the specified page and page size // Fetch the quote data for the specified page and page size
var response = await QuoteService.getSomeQuote(e.PageSize, e.Page); var response = await QuoteService.getSomeQuote(e.PageSize, e.Page);
// If cancellation hasn't been requested, process the data // If cancellation hasn't been requested, process the data
if (!e.CancellationToken.IsCancellationRequested) if (!e.CancellationToken.IsCancellationRequested)
{ {
// Get the total number of quotes for pagination purposes // Get the total number of quotes for pagination purposes
totalItem = await QuoteService.getNbQuote(); totalItem = await QuoteService.getNbQuote();
// Update the quotes data for the current page // Update the quotes data for the current page
quotes = response.ToArray(); quotes = response.ToArray();
// Update the current page number // Update the current page number
page = e.Page; page = e.Page;
} }
} }
/*private void OnEditButtonClicked(Quote quote) /*private void OnEditButtonClicked(Quote quote)
{ {
if (selectedQuote == null) return; if (selectedQuote == null) return;
selectedQuote = quote; selectedQuote = quote;
showEditQuote = true; showEditQuote = true;
}*/ }*/
/// <summary> /// <summary>
/// Closes the open popups and resets any related states. /// Closes the open popups and resets any related states.
/// This method hides the delete confirmation popup and clears the selected quote. /// This method hides the delete confirmation popup and clears the selected quote.
/// </summary> /// </summary>
private void ClosePopup() private void ClosePopup()
{ {
// Hide the delete confirmation popup // Hide the delete confirmation popup
showPopupDelete = false; showPopupDelete = false;
// Reset the selected quote to null // Reset the selected quote to null
selectedQuote = null; selectedQuote = null;
} }
/*private async Task EditQuote() /*private async Task EditQuote()
{ {
await QuoteService.updateQuote(selectedQuote); await QuoteService.updateQuote(selectedQuote);
selectedQuote = null; selectedQuote = null;
ClosePopup(); ClosePopup();
}*/ }*/
/// <summary> /// <summary>
/// Handles the event when the delete action is triggered for a quote. /// Handles the event when the delete action is triggered for a quote.
/// This method sets the selected quote to the one passed as a parameter and displays the delete confirmation popup. /// This method sets the selected quote to the one passed as a parameter and displays the delete confirmation popup.
/// </summary> /// </summary>
/// <param name="q">The quote that is being deleted.</param> /// <param name="q">The quote that is being deleted.</param>
private void OnDelete(Quote q) private void OnDelete(Quote q)
{ {
// Set the selected quote to the one passed in // Set the selected quote to the one passed in
selectedQuote = q; selectedQuote = q;
// Display the delete confirmation popup // Display the delete confirmation popup
showPopupDelete = true; showPopupDelete = true;
} }
/// <summary> /// <summary>
/// Removes the selected quote by calling the remove service and updates the quote list. /// Removes the selected quote by calling the remove service and updates the quote list.
/// This method checks if a quote is selected. If so, it removes the quote using the `QuoteService`, clears the selected quote, /// This method checks if a quote is selected. If so, it removes the quote using the `QuoteService`, clears the selected quote,
/// and fetches the updated list of quotes. It also closes the delete confirmation popup after the operation. /// and fetches the updated list of quotes. It also closes the delete confirmation popup after the operation.
/// </summary> /// </summary>
private async void RemoveQuote() private async Task RemoveQuote()
{ {
// Check if a quote is selected for removal // Check if a quote is selected for removal
if (selectedQuote != null) if (selectedQuote != null)
{ {
// Remove the selected quote using the QuoteService // Remove the selected quote using the QuoteService
LoggerSaveStub.Log(Logger, LogLevel.Information, $"The quote {selectedQuote.Content} has been deleted"); LoggerSaveStub.Log(Logger, LogLevel.Information, $"The quote {selectedQuote.Content} has been deleted");
await QuoteService.removeQuote(selectedQuote); await QuoteService.removeQuote(selectedQuote);
// Clear the selected quote after removal // Clear the selected quote after removal
selectedQuote = null; selectedQuote = null;
// Update the quotes list by fetching the latest quotes data // Update the quotes list by fetching the latest quotes data
var response = await QuoteService.getSomeQuote(MaxValue, page); var response = await QuoteService.getSomeQuote(MaxValue, page);
quotes = response.ToArray(); quotes = response.ToArray();
} }
// Close the delete confirmation popup // Close the delete confirmation popup
showPopupDelete = false; showPopupDelete = false;
} }
} }
} }

@ -1,39 +1,40 @@
@using Microsoft.AspNetCore.Components.Web @using Microsoft.AspNetCore.Components.Web
@namespace WF_WebAdmin.Pages @namespace WF_WebAdmin.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <title>layout</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta charset="utf-8" />
<base href="~/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" /> <base href="~/" />
<link href="css/site.css" rel="stylesheet" /> <link rel="stylesheet" href="css/bootstrap/bootstrap.min.css" />
<link href="WF-WebAdmin.styles.css" rel="stylesheet" /> <link href="css/site.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" /> <link href="WF-WebAdmin.styles.css" rel="stylesheet" />
<link rel="icon" type="image/svg" href="../Shared/iconwf.svg" /> <component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head> <link rel="icon" type="image/svg" href="../Shared/iconwf.svg" />
<body> </head>
@RenderBody() <body>
@RenderBody()
<div id="blazor-error-ui">
<environment include="Staging,Production"> <div id="blazor-error-ui">
An error has occurred. This application may no longer respond until reloaded. <environment include="Staging,Production">
</environment> An error has occurred. This application may no longer respond until reloaded.
<environment include="Development"> </environment>
An unhandled exception has occurred. See browser dev tools for details. <environment include="Development">
</environment> An unhandled exception has occurred. See browser dev tools for details.
<a href="" class="reload">Reload</a> </environment>
<a class="dismiss">🗙</a> <a href="" class="reload">reload</a>
</div> <a class="dismiss">🗙</a>
</div>
<script src="_framework/blazor.server.js"></script>
<script src="_framework/blazor.server.js"></script>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.15.4/css/all.css">
<link href="_content/Blazorise/blazorise.css" rel="stylesheet" />
<link href="_content/Blazorise.Bootstrap/blazorise.bootstrap.css" rel="stylesheet" /> <link href="_content/Blazorise/blazorise.css" rel="stylesheet" />
<link href="_content/Blazorise.Bootstrap/blazorise.bootstrap.css" rel="stylesheet" />
</body>
</html> </body>
</html>

@ -14,6 +14,7 @@ using Blazored.Modal;
using WF_WebAdmin.Service; using WF_WebAdmin.Service;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using MudBlazor.Services; using MudBlazor.Services;
using Syncfusion.Blazor;
[assembly: RootNamespace("WF_WebAdmin")] [assembly: RootNamespace("WF_WebAdmin")]
@ -32,6 +33,8 @@ builder.Services.AddScoped<UserLogin>();
builder.Services.AddMudServices(); builder.Services.AddMudServices();
builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging")); builder.Logging.AddConfiguration(builder.Configuration.GetSection("Logging"));
builder.Services.AddSyncfusionBlazor();
builder.Services builder.Services
.AddBlazorise() .AddBlazorise()
.AddBootstrapProviders() .AddBootstrapProviders()

@ -1,198 +1,198 @@
using WF_WebAdmin.Converter; using WF_WebAdmin.Converter;
using WF_WebAdmin.Model; using WF_WebAdmin.Model;
using Npgsql; using Npgsql;
namespace WF_WebAdmin.Service namespace WF_WebAdmin.Service
{ {
public class QuoteServiceLocal: IQuoteService public class QuoteServiceLocal: IQuoteService
{ {
private readonly string? _connectionString = "Host=localhost;Port=5432;Username=loguichard3;Password=Reglisse15.;Database=dbloguichard3"; private readonly string? _connectionString = "Host=localhost;Port=5432;Username=;Password=;Database=";
/// <summary> /// <summary>
/// Asynchronously adds a new quote to the database and returns the corresponding <see cref="QuoteDTO"/>. /// Asynchronously adds a new quote to the database and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary> /// </summary>
/// <param name="quote">The <see cref="Quote"/> object to be added to the database.</param> /// <param name="quote">The <see cref="Quote"/> object to be added to the database.</param>
/// <returns>A task representing the asynchronous operation, with a <see cref="QuoteDTO"/> result containing the added quote's data.</returns> /// <returns>A task representing the asynchronous operation, with a <see cref="QuoteDTO"/> result containing the added quote's data.</returns>
/// <remarks> /// <remarks>
/// This method converts the provided <see cref="Quote"/> object into a <see cref="QuoteDTO"/> using <see cref="QuoteExtension"/>. /// This method converts the provided <see cref="Quote"/> object into a <see cref="QuoteDTO"/> using <see cref="QuoteExtension"/>.
/// It then inserts the quote into the PostgreSQL database using a parameterized SQL query with the help of Npgsql. /// It then inserts the quote into the PostgreSQL database using a parameterized SQL query with the help of Npgsql.
/// After successfully inserting the quote, the corresponding <see cref="QuoteDTO"/> is returned to the caller. /// After successfully inserting the quote, the corresponding <see cref="QuoteDTO"/> is returned to the caller.
/// Error handling is in place to catch any issues during the database insertion process, with the exception message logged in case of failure. /// Error handling is in place to catch any issues during the database insertion process, with the exception message logged in case of failure.
/// </remarks> /// </remarks>
public async Task<QuoteDTO> AddQuoteAsync(Quote quote) public async Task<QuoteDTO> AddQuoteAsync(Quote quote)
{ {
QuoteExtension extension = new QuoteExtension(); QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote); QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Utilisation de NpgsqlConnection pour PostgreSQL // Utilisation de NpgsqlConnection pour PostgreSQL
using (var connection = new NpgsqlConnection(_connectionString)) using (var connection = new NpgsqlConnection(_connectionString))
{ {
// Définir la requête SQL d'insertion // Définir la requête SQL d'insertion
var commandText = "INSERT INTO Quote (content, langue, reason, id_source, id_caracter, id_user_verif, img_path) " + var commandText = "INSERT INTO Quote (content, langue, reason, id_source, id_caracter, id_user_verif, img_path) " +
"VALUES (@content, @langue, @reason, @source, @character, @user, @img_path)"; "VALUES (@content, @langue, @reason, @source, @character, @user, @img_path)";
// Créer une commande Npgsql // Créer une commande Npgsql
var command = new NpgsqlCommand(commandText, connection); var command = new NpgsqlCommand(commandText, connection);
/* /*
// Ajouter des paramètres à la commande // Ajouter des paramètres à la commande
command.Parameters.AddWithValue("@content", quote.Content); command.Parameters.AddWithValue("@content", quote.Content);
command.Parameters.AddWithValue("@langue", quote.Langue); command.Parameters.AddWithValue("@langue", quote.Langue);
command.Parameters.AddWithValue("@reason", "À vérifier"); // Vous pouvez changer ça si nécessaire command.Parameters.AddWithValue("@reason", "À vérifier"); // Vous pouvez changer ça si nécessaire
command.Parameters.AddWithValue("@source", quote.Source); command.Parameters.AddWithValue("@source", quote.Source);
command.Parameters.AddWithValue("@character", quote.Character); command.Parameters.AddWithValue("@character", quote.Character);
command.Parameters.AddWithValue("@user", quote.User); // Assurez-vous que `quote.User` est correctement défini command.Parameters.AddWithValue("@user", quote.User); // Assurez-vous que `quote.User` est correctement défini
command.Parameters.AddWithValue("@img_path", quote.ImgPath); command.Parameters.AddWithValue("@img_path", quote.ImgPath);
*/ */
try try
{ {
// Ouvrir la connexion à la base de données // Ouvrir la connexion à la base de données
await connection.OpenAsync(); await connection.OpenAsync();
// Exécuter la commande d'insertion // Exécuter la commande d'insertion
await command.ExecuteNonQueryAsync(); await command.ExecuteNonQueryAsync();
} }
catch (Exception ex) catch (Exception ex)
{ {
// Gérer les erreurs ici (par exemple, afficher ou enregistrer les erreurs) // Gérer les erreurs ici (par exemple, afficher ou enregistrer les erreurs)
Console.WriteLine($"Une erreur est survenue lors de l'ajout de la citation : {ex.Message}"); Console.WriteLine($"Une erreur est survenue lors de l'ajout de la citation : {ex.Message}");
} }
finally finally
{ {
// Fermer la connexion (automatiquement géré avec `using`, mais ajouté pour explicitement montrer le processus) // Fermer la connexion (automatiquement géré avec `using`, mais ajouté pour explicitement montrer le processus)
await connection.CloseAsync(); await connection.CloseAsync();
} }
} }
// Retourner l'objet DTO pour que vous puissiez l'utiliser ailleurs dans votre application // Retourner l'objet DTO pour que vous puissiez l'utiliser ailleurs dans votre application
return quoteDTO; return quoteDTO;
} }
/// <summary> /// <summary>
/// Asynchronously handles the removal of a quote and returns the corresponding <see cref="QuoteDTO"/>. /// Asynchronously handles the removal of a quote and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary> /// </summary>
/// <param name="quote">The <see cref="Quote"/> object to be removed.</param> /// <param name="quote">The <see cref="Quote"/> object to be removed.</param>
/// <returns>A task representing the asynchronous operation, with a <see cref="QuoteDTO"/> result corresponding to the removed quote.</returns> /// <returns>A task representing the asynchronous operation, with a <see cref="QuoteDTO"/> result corresponding to the removed quote.</returns>
/// <remarks> /// <remarks>
/// This method takes a <see cref="Quote"/> object, converts it into a <see cref="QuoteDTO"/> using the /// This method takes a <see cref="Quote"/> object, converts it into a <see cref="QuoteDTO"/> using the
/// <see cref="QuoteExtension"/>, and then returns the DTO. Note that while this function is named `RemoveQuote`, /// <see cref="QuoteExtension"/>, and then returns the DTO. Note that while this function is named `RemoveQuote`,
/// it currently only converts the quote to a DTO and does not actually perform any database removal operation. /// it currently only converts the quote to a DTO and does not actually perform any database removal operation.
/// You may need to implement additional logic to remove the quote from the database. /// You may need to implement additional logic to remove the quote from the database.
/// </remarks> /// </remarks>
public Task RemoveQuote(Quote quote) public Task RemoveQuote(Quote quote)
{ {
QuoteExtension extension = new QuoteExtension(); QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote); QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Return the DTO as the result of this asynchronous operation (though no removal logic is currently implemented) // Return the DTO as the result of this asynchronous operation (though no removal logic is currently implemented)
return Task.FromResult(quoteDTO); return Task.FromResult(quoteDTO);
} }
/// <summary> /// <summary>
/// Asynchronously validates a quote and returns the corresponding <see cref="QuoteDTO"/>. /// Asynchronously validates a quote and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary> /// </summary>
/// <param name="quote">The <see cref="Quote"/> object to be validated.</param> /// <param name="quote">The <see cref="Quote"/> object to be validated.</param>
/// <returns>A task representing the asynchronous operation, with a <see cref="QuoteDTO"/> result corresponding to the validated quote.</returns> /// <returns>A task representing the asynchronous operation, with a <see cref="QuoteDTO"/> result corresponding to the validated quote.</returns>
/// <remarks> /// <remarks>
/// This method takes a <see cref="Quote"/> object, converts it into a <see cref="QuoteDTO"/> using the /// This method takes a <see cref="Quote"/> object, converts it into a <see cref="QuoteDTO"/> using the
/// <see cref="QuoteExtension"/>, and returns the DTO. The method is named `validQuote`, but currently, it only /// <see cref="QuoteExtension"/>, and returns the DTO. The method is named `validQuote`, but currently, it only
/// converts the quote into a DTO and does not perform any actual validation logic. /// converts the quote into a DTO and does not perform any actual validation logic.
/// If you intend to validate the quote (e.g., updating its status in a database), you will need to implement /// If you intend to validate the quote (e.g., updating its status in a database), you will need to implement
/// the actual validation logic separately. /// the actual validation logic separately.
/// </remarks> /// </remarks>
public Task validQuote(Quote quote) public Task validQuote(Quote quote)
{ {
QuoteExtension extension = new QuoteExtension(); QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote); QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Return the DTO as the result of this asynchronous operation (though no validation logic is currently implemented) // Return the DTO as the result of this asynchronous operation (though no validation logic is currently implemented)
return Task.FromResult(quoteDTO); return Task.FromResult(quoteDTO);
} }
/// <summary> /// <summary>
/// Asynchronously updates a quote and returns the corresponding <see cref="QuoteDTO"/>. /// Asynchronously updates a quote and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary> /// </summary>
/// <param name="quote">The <see cref="Quote"/> object to be updated.</param> /// <param name="quote">The <see cref="Quote"/> object to be updated.</param>
/// <returns>A task representing the asynchronous operation, with a <see cref="QuoteDTO"/> result corresponding to the updated quote.</returns> /// <returns>A task representing the asynchronous operation, with a <see cref="QuoteDTO"/> result corresponding to the updated quote.</returns>
/// <remarks> /// <remarks>
/// This method takes a <see cref="Quote"/> object, converts it into a <see cref="QuoteDTO"/> using the /// This method takes a <see cref="Quote"/> object, converts it into a <see cref="QuoteDTO"/> using the
/// <see cref="QuoteExtension"/>, and returns the DTO. The method is named `updateQuote`, but currently, it only /// <see cref="QuoteExtension"/>, and returns the DTO. The method is named `updateQuote`, but currently, it only
/// converts the quote into a DTO and does not perform any actual update logic. /// converts the quote into a DTO and does not perform any actual update logic.
/// If you intend to update the quote (e.g., modifying the quote in a database or data source), /// If you intend to update the quote (e.g., modifying the quote in a database or data source),
/// you will need to implement the actual update logic separately. /// you will need to implement the actual update logic separately.
/// </remarks> /// </remarks>
public Task updateQuote(Quote quote) public Task updateQuote(Quote quote)
{ {
QuoteExtension extension = new QuoteExtension(); QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote); QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Return the DTO as the result of this asynchronous operation (though no update logic is currently implemented) // Return the DTO as the result of this asynchronous operation (though no update logic is currently implemented)
return Task.FromResult(quoteDTO); return Task.FromResult(quoteDTO);
} }
public Task addQuote(Quote quote) public Task addQuote(Quote quote)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task removeQuote(Quote quote) public Task removeQuote(Quote quote)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<List<Quote>> getAllQuote() public Task<List<Quote>> getAllQuote()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<List<Quote>> getSomeQuote(int nb, int page) public Task<List<Quote>> getSomeQuote(int nb, int page)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<List<Quote>> reserchQuote(string reserch, List<string> argument) public Task<List<Quote>> reserchQuote(string reserch, List<string> argument)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<List<Quote>> getAllQuoteInvalid() public Task<List<Quote>> getAllQuoteInvalid()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<List<Quote>> getSomeQuoteInvalid(int nb, int page) public Task<List<Quote>> getSomeQuoteInvalid(int nb, int page)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<Quote> getOnequote(int id) public Task<Quote> getOnequote(int id)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<int> getNbQuote() public Task<int> getNbQuote()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<List<Character>> getChar() public Task<List<Character>> getChar()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
public Task<List<Source>> getSrc() public Task<List<Source>> getSrc()
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }
} }
} }

@ -59,6 +59,11 @@
<span class="oi oi-list-rich" aria-hidden="true"></span> Stats commentaires <span class="oi oi-list-rich" aria-hidden="true"></span> Stats commentaires
</MudNavLink> </MudNavLink>
</div> </div>
<div class="nav-item px-3">
<MudNavLink class="nav-link" Href="/graph">
<span class="oi oi-list-rich" aria-hidden="true"></span> Stats commentaires
</MudNavLink>
</div>
</nav> </nav>
</div> </div>

@ -18,6 +18,7 @@
<PackageReference Include="MudBlazor" Version="6.2.0" /> <PackageReference Include="MudBlazor" Version="6.2.0" />
<PackageReference Include="Npgsql" Version="9.0.2" /> <PackageReference Include="Npgsql" Version="9.0.2" />
<PackageReference Include="Blazored.Modal" Version="7.2.0" /> <PackageReference Include="Blazored.Modal" Version="7.2.0" />
<PackageReference Include="Syncfusion.Blazor.Charts" Version="28.2.4" />
</ItemGroup> </ItemGroup>
</Project> </Project>

@ -1,262 +1,268 @@
@import url('open-iconic/font/css/open-iconic-bootstrap.min.css'); @import url('open-iconic/font/css/open-iconic-bootstrap.min.css');
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap'); @import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap');
html, body { html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
background: white; background: white;
color: black; color: black;
} }
h1:focus {
outline: none;
}
h1 {
a, .btn-link { text-align: center;
color: #ffffff; font-size: 32px;
text-decoration: none; margin-top: 10%;
} font-family: "Roboto", serif;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2; h1:focus {
border-color: #1861ac; outline: none;
} }
.content { a, .btn-link {
padding-top: 1.1rem; color: #ffffff;
} text-decoration: none;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050; .btn-primary {
} color: #fff;
background-color: #1b6ec2;
.invalid { border-color: #1861ac;
outline: 1px solid red; }
}
.content {
.validation-message { padding-top: 1.1rem;
color: red; }
}
.valid.modified:not([type=checkbox]) {
#blazor-error-ui { outline: 1px solid #26b050;
background: lightyellow; }
bottom: 0;
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2); .invalid {
display: none; outline: 1px solid red;
left: 0; }
padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed; .validation-message {
width: 100%; color: red;
z-index: 1000; }
}
#blazor-error-ui {
#blazor-error-ui .dismiss { background: lightyellow;
cursor: pointer; bottom: 0;
position: absolute; box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
right: 0.75rem; display: none;
top: 0.5rem; left: 0;
} padding: 0.6rem 1.25rem 0.7rem 1.25rem;
position: fixed;
.blazor-error-boundary { width: 100%;
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121; z-index: 1000;
padding: 1rem 1rem 1rem 3.7rem; }
color: white;
} #blazor-error-ui .dismiss {
cursor: pointer;
.blazor-error-boundary::after { position: absolute;
content: "An error has occurred." right: 0.75rem;
} top: 0.5rem;
}
button { .blazor-error-boundary {
border: none; background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
border-radius: 25px; padding: 1rem 1rem 1rem 3.7rem;
background-color: lightgrey; color: white;
padding: 1vh; }
}
.blazor-error-boundary::after {
/*Page DeleteUser*/ content: "An error has occurred."
.userDiv, .QuoteDiv { }
margin-right: 20px;
margin-bottom: 10px;
border-radius: 25px; button {
background-color: #C3C4C5; border: none;
} border-radius: 25px;
background-color: lightgrey;
.imgProfil { padding: 1vh;
border-radius: 25px; }
width: 150px; /* Taille standard */
height: 150px; /* Taille standard */ /*Page DeleteUser*/
object-fit: cover; .userDiv, .QuoteDiv {
} margin-right: 20px;
margin-bottom: 10px;
.imgQuote { border-radius: 25px;
border-radius: 20px; background-color: #C3C4C5;
width: 300px; /* Taille standard */ }
height: 300px; /* Taille standard */
object-fit: cover; .imgProfil {
} border-radius: 25px;
width: 150px; /* Taille standard */
.pseudo, .mail, .idUser, .dateCrea, .idQuote, .contentQuote, .CaracterQuote, .SourceQuote, .langueQuote, .UserPropositionQuote { height: 150px; /* Taille standard */
margin-left: 10px; object-fit: cover;
} }
/*ModifQuote*/ .imgQuote {
border-radius: 20px;
.imgTab{ width: 300px; /* Taille standard */
width: 5vw; height: 300px; /* Taille standard */
height: 5vw; object-fit: cover;
object-fit: contain; }
}
.pseudo, .mail, .idUser, .dateCrea, .idQuote, .contentQuote, .CaracterQuote, .SourceQuote, .langueQuote, .UserPropositionQuote {
/*Popup DeleteUser*/ margin-left: 10px;
.divPopup { }
position: fixed;
top: 0; /*ModifQuote*/
left: 0;
width: 100%; .imgTab{
height: 100%; width: 5vw;
border-radius:20px; height: 5vw;
display: flex; object-fit: contain;
justify-content: center; }
align-items: center;
z-index: 2; /*Popup DeleteUser*/
} .divPopup {
position: fixed;
.contentPopup { top: 0;
padding: 20px; left: 0;
border-radius: 20px; width: 100%;
border: 3px solid black; height: 100%;
display: flex; border-radius:20px;
background-color: white; display: flex;
flex-direction: column; justify-content: center;
gap: 10px; align-items: center;
width: 300px; z-index: 2;
text-align: center; }
}
.contentPopup {
table { padding: 20px;
border-collapse: collapse; border-radius: 20px;
width: 100%; border: 3px solid black;
} display: flex;
background-color: white;
td { flex-direction: column;
padding: 10px 20px; gap: 10px;
border: none; width: 300px;
} text-align: center;
}
.boutons {
display: flex; table {
justify-content: space-between; border-collapse: collapse;
gap: 10px; width: 100%;
} }
.boutons button { td {
border: none; padding: 10px 20px;
background-color: transparent; border: none;
padding: 5px; }
cursor: pointer;
} .boutons {
display: flex;
.boutons button img { justify-content: space-between;
width: 24px; gap: 10px;
height: 24px; }
object-fit: contain;
} .boutons button {
border: none;
background-color: transparent;
.buttonSubmitDiv { padding: 5px;
text-align: center; cursor: pointer;
} }
h1 { .boutons button img {
text-align: center; width: 24px;
font-size: 32px; height: 24px;
margin-top: 10%; object-fit: contain;
font-family: "Roboto", serif; }
}
p { .buttonSubmitDiv {
margin-bottom: 2%; text-align: center;
font-size: 20px; }
font-family: "Roboto", serif;
}
.login { p {
width: 35vw; margin-bottom: 2%;
margin-left: 30.5vw; font-size: 20px;
margin-top: 3vh; font-family: "Roboto", serif;
border-radius: 25px; }
padding: 2vw;
background-color: #cfcfcf; .login {
} width: 35vw;
margin-left: 30.5vw;
margin-top: 3vh;
/*Page login*/ border-radius: 25px;
.buttonSudmite { padding: 2vw;
border: none; background-color: #cfcfcf;
padding: 2%; }
margin-top: 5%;
border-radius: 25px;
width: 50%; /*Page login*/
font-size: 1.25em; .buttonSudmite {
background-color: white; border: none;
font-family: "Roboto", serif; padding: 2%;
} margin-top: 5%;
border-radius: 25px;
.connexion { width: 50%;
width: 94%; font-size: 1.25em;
height: 40px; background-color: white;
padding-left: 3%; font-family: "Roboto", serif;
margin-left: 1%; }
margin-top: -1%;
border-radius: 25px; .connexion {
border: none; width: 94%;
font-size: 15px; height: 40px;
} padding-left: 3%;
margin-left: 1%;
margin-top: -1%;
border-radius: 25px;
.ErrorMsg { border: none;
color: red; font-size: 15px;
} }
table {
border-collapse: collapse;
width: 100%; .ErrorMsg {
} color: red;
}
td {
padding: 10px 20px; table {
border: none; border-collapse: collapse;
} width: 100%;
}
.boutons {
display: flex; td {
justify-content: space-between; padding: 10px 20px;
gap: 10px; border: none;
} }
.boutons button { .boutons {
border: none; display: flex;
background-color: transparent; justify-content: space-between;
padding: 5px; gap: 10px;
cursor: pointer; }
}
.boutons button {
.boutons button img { border: none;
width: 24px; background-color: transparent;
height: 24px; padding: 5px;
object-fit: contain; cursor: pointer;
} }
.boutons button img {
.imageProfil { width: 24px;
height: auto; height: 24px;
width: 30px; object-fit: contain;
border-radius: 45%; }
}
.buttonProfil{ .imageProfil {
background-color:transparent; height: auto;
width: 30px;
border-radius: 45%;
}
.buttonProfil{
background-color:transparent;
} }
Loading…
Cancel
Save