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)
{
this.Id = id_quote;
this.Content = content;
this.Content = content;
this.Likes = likes;
this.Langue = langue;
this.IsValide = isValide;
this.Reason = reason;
this.IdCaracter = id_caracter;
this.NameCharac = name_charac;
this.IdSource = id_source;
this.TitleSrc = title;
this.DateSrc = date;
this.IdUserVerif = id_user_verif;
this.NameUser = name_user;
this.IdImg = id_img;
this.ImgPath =img_path;
this.Reason = reason;
this.IdCaracter = id_caracter;
this.NameCharac = name_charac;
this.IdSource = id_source;
this.TitleSrc = title;
this.DateSrc = date;
this.IdUserVerif = id_user_verif;
this.NameUser = name_user;
this.IdImg = id_img;
this.ImgPath =img_path;
}
}
}

@ -10,7 +10,7 @@ namespace WF_WebAdmin.Converter
public DateTime DateCreation { 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)
{

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

@ -1,41 +1,25 @@
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.Logging;
using Microsoft.VisualBasic;
using System;
using System.Diagnostics;
using System.Security.Claims;
using WF_WebAdmin.Pages;
using WF_WebAdmin.Service;
namespace WF_WebAdmin.Model
{
public static partial class LoggerSaveStub
{
public static void Log(ILogger logs,LogLevel logLevel,string message)
{
ILogsService logsService = new LogsServiceStub();
logsService.addLogs( new Logs( 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,
*/
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.Logging;
using Microsoft.VisualBasic;
using System;
using System.Diagnostics;
using System.Security.Claims;
using WF_WebAdmin.Pages;
using WF_WebAdmin.Service;
namespace WF_WebAdmin.Model
{
public static partial class LoggerSaveStub
{
public static void Log(ILogger logs,LogLevel logLevel,string message)
{
ILogsService logsService = new LogsServiceStub();
logsService.addLogs( new Logs( logLevel , message ) );
logs.Log(logLevel, message );
}
}
}

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

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

@ -1,69 +1,33 @@
using Microsoft.AspNetCore.DataProtection.KeyManagement;
namespace WF_WebAdmin.Model
{
public class Quote
{
public int Id { get; set; }
public string Content { get; set; }
public int Like { get; set; }
public string Langue { get; set; }
public string Charac { get; set; }
public string ImgPath { get; set; }
public string TitleSrc { get; set; }
public DateTime DateSrc { get; set; }
public string UserProposition { 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)
{
Id = id;
Content = content;
Charac = charac;
ImgPath = imgPath;
TitleSrc = titleSrc;
DateSrc = dateSrc;
Like = like;
Langue = langue;
UserProposition = userProposition;
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;
}
*/
}
}
using Microsoft.AspNetCore.DataProtection.KeyManagement;
namespace WF_WebAdmin.Model
{
public class Quote
{
public int Id { get; set; }
public string Content { get; set; }
public int Like { get; set; }
public string Langue { get; set; }
public string Charac { get; set; }
public string ImgPath { get; set; }
public string TitleSrc { get; set; }
public DateTime DateSrc { get; set; }
public string UserProposition { 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)
{
Id = id;
Content = content;
Charac = charac;
ImgPath = imgPath;
TitleSrc = titleSrc;
DateSrc = dateSrc;
Like = like;
Langue = langue;
UserProposition = userProposition;
IsValid = isvalid;
}
}
}

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

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

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

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

@ -1,42 +1,42 @@
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using System.Security.Claims;
using WF_WebAdmin.Model;
namespace WF_WebAdmin.Pages
{
public partial class Accueil
{
private Quote[] Dailyquote;
[Inject]
public ILogger<Accueil> Logger { get; set; }
[Inject]
public HttpClient Http { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
[Inject]
public IStringLocalizer<Accueil> Localizer { get; set; }
/// <summary>
/// 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.
/// </summary>
protected override async Task OnInitializedAsync()
{
Dailyquote = await Http.GetFromJsonAsync<Quote[]>($"{NavigationManager.BaseUri}fake-dataDailyQuote.json");
}
private void RandomDailyquote()
{
//fonction a compléter
LoggerSaveStub.Log(Logger, LogLevel.Information, "Random change of quote of the day");
}
}
}
using Blazorise.DataGrid;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Localization;
using System.Security.Claims;
using WF_WebAdmin.Model;
namespace WF_WebAdmin.Pages
{
public partial class Accueil
{
private Quote[]? Dailyquote;
[Inject]
public ILogger<Accueil>? Logger { get; set; }
[Inject]
public HttpClient? Http { get; set; }
[Inject]
public NavigationManager? NavigationManager { get; set; }
[Inject]
public IStringLocalizer<Accueil>? Localizer { get; set; }
/// <summary>
/// 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.
/// </summary>
protected override async Task OnInitializedAsync()
{
Dailyquote = await Http.GetFromJsonAsync<Quote[]>($"{NavigationManager.BaseUri}fake-dataDailyQuote.json");
}
private void RandomDailyquote()
{
//fonction a compléter
LoggerSaveStub.Log(Logger, LogLevel.Information, "Random change of quote of the day");
}
}
}

@ -1,140 +1,140 @@
using Microsoft.AspNetCore.Components;
using WF_WebAdmin.Service;
using WF_WebAdmin.Model;
using Microsoft.AspNetCore.Mvc;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using System.Security.Claims;
namespace WF_WebAdmin.Pages
{
public partial class AddQuiz
{
[Inject]
public ILogger<AddQuiz> Logger { get; set; }
[Inject]
public IStringLocalizer<AddQuiz> Localizer { get; set; }
[Inject]
private IQuizService quizService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
private QuizModel QuizModel = new();
/// <summary>
/// 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.
/// 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.
/// </summary>
private async void HandleValidSubmit()
{
// Declare a variable to hold the ID of the new quiz.
int id;
// Get the current number of quizzes from the quiz service.
id = await quizService.getNbQuiz();
// Increment the quiz ID for the new quiz.
id++;
// Create a new quiz and add it using the quiz service.
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Creation of the {QuizModel.Question} question");
await quizService.addQuiz(new Quiz(
id, // New quiz ID
validateInformation(QuizModel.Question), // Validated question
validateInformation(QuizModel.AnswerA), // Validated answer A
validateInformation(QuizModel.AnswerB), // Validated answer B
validateInformation(QuizModel.AnswerC), // Validated answer C
validateInformation(QuizModel.AnswerD), // Validated answer D
validateReponse(QuizModel.CAnswer) // Validated correct answer
));
// Navigate to the "modifquiz" page after adding the quiz.
NavigationManager.NavigateTo("modifquiz");
}
/// <summary>
/// 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.
/// It updates the QuizModel's Correct Answer property with the selected answer.
/// </summary>
/// <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>
private void OnCAwnserChange(string item, object checkedValue)
{
// Update the correct answer in the QuizModel with the selected answer.
QuizModel.CAnswer = item;
}
/// <summary>
/// Validates the provided string item.
/// This method is used to validate input data, but the validation logic is not yet implemented.
/// </summary>
/// <param name="item">The string input to be validated.</param>
/// <returns>
/// Returns the input string as it is for now. The validation logic is yet to be implemented.
/// </returns>
private static string validateInformation(string item)
{
return item; // VALIDATION A FAIRE
}
/// <summary>
/// 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.
/// If the input is invalid or null, it throws an exception and returns a default value ("A") in case of error.
/// </summary>
/// <param name="item">The answer item (A, B, C, or D) to be validated.</param>
/// <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>
private static string validateReponse(string item)
{
try
{
// Check if the item is not null or empty
if (!string.IsNullOrEmpty(item))
{
// Validate that the item is one of the allowed values: A, B, C, or D
switch (item)
{
case "A":
break;
case "B":
break;
case "C":
break;
case "D":
break;
default:
// 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.");
}
}
else
{
// Throw exception if the item is null or empty
throw new ArgumentNullException("Invalid item (validateReponse): null given.");
}
// Return the validated item
return item;
}
catch (Exception ex)
{
// In case of an exception, return a default answer ("A")
return "A"; // Default Argument
}
}
}
}
using Microsoft.AspNetCore.Components;
using WF_WebAdmin.Service;
using WF_WebAdmin.Model;
using Microsoft.AspNetCore.Mvc;
using System.Text.RegularExpressions;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
using System.Security.Claims;
namespace WF_WebAdmin.Pages
{
public partial class AddQuiz
{
[Inject]
public ILogger<AddQuiz> Logger { get; set; }
[Inject]
public IStringLocalizer<AddQuiz> Localizer { get; set; }
[Inject]
private IQuizService quizService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
private QuizModel QuizModel = new();
/// <summary>
/// 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.
/// 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.
/// </summary>
private async Task HandleValidSubmit()
{
// Declare a variable to hold the ID of the new quiz.
int id;
// Get the current number of quizzes from the quiz service.
id = await quizService.getNbQuiz();
// Increment the quiz ID for the new quiz.
id++;
// Create a new quiz and add it using the quiz service.
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Creation of the {QuizModel.Question} question");
await quizService.addQuiz(new Quiz(
id, // New quiz ID
validateInformation(QuizModel.Question), // Validated question
validateInformation(QuizModel.AnswerA), // Validated answer A
validateInformation(QuizModel.AnswerB), // Validated answer B
validateInformation(QuizModel.AnswerC), // Validated answer C
validateInformation(QuizModel.AnswerD), // Validated answer D
validateReponse(QuizModel.CAnswer) // Validated correct answer
));
// Navigate to the "modifquiz" page after adding the quiz.
NavigationManager.NavigateTo("modifquiz");
}
/// <summary>
/// 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.
/// It updates the QuizModel's Correct Answer property with the selected answer.
/// </summary>
/// <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>
private void OnCAwnserChange(string item, object checkedValue)
{
// Update the correct answer in the QuizModel with the selected answer.
QuizModel.CAnswer = item;
}
/// <summary>
/// Validates the provided string item.
/// This method is used to validate input data, but the validation logic is not yet implemented.
/// </summary>
/// <param name="item">The string input to be validated.</param>
/// <returns>
/// Returns the input string as it is for now. The validation logic is yet to be implemented.
/// </returns>
private static string validateInformation(string item)
{
return item; // VALIDATION A FAIRE
}
/// <summary>
/// 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.
/// If the input is invalid or null, it throws an exception and returns a default value ("A") in case of error.
/// </summary>
/// <param name="item">The answer item (A, B, C, or D) to be validated.</param>
/// <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>
private static string validateReponse(string item)
{
try
{
// Check if the item is not null or empty
if (!string.IsNullOrEmpty(item))
{
// Validate that the item is one of the allowed values: A, B, C, or D
switch (item)
{
case "A":
break;
case "B":
break;
case "C":
break;
case "D":
break;
default:
// 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.");
}
}
else
{
// Throw exception if the item is null or empty
throw new ArgumentNullException("Invalid item (validateReponse): null given.");
}
// Return the validated item
return item;
}
catch (Exception ex)
{
// In case of an exception, return a default answer ("A")
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 Microsoft.AspNetCore.Components;
using Microsoft.Extensions.Configuration.UserSecrets;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Localization;
using System.Collections.Generic;
using WF_WebAdmin.Model;
@ -11,12 +11,12 @@ namespace WF_WebAdmin.Pages
{
public partial class DeleteUser
{
[Inject]
public ILogger<DeleteUser> Logger { get; set; }
[Inject]
public ILogger<DeleteUser> Logger { get; set; }
private List<User> users;
private List<User> users;
private bool showDeletePopup = false;
private bool showModifyPopup = false;
private User userToDelete = null;
private User selectedUser;
@ -37,180 +37,180 @@ namespace WF_WebAdmin.Pages
[Inject]
private IUserService userService { get; set; }
[Inject]
[Inject]
public IStringLocalizer<DeleteUser> Localizer { get; set; }
/// <summary>
/// This method is called when the component is initialized.
/// 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).
/// </summary>
/// <summary>
/// This method is called when the component is initialized.
/// 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).
/// </summary>
protected override async Task OnInitializedAsync()
{
// 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.
// 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.
users = await userService.getSomeUser(MaxValue, 1);
}
/// <summary>
/// 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.
/// 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.
/// </summary>
/// <param name="e">The event arguments containing pagination details (page size and page number) and a cancellation token.</param>
/// <summary>
/// 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.
/// 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.
/// </summary>
/// <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)
{
// 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)
{
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);
// 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)
{
totalItem = await userService.getNbUser(); // Get the total number of users
users = new List<User>(response.ToArray()); // Store the retrieved users in the users list
page = e.Page; // Update the current page number
totalItem = await userService.getNbUser(); // Get the total number of users
users = new List<User>(response.ToArray()); // Store the retrieved users in the users list
page = e.Page; // Update the current page number
}
}
// ------- Popup remove user -------
/// <summary>
/// Displays a confirmation popup to confirm the deletion of 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.
/// </summary>
/// <param name="user">The user to be deleted, which is passed to the method for confirmation.</param>
/// <summary>
/// Displays a confirmation popup to confirm the deletion of 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.
/// </summary>
/// <param name="user">The user to be deleted, which is passed to the method for confirmation.</param>
private void ShowConfirmation(User user)
{
// Set the user to be deleted and show the confirmation popup.
userToDelete = user; // Store the user to be deleted in a variable
showPopupDelete = true; // Display 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
showPopupDelete = true; // Display the confirmation popup
}
/// <summary>
/// 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,
/// and it sets the selected user and shows the modification confirmation popup.
/// </summary>
/// <param name="user">The user whose information is to be modified, passed to the method for confirmation.</param>
/// <summary>
/// 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,
/// and it sets the selected user and shows the modification confirmation popup.
/// </summary>
/// <param name="user">The user whose information is to be modified, passed to the method for confirmation.</param>
private void ShowModifyConfirmation(User user)
{
// Set the selected user and show the modification confirmation popup.
selectedUser = user; // Store the user to be modified
showModifyPopup = true; // Display the confirmation popup for modification
// Set the selected user and show the modification confirmation popup.
selectedUser = user; // Store the user to be modified
showModifyPopup = true; // Display the confirmation popup for modification
}
/// <summary>
/// Removes the specified user from the system.
/// 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,
/// and then refreshes the list of users by fetching the updated data.
/// </summary>
/// <summary>
/// Removes the specified user from the system.
/// 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,
/// and then refreshes the list of users by fetching the updated data.
/// </summary>
private async Task RemoveUser()
{
// Check if there is a user to delete
// Check if there is a user to delete
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}");
await userService.removeUser(userToDelete);
// Close the confirmation popup after the deletion
// Close the confirmation popup after the deletion
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);
// Update the users list with the latest data
// Update the users list with the latest data
users = new List<User>(response.ToArray());
}
}
/// <summary>
/// Modifies the selected user's information.
/// 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.
/// </summary>
/// <summary>
/// Modifies the selected user's information.
/// 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.
/// </summary>
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}");
await userService.updateUser(selectedUser);
// Close the modification popup after the update is complete
// Close the modification popup after the update is complete
ClosePopup();
}
/// <summary>
/// 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)
/// to hide any active popups and reset the UI state.
/// </summary>
/// <summary>
/// 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)
/// to hide any active popups and reset the UI state.
/// </summary>
private void ClosePopup()
{
// Set all popup visibility flags to false to hide the popups
showDeletePopup = false; // Close the delete confirmation popup
showModifyPopup = false; // Close the modify confirmation popup
showPopupDelete = false; // Close any additional delete popups
showPopupAdmin = false; // Close the admin-related popup (if any)
// Set all popup visibility flags to false to hide the popups
showDeletePopup = false; // Close the delete confirmation popup
showModifyPopup = false; // Close the modify confirmation popup
showPopupDelete = false; // Close any additional delete popups
showPopupAdmin = false; // Close the admin-related popup (if any)
}
// ------- Popup admin -------
/// <summary>
/// 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.
/// It sets the selected user to be promoted and shows the confirmation popup for admin promotion.
/// </summary>
/// <param name="user">The user to be promoted to admin, passed to the method for confirmation.</param>
/// <summary>
/// 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.
/// It sets the selected user to be promoted and shows the confirmation popup for admin promotion.
/// </summary>
/// <param name="user">The user to be promoted to admin, passed to the method for confirmation.</param>
private void ShowConfirmationAdmin(User user)
{
// Set the user to be promoted to admin and show the confirmation popup.
userToAdmin = user; // Store the user to be promoted
showPopupAdmin = true; // Display the confirmation popup for admin promotion
// Set the user to be promoted to admin and show the confirmation popup.
userToAdmin = user; // Store the user to be promoted
showPopupAdmin = true; // Display the confirmation popup for admin promotion
}
/// <summary>
/// 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,
/// 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.
/// </summary>
/// <summary>
/// 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,
/// 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.
/// </summary>
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)
{
// Promote the user to admin
LoggerSaveStub.Log(Logger, LogLevel.Information, $"User {userToAdmin.Name} is now administrator");
// Promote the user to admin
LoggerSaveStub.Log(Logger, LogLevel.Information, $"User {userToAdmin.Name} is now administrator");
userToAdmin.IsAdmin = true;
await userService.updateUser(userToAdmin); // Update the user status in the service
ClosePopup(); // Close the confirmation popup
await userService.updateUser(userToAdmin); // Update the user status in the service
ClosePopup(); // Close the confirmation popup
}
else
{
// Demote the user from admin to normal user
LoggerSaveStub.Log(Logger, LogLevel.Information, $"User {userToAdmin.Name} is no longer an administator");
// Demote the user from admin to normal user
LoggerSaveStub.Log(Logger, LogLevel.Information, $"User {userToAdmin.Name} is no longer an administator");
userToAdmin.IsAdmin = false;
await userService.updateUser(userToAdmin); // Update the user status in the service
ClosePopup(); // Close the confirmation popup
await userService.updateUser(userToAdmin); // Update the user status in the service
ClosePopup(); // Close the confirmation popup
}
}

@ -1,100 +1,100 @@
using Microsoft.AspNetCore.Components;
using System.Security.Claims;
using WF_WebAdmin.Model;
using WF_WebAdmin.Service;
namespace WF_WebAdmin.Pages
{
public partial class Edit
{
[Parameter]
public int Id { get; set; }
[Inject]
public ILogger<Edit> Logger { get; set; }
[Inject]
private IQuoteService quoteService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
private Quote q{ get; set; }
private QuoteModel quoteModel = new();
private List<Character> charac = new List<Character>();
private List<Source> src = new List<Source>();
/// <summary>
/// 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`
/// 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.
/// </summary>
protected override async Task OnInitializedAsync()
{
// Fetch the quote data based on the provided ID.
q = await quoteService.getOnequote(Id);
// Populate the quoteModel with the data from the retrieved quote.
quoteModel.Content = q.Content;
quoteModel.Langue = q.Langue;
quoteModel.Charac = q.Charac;
quoteModel.TitleSrc = q.TitleSrc;
quoteModel.Id = q.Id;
quoteModel.Like = q.Like;
quoteModel.ImgPath = q.ImgPath;
quoteModel.DateSrc = q.DateSrc;
quoteModel.UserProposition = q.UserProposition;
quoteModel.IsValid = q.IsValid;
// Fetch additional data related to the quote, such as character and source.
charac = await quoteService.getChar();
src = await quoteService.getSrc();
}
/// <summary>
/// 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,
/// and then calls the `quoteService.updateQuote` method to persist the changes.
/// After updating, it navigates to the "modifquote" page.
/// </summary>
protected async void HandleValidSubmit()
{
// Update the properties of the selected quote (`q`) with the data from `quoteModel`.
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Editing the quote {q.Content}");
q.Content = quoteModel.Content;
q.Langue = quoteModel.Langue;
q.TitleSrc = quoteModel.TitleSrc;
q.Charac = quoteModel.Charac;
// Call the quote service to update the quote in the data source.
await quoteService.updateQuote(q);
// Navigate to the "modifquote" page after updating the quote.
NavigationManager.NavigateTo("modifquote");
}
/// <summary>
/// Handles the language change event for the quote.
/// 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.
/// </summary>
/// <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>
private void OnlangChange(string item, object checkedValue)
{
// Check if the selected language is either "fr" or "en"
if (item == "fr" || item == "en")
{
// Update the Langue property of the quoteModel with the selected language
quoteModel.Langue = item;
}
}
}
}
using Microsoft.AspNetCore.Components;
using System.Security.Claims;
using WF_WebAdmin.Model;
using WF_WebAdmin.Service;
namespace WF_WebAdmin.Pages
{
public partial class Edit
{
[Parameter]
public int Id { get; set; }
[Inject]
public ILogger<Edit> Logger { get; set; }
[Inject]
private IQuoteService quoteService { get; set; }
[Inject]
public NavigationManager NavigationManager { get; set; }
private Quote q{ get; set; }
private QuoteModel quoteModel = new();
private List<Character> charac = new List<Character>();
private List<Source> src = new List<Source>();
/// <summary>
/// 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`
/// 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.
/// </summary>
protected override async Task OnInitializedAsync()
{
// Fetch the quote data based on the provided ID.
q = await quoteService.getOnequote(Id);
// Populate the quoteModel with the data from the retrieved quote.
quoteModel.Content = q.Content;
quoteModel.Langue = q.Langue;
quoteModel.Charac = q.Charac;
quoteModel.TitleSrc = q.TitleSrc;
quoteModel.Id = q.Id;
quoteModel.Like = q.Like;
quoteModel.ImgPath = q.ImgPath;
quoteModel.DateSrc = q.DateSrc;
quoteModel.UserProposition = q.UserProposition;
quoteModel.IsValid = q.IsValid;
// Fetch additional data related to the quote, such as character and source.
charac = await quoteService.getChar();
src = await quoteService.getSrc();
}
/// <summary>
/// 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,
/// and then calls the `quoteService.updateQuote` method to persist the changes.
/// After updating, it navigates to the "modifquote" page.
/// </summary>
protected async Task HandleValidSubmit()
{
// Update the properties of the selected quote (`q`) with the data from `quoteModel`.
LoggerSaveStub.Log(Logger, LogLevel.Information, $"Editing the quote {q.Content}");
q.Content = quoteModel.Content;
q.Langue = quoteModel.Langue;
q.TitleSrc = quoteModel.TitleSrc;
q.Charac = quoteModel.Charac;
// Call the quote service to update the quote in the data source.
await quoteService.updateQuote(q);
// Navigate to the "modifquote" page after updating the quote.
NavigationManager.NavigateTo("modifquote");
}
/// <summary>
/// Handles the language change event for the quote.
/// 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.
/// </summary>
/// <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>
private void OnlangChange(string item, object checkedValue)
{
// Check if the selected language is either "fr" or "en"
if (item == "fr" || item == "en")
{
// Update the Langue property of the quoteModel with the selected language
quoteModel.Langue = item;
}
}
}
}

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

@ -1,40 +1,40 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Diagnostics;
namespace WF_WebAdmin.Pages
{
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
private readonly ILogger<ErrorModel> _logger;
/// <summary>
/// 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.
/// </summary>
/// <param name="logger">An instance of the <see cref="ILogger{ErrorModel}"/> used for logging error-related information.</param>
public ErrorModel(ILogger<ErrorModel> logger)
{
_logger = logger;
}
/// <summary>
/// Handles the GET request for the page or endpoint.
/// 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.
/// </summary>
public void OnGet()
{
// Retrieve the current request ID for tracing
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
}
}
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using System.Diagnostics;
namespace WF_WebAdmin.Pages
{
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
[IgnoreAntiforgeryToken]
public class ErrorModel : PageModel
{
public string? RequestId { get; set; }
public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
/// <summary>
/// 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.
/// </summary>
/// <param name="logger">An instance of the <see cref="ILogger{ErrorModel}"/> used for logging error-related information.</param>
public ErrorModel(ILogger<ErrorModel> logger)
{
_logger = logger;
}
/// <summary>
/// Handles the GET request for the page or endpoint.
/// 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.
/// </summary>
public void OnGet()
{
// Retrieve the current request ID for tracing
RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
}
}
}

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

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

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

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

@ -1,198 +1,198 @@
using WF_WebAdmin.Converter;
using WF_WebAdmin.Model;
using Npgsql;
namespace WF_WebAdmin.Service
{
public class QuoteServiceLocal: IQuoteService
{
private readonly string? _connectionString = "Host=localhost;Port=5432;Username=loguichard3;Password=Reglisse15.;Database=dbloguichard3";
/// <summary>
/// Asynchronously adds a new quote to the database and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary>
/// <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>
/// <remarks>
/// 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.
/// 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.
/// </remarks>
public async Task<QuoteDTO> AddQuoteAsync(Quote quote)
{
QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Utilisation de NpgsqlConnection pour PostgreSQL
using (var connection = new NpgsqlConnection(_connectionString))
{
// 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) " +
"VALUES (@content, @langue, @reason, @source, @character, @user, @img_path)";
// Créer une commande Npgsql
var command = new NpgsqlCommand(commandText, connection);
/*
// Ajouter des paramètres à la commande
command.Parameters.AddWithValue("@content", quote.Content);
command.Parameters.AddWithValue("@langue", quote.Langue);
command.Parameters.AddWithValue("@reason", "À vérifier"); // Vous pouvez changer ça si nécessaire
command.Parameters.AddWithValue("@source", quote.Source);
command.Parameters.AddWithValue("@character", quote.Character);
command.Parameters.AddWithValue("@user", quote.User); // Assurez-vous que `quote.User` est correctement défini
command.Parameters.AddWithValue("@img_path", quote.ImgPath);
*/
try
{
// Ouvrir la connexion à la base de données
await connection.OpenAsync();
// Exécuter la commande d'insertion
await command.ExecuteNonQueryAsync();
}
catch (Exception ex)
{
// 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}");
}
finally
{
// Fermer la connexion (automatiquement géré avec `using`, mais ajouté pour explicitement montrer le processus)
await connection.CloseAsync();
}
}
// Retourner l'objet DTO pour que vous puissiez l'utiliser ailleurs dans votre application
return quoteDTO;
}
/// <summary>
/// Asynchronously handles the removal of a quote and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary>
/// <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>
/// <remarks>
/// 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`,
/// 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.
/// </remarks>
public Task RemoveQuote(Quote quote)
{
QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Return the DTO as the result of this asynchronous operation (though no removal logic is currently implemented)
return Task.FromResult(quoteDTO);
}
/// <summary>
/// Asynchronously validates a quote and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary>
/// <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>
/// <remarks>
/// 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
/// 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
/// the actual validation logic separately.
/// </remarks>
public Task validQuote(Quote quote)
{
QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Return the DTO as the result of this asynchronous operation (though no validation logic is currently implemented)
return Task.FromResult(quoteDTO);
}
/// <summary>
/// Asynchronously updates a quote and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary>
/// <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>
/// <remarks>
/// 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
/// 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),
/// you will need to implement the actual update logic separately.
/// </remarks>
public Task updateQuote(Quote quote)
{
QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Return the DTO as the result of this asynchronous operation (though no update logic is currently implemented)
return Task.FromResult(quoteDTO);
}
public Task addQuote(Quote quote)
{
throw new NotImplementedException();
}
public Task removeQuote(Quote quote)
{
throw new NotImplementedException();
}
public Task<List<Quote>> getAllQuote()
{
throw new NotImplementedException();
}
public Task<List<Quote>> getSomeQuote(int nb, int page)
{
throw new NotImplementedException();
}
public Task<List<Quote>> reserchQuote(string reserch, List<string> argument)
{
throw new NotImplementedException();
}
public Task<List<Quote>> getAllQuoteInvalid()
{
throw new NotImplementedException();
}
public Task<List<Quote>> getSomeQuoteInvalid(int nb, int page)
{
throw new NotImplementedException();
}
public Task<Quote> getOnequote(int id)
{
throw new NotImplementedException();
}
public Task<int> getNbQuote()
{
throw new NotImplementedException();
}
public Task<List<Character>> getChar()
{
throw new NotImplementedException();
}
public Task<List<Source>> getSrc()
{
throw new NotImplementedException();
}
}
}
using WF_WebAdmin.Converter;
using WF_WebAdmin.Model;
using Npgsql;
namespace WF_WebAdmin.Service
{
public class QuoteServiceLocal: IQuoteService
{
private readonly string? _connectionString = "Host=localhost;Port=5432;Username=;Password=;Database=";
/// <summary>
/// Asynchronously adds a new quote to the database and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary>
/// <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>
/// <remarks>
/// 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.
/// 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.
/// </remarks>
public async Task<QuoteDTO> AddQuoteAsync(Quote quote)
{
QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Utilisation de NpgsqlConnection pour PostgreSQL
using (var connection = new NpgsqlConnection(_connectionString))
{
// 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) " +
"VALUES (@content, @langue, @reason, @source, @character, @user, @img_path)";
// Créer une commande Npgsql
var command = new NpgsqlCommand(commandText, connection);
/*
// Ajouter des paramètres à la commande
command.Parameters.AddWithValue("@content", quote.Content);
command.Parameters.AddWithValue("@langue", quote.Langue);
command.Parameters.AddWithValue("@reason", "À vérifier"); // Vous pouvez changer ça si nécessaire
command.Parameters.AddWithValue("@source", quote.Source);
command.Parameters.AddWithValue("@character", quote.Character);
command.Parameters.AddWithValue("@user", quote.User); // Assurez-vous que `quote.User` est correctement défini
command.Parameters.AddWithValue("@img_path", quote.ImgPath);
*/
try
{
// Ouvrir la connexion à la base de données
await connection.OpenAsync();
// Exécuter la commande d'insertion
await command.ExecuteNonQueryAsync();
}
catch (Exception ex)
{
// 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}");
}
finally
{
// Fermer la connexion (automatiquement géré avec `using`, mais ajouté pour explicitement montrer le processus)
await connection.CloseAsync();
}
}
// Retourner l'objet DTO pour que vous puissiez l'utiliser ailleurs dans votre application
return quoteDTO;
}
/// <summary>
/// Asynchronously handles the removal of a quote and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary>
/// <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>
/// <remarks>
/// 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`,
/// 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.
/// </remarks>
public Task RemoveQuote(Quote quote)
{
QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Return the DTO as the result of this asynchronous operation (though no removal logic is currently implemented)
return Task.FromResult(quoteDTO);
}
/// <summary>
/// Asynchronously validates a quote and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary>
/// <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>
/// <remarks>
/// 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
/// 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
/// the actual validation logic separately.
/// </remarks>
public Task validQuote(Quote quote)
{
QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Return the DTO as the result of this asynchronous operation (though no validation logic is currently implemented)
return Task.FromResult(quoteDTO);
}
/// <summary>
/// Asynchronously updates a quote and returns the corresponding <see cref="QuoteDTO"/>.
/// </summary>
/// <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>
/// <remarks>
/// 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
/// 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),
/// you will need to implement the actual update logic separately.
/// </remarks>
public Task updateQuote(Quote quote)
{
QuoteExtension extension = new QuoteExtension();
QuoteDTO quoteDTO = extension.QuoteToDTO(quote);
// Return the DTO as the result of this asynchronous operation (though no update logic is currently implemented)
return Task.FromResult(quoteDTO);
}
public Task addQuote(Quote quote)
{
throw new NotImplementedException();
}
public Task removeQuote(Quote quote)
{
throw new NotImplementedException();
}
public Task<List<Quote>> getAllQuote()
{
throw new NotImplementedException();
}
public Task<List<Quote>> getSomeQuote(int nb, int page)
{
throw new NotImplementedException();
}
public Task<List<Quote>> reserchQuote(string reserch, List<string> argument)
{
throw new NotImplementedException();
}
public Task<List<Quote>> getAllQuoteInvalid()
{
throw new NotImplementedException();
}
public Task<List<Quote>> getSomeQuoteInvalid(int nb, int page)
{
throw new NotImplementedException();
}
public Task<Quote> getOnequote(int id)
{
throw new NotImplementedException();
}
public Task<int> getNbQuote()
{
throw new NotImplementedException();
}
public Task<List<Character>> getChar()
{
throw new NotImplementedException();
}
public Task<List<Source>> getSrc()
{
throw new NotImplementedException();
}
}
}

@ -59,6 +59,11 @@
<span class="oi oi-list-rich" aria-hidden="true"></span> Stats commentaires
</MudNavLink>
</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>
</div>

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

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