2 Commits

Author SHA1 Message Date
a31292e476 NEW: Zusagen / Absagen Chart (PoC) 2025-12-04 22:57:22 +01:00
ab237de4c8 Comments: IEventRegistrationService.cs 2025-12-04 22:56:41 +01:00
9 changed files with 208 additions and 166 deletions

View File

@ -1,6 +0,0 @@
<h3>@user.DisplayName</h3>
@code {
[Parameter]
public User user { get; set; }
}

View File

@ -11,5 +11,20 @@ namespace SZUAbsolventenverein.Module.EventRegistration
{ {
_jsRuntime = jsRuntime; _jsRuntime = jsRuntime;
} }
public async Task CreateChart(string divid, string type, string[] labels, object[] datasets, object options)
{
try
{
await _jsRuntime.InvokeVoidAsync(
"SZUAbsolventenverein.EventRegistration.createChart",
divid, type, (object) labels, (object) datasets, options);
}
catch
{
// handle exception
}
}
} }
} }

View File

@ -4,7 +4,6 @@
@using SZUAbsolventenverein.Module.EventRegistration.Services @using SZUAbsolventenverein.Module.EventRegistration.Services
@using SZUAbsolventenverein.Module.EventRegistration.Models @using SZUAbsolventenverein.Module.EventRegistration.Models
@using System.Text.RegularExpressions @using System.Text.RegularExpressions
@using SZUAbsolventenverein.Module.EventRegistration.Client.Components
@namespace SZUAbsolventenverein.Module.EventRegistration @namespace SZUAbsolventenverein.Module.EventRegistration
@inherits ModuleBase @inherits ModuleBase
@ -32,23 +31,19 @@
@if (Status == true) @if (Status == true)
{ {
<span class ="fontsizeInf">@Localizer["Zugesagt"]</span><br /> <span class ="fontsizeInf">@Localizer["Zugesagt"]</span><br />
<p><button class="btn btn-danger" @onclick="Reject">@Localizer["Absagen"]</button></p> <p><button class="btn btn-danger" @onclick="Absage">@Localizer["Absagen"]</button></p>
} else } else
{ {
<span class="fontsizeInf"> @Localizer["Abgesagt"]</span><br /> <span class="fontsizeInf"> @Localizer["Abgesagt"]</span><br />
<p><button class="btn btn-success" @onclick="Accept">@Localizer["Zusagen"]</button></p> <p><button class="btn btn-success" @onclick="Zusage">@Localizer["Zusagen"]</button></p>
} }
</p> </p>
} else { } else {
<div class="buttons"> <div class="buttons">
<button class="btn btn-success" @onclick="Accept">@Localizer["Zusagen"]</button> <button class="btn btn-success" @onclick="Zusage">@Localizer["Zusagen"]</button>
<button class="btn btn-danger" @onclick="Reject">@Localizer["Absagen"]</button> <button class="btn btn-danger" @onclick="Absage">@Localizer["Absagen"]</button>
</div> </div>
} }
@foreach (User u in _users)
{
<UserComponent user="u" />
}
} else } else
{ {
<p class="mt-3">Um dich für dieses Event zu registrieren, muss man sich zuerst anmelden.</p> <p class="mt-3">Um dich für dieses Event zu registrieren, muss man sich zuerst anmelden.</p>
@ -70,6 +65,9 @@
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" } new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" }
}; };
// private ElementReference form;
// private bool validated = false;
private int _id; private int _id;
private string _name; private string _name;
private string _description; private string _description;
@ -82,8 +80,6 @@
private List<Profile> _profiles = new List<Profile>(); private List<Profile> _profiles = new List<Profile>();
private Dictionary<string, string> _settings; private Dictionary<string, string> _settings;
private List<User> _users = new List<User>();
private async Task SendResponse(bool response) private async Task SendResponse(bool response)
{ {
if(ValidateProfiles()) { if(ValidateProfiles()) {
@ -111,12 +107,12 @@
} }
} }
private async void Accept() private async void Zusage()
{ {
await SendResponse(true); await SendResponse(true);
} }
private async void Reject() private async void Absage()
{ {
await SendResponse(false); await SendResponse(false);
} }
@ -125,8 +121,6 @@
{ {
try try
{ {
_id = Int32.Parse(PageState.QueryString["id"]);
if(PageState.User != null) { if(PageState.User != null) {
_profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId); _profiles = await ProfileService.GetProfilesAsync(PageState.Site.SiteId);
var user = await UserService.GetUserAsync(PageState.User.UserId, PageState.Site.SiteId); var user = await UserService.GetUserAsync(PageState.User.UserId, PageState.Site.SiteId);
@ -134,10 +128,10 @@
{ {
_settings = user.Settings; _settings = user.Settings;
} }
_users = await EventRegistrationService.GetRecommendedResponses(_id, ModuleState.ModuleId);
_users.ForEach(u => Console.WriteLine(u.UserId));
} }
_id = Int32.Parse(PageState.QueryString["id"]);
Event currentEvent; Event currentEvent;
Response rsvp; Response rsvp;
(currentEvent, rsvp) = await EventRegistrationService.GetEventDetails(_id, ModuleState.ModuleId); (currentEvent, rsvp) = await EventRegistrationService.GetEventDetails(_id, ModuleState.ModuleId);

View File

@ -42,6 +42,7 @@
{ {
<AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo> <AuditInfo CreatedBy="@_createdby" CreatedOn="@_createdon" ModifiedBy="@_modifiedby" ModifiedOn="@_modifiedon"></AuditInfo>
} }
<div id="chart"></div>
</form> </form>
@code { @code {
@ -53,7 +54,9 @@
public override List<Resource> Resources => new List<Resource>() public override List<Resource> Resources => new List<Resource>()
{ {
new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" } new Resource { ResourceType = ResourceType.Stylesheet, Url = ModulePath() + "Module.css" },
new Resource { ResourceType = ResourceType.Script, Bundle = "ChartJS", Url = "https://cdn.jsdelivr.net/npm/chart.js" },
new Resource { ResourceType = ResourceType.Script, Bundle = "ChartJS", Url = ModulePath() + "Module.js"}
}; };
@ -72,6 +75,9 @@
private string _modifiedby; private string _modifiedby;
private DateTime _modifiedon; private DateTime _modifiedon;
bool _refresh = false;
private List<Response> _responses;
protected override async Task OnInitializedAsync() protected override async Task OnInitializedAsync()
{ {
try try
@ -92,6 +98,10 @@
_modifiedby = EventRegistration.ModifiedBy; _modifiedby = EventRegistration.ModifiedBy;
_modifiedon = EventRegistration.ModifiedOn; _modifiedon = EventRegistration.ModifiedOn;
} }
_responses = await EventRegistrationService.GetEventResponses(_id, ModuleState.ModuleId);
Console.WriteLine("Responses count: " + (_responses != null ? _responses.Count.ToString() : "null"));
_refresh = true;
} }
} }
catch (Exception ex) catch (Exception ex)
@ -101,6 +111,37 @@
} }
} }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
try
{
await base.OnAfterRenderAsync(firstRender);
Console.WriteLine("Responses count: " + (_responses != null ? _responses.Count.ToString() : "null"));
if (_refresh && _responses != null)
{
List<string> labels = new List<string>();
List<object> datasets = new List<object>();
string[] colors = new string[] { "#FF0000", "#FF8000", "#FFFF00", "#00FF00", "#00FFFF", "#0080FF", "#0000FF", "#8000FF", "#FF00FF", "#CCCCCC" };
labels.AddRange("Zusage", "Absage");
datasets.Add(new { label = "DS1", data = new int[] { _responses.Count(r => r.ResponseType == true), _responses.Count(r => r.ResponseType == false) }, fill = false, backgroundColor = colors });
object options = new { maintainAspectRatio = false, legend = new { display = true, position = "bottom", labels = new { fontColor = "white", fontSize = 16 } } };
var interop = new Interop(JSRuntime);
await interop.CreateChart("chart", "pie", labels.ToArray(), datasets.ToArray(), options);
_refresh = false;
}
}
catch (Exception ex)
{
await logger.LogError(ex, "Error Rendering Chart {Error}", ex.Message);
AddModuleMessage("Error Rendering Chart", MessageType.Error);
}
}
private async Task Save() private async Task Save()
{ {
try try

View File

@ -3,7 +3,6 @@ using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Oqtane.Models;
using Oqtane.Services; using Oqtane.Services;
using Oqtane.Shared; using Oqtane.Shared;
using SZUAbsolventenverein.Module.EventRegistration.Models; using SZUAbsolventenverein.Module.EventRegistration.Models;
@ -31,9 +30,9 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
return await PostJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}", EntityNames.Module, NewEvent.ModuleId), NewEvent); return await PostJsonAsync(CreateAuthorizationPolicyUrl($"{Apiurl}", EntityNames.Module, NewEvent.ModuleId), NewEvent);
} }
public async Task<Event> UpdateEventAsync(Event NewEvent) public async Task<Event> UpdateEventAsync(Event UpdatedEvent)
{ {
return await PutJsonAsync<Event>(CreateAuthorizationPolicyUrl($"{Apiurl}/{NewEvent.EventId}", EntityNames.Module, NewEvent.ModuleId), NewEvent); return await PutJsonAsync<Event>(CreateAuthorizationPolicyUrl($"{Apiurl}/{UpdatedEvent.EventId}", EntityNames.Module, UpdatedEvent.ModuleId), UpdatedEvent);
} }
public async Task DeleteEventAsync(int EventId, int ModuleId) public async Task DeleteEventAsync(int EventId, int ModuleId)
@ -56,12 +55,12 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
return await GetJsonAsync<(Event, Response)>(CreateAuthorizationPolicyUrl($"{Apiurl}/details/{EventId}/{ModuleId}", EntityNames.Module, ModuleId)); return await GetJsonAsync<(Event, Response)>(CreateAuthorizationPolicyUrl($"{Apiurl}/details/{EventId}/{ModuleId}", EntityNames.Module, ModuleId));
} }
public Task<List<Response>> GetEventResponses(int EventId, int ModuleId) public async Task<List<Response>> GetEventResponses(int EventId, int ModuleId)
{ {
throw new System.NotImplementedException(); return await GetJsonAsync<List<Response>>(CreateAuthorizationPolicyUrl($"{Apiurl}/all-responses/{EventId}/{ModuleId}", EntityNames.Module, ModuleId));
} }
public Task<List<User>> GetRecommendedResponses(int EventId, int ModuleId) public Task<List<Response>> GetRecommendedEventResponses(int EventId, int MouleId)
{ {
throw new System.NotImplementedException(); throw new System.NotImplementedException();
} }

View File

@ -131,6 +131,24 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Controllers
} }
} }
// GET api/<controller>/5
[HttpGet("all-respones/{id}/{moduleid}")]
[Authorize(Policy = PolicyNames.ViewModule)]
public async Task<List<Models.Response>> GetResponses(int id, int moduleid)
{
List<Models.Response> eventResponses = await _EventRegistrationService.GetEventResponses(id, moduleid);
if (eventResponses != null && IsAuthorizedEntityId(EntityNames.Module, moduleid))
{
return eventResponses;
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized EventRegistration Get Attempt {EventRegistrationId} {ModuleId}", id, moduleid);
HttpContext.Response.StatusCode = (int)HttpStatusCode.Forbidden;
return null;
}
}
// TODO: Add Event Response Endpoints. // TODO: Add Event Response Endpoints.
} }
} }

View File

@ -1,7 +1,5 @@
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Numerics;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Oqtane.Enums; using Oqtane.Enums;
@ -25,10 +23,9 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
private readonly IUserPermissions _userPermissions; private readonly IUserPermissions _userPermissions;
private readonly ILogManager _logger; private readonly ILogManager _logger;
private readonly IHttpContextAccessor _accessor; private readonly IHttpContextAccessor _accessor;
private readonly ISettingRepository _settingRepository;
private readonly Alias _alias; private readonly Alias _alias;
public ServerEventRegistrationService(IEventRepository EventRepository, IResponseRepository ResponseRepository, INotificationRepository NotificationRepository, IUserRepository UserRepository, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor, ISettingRepository settingRepository) public ServerEventRegistrationService(IEventRepository EventRepository, IResponseRepository ResponseRepository, INotificationRepository NotificationRepository, IUserRepository UserRepository, IUserPermissions userPermissions, ITenantManager tenantManager, ILogManager logger, IHttpContextAccessor accessor)
{ {
_EventRepository = EventRepository; _EventRepository = EventRepository;
_ResponseRepository = ResponseRepository; _ResponseRepository = ResponseRepository;
@ -37,7 +34,6 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
_userPermissions = userPermissions; _userPermissions = userPermissions;
_logger = logger; _logger = logger;
_accessor = accessor; _accessor = accessor;
_settingRepository = settingRepository;
_alias = tenantManager.GetAlias(); _alias = tenantManager.GetAlias();
} }
@ -126,6 +122,34 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
} }
} }
public Task<List<Event>> GetEventsAsync(int ModuleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
{
return Task.FromResult(_EventRepository.GetEvents(ModuleId).ToList());
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Events Get Attempt {ModuleId}", ModuleId);
return null;
}
}
public Task<Event> UpdateEventAsync(Event UpdatedEvent)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, UpdatedEvent.ModuleId, PermissionNames.Edit))
{
UpdatedEvent = _EventRepository.UpdateEvent(UpdatedEvent);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Event Updated {NewEvent}", UpdatedEvent);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Update Attempt {NewEvent}", UpdatedEvent);
UpdatedEvent = null;
}
return Task.FromResult(UpdatedEvent);
}
public Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId) public Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId)
{ {
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View)) if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
@ -154,59 +178,11 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
} }
} }
public async Task<List<User>> GetRecommendedResponses(int EventId, int ModuleId) public Task<List<Response>> GetRecommendedEventResponses(int EventId, int MouleId)
{ {
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View)) throw new System.NotImplementedException();
{
IEnumerable<Response> responses = _ResponseRepository.GetResponses(EventId, ModuleId).DistinctBy(r => r.OwnerId).Where(r => r.OwnerId != _accessor.HttpContext.User.UserId() && r.ResponseType);
IEnumerable<User> users = _UserRepository.GetUsers();
List<Setting> userSettings = _settingRepository.GetSettings("User").ToList();
List<Setting> requestorSettings = userSettings.FindAll(s => s.EntityId == _accessor.HttpContext.User.UserId());
string targetFachrichtung = requestorSettings.FirstOrDefault(s => s.SettingName == "Fachrichtung")?.SettingValue;
int targetStartjahr = int.Parse(requestorSettings.FirstOrDefault(s => s.SettingName == "Jahrgang")?.SettingValue ?? "0");
IEnumerable<GroupingUser> gu = responses.Join(users, r => r.OwnerId, u => u.UserId,
(response, user) => (response, user)).GroupJoin(userSettings, ru => ru.user.UserId,
s => s.EntityId, (ru, s) => new GroupingUser(ru.user, ru.response, s, targetStartjahr, targetFachrichtung)).OrderBy(gu => gu.Score());
return gu.Select(gu => gu.User).Take(10).ToList();
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Response Get Attempt {ModuleId}", ModuleId);
return null;
}
} }
public Task<List<Event>> GetEventsAsync(int ModuleId)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, ModuleId, PermissionNames.View))
{
return Task.FromResult(_EventRepository.GetEvents(ModuleId).ToList());
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Events Get Attempt {ModuleId}", ModuleId);
return null;
}
}
public Task<Event> UpdateEventAsync(Event NewEvent)
{
if (_userPermissions.IsAuthorized(_accessor.HttpContext.User, _alias.SiteId, EntityNames.Module, NewEvent.ModuleId, PermissionNames.Edit))
{
NewEvent = _EventRepository.UpdateEvent(NewEvent);
_logger.Log(LogLevel.Information, this, LogFunction.Update, "Event Updated {NewEvent}", NewEvent);
}
else
{
_logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized Event Update Attempt {NewEvent}", NewEvent);
NewEvent = null;
}
return Task.FromResult(NewEvent);
}
private void SendEventResponseNotification(string subject, string body) private void SendEventResponseNotification(string subject, string body)
{ {
@ -215,76 +191,4 @@ namespace SZUAbsolventenverein.Module.EventRegistration.Services
_NotificationRepository.AddNotification(notification); _NotificationRepository.AddNotification(notification);
} }
} }
public class GroupingUser
{
private User _user;
private Response _response;
private string _fachrichtung;
private int _startjahr;
private int _targetyear;
private string _targetfachrichtung;
public User User { get { return _user; } }
public IEnumerable<Setting> Settings
{
set
{
if (value == null)
{
_fachrichtung = "-";
_startjahr = 0;
return;
}
_fachrichtung = value.FirstOrDefault(v => v.SettingName == "Fachrichtung", new Setting(){SettingValue = "-"}).SettingValue;
_startjahr = int.Parse(value.FirstOrDefault(v => v.SettingName == "Jahrgang", new Setting(){SettingValue = "0"}).SettingValue);
}
}
public string TargetFachrichtung
{
set { _targetfachrichtung = value; }
}
public int TargetJahr
{
set { _targetyear = value; }
}
public GroupingUser(User user, Response response, IEnumerable<Setting> settings, int targetyear, string targetfachrichtung)
{
_user = user;
_response = response;
Settings = settings;
TargetJahr = targetyear;
TargetFachrichtung = targetfachrichtung;
}
public int Score()
{
int total = 0;
total += ScoreYear() * 5;
total += ScoreFachrichtung() * 3;
return total;
}
private int ScoreYear()
{
return Math.Abs(_targetyear - _startjahr);
}
private int ScoreFachrichtung()
{
if (_fachrichtung == _targetfachrichtung)
{
return 1;
}
else
{
return 0;
}
}
}
} }

View File

@ -2,4 +2,25 @@
var SZUAbsolventenverein = SZUAbsolventenverein || {}; var SZUAbsolventenverein = SZUAbsolventenverein || {};
SZUAbsolventenverein.EventRegistration = { SZUAbsolventenverein.EventRegistration = {
createChart: async function (divid, type, labels, datasets, options) {
var container = document.getElementById(divid);
if (container.hasChildNodes()) {
while (container.firstChild) {
container.removeChild(container.firstChild);
}
}
var canvas = document.createElement('canvas');
canvas.id = divid + '-canvas';
container.appendChild(canvas);
var ctx = canvas.getContext('2d');
var chart = new Chart(ctx, {
type: type,
data: {
labels: labels,
datasets: datasets
},
options: options
});
}
}; };

View File

@ -1,32 +1,88 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using Oqtane.Models;
using SZUAbsolventenverein.Module.EventRegistration.Models; using SZUAbsolventenverein.Module.EventRegistration.Models;
namespace SZUAbsolventenverein.Module.EventRegistration.Services namespace SZUAbsolventenverein.Module.EventRegistration.Services
{ {
/// <summary>
/// Methods for managing events and their responses
/// </summary>
public interface IEventRegistrationService public interface IEventRegistrationService
{ {
/* Reine Events */ /// <summary>
/// Alle Events eines Moduls abrufen
/// </summary>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns>Liste aller Veranstaltungen</returns>
Task<List<Event>> GetEventsAsync(int ModuleId); Task<List<Event>> GetEventsAsync(int ModuleId);
/// <summary>
/// Ein bestimmtes Event abrufen
/// </summary>
/// <param name="EventId">das aufzurufende Event</param>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns>Das Event selbst</returns>
Task<Event> GetEventAsync(int EventId, int ModuleId); Task<Event> GetEventAsync(int EventId, int ModuleId);
/// <summary>
/// Ein neues Event anlegen
/// </summary>
/// <param name="NewEvent">das anzulegende Event</param>
/// <returns>das angelegte Event</returns>
Task<Event> AddEventAsync(Event NewEvent); Task<Event> AddEventAsync(Event NewEvent);
Task<Event> UpdateEventAsync(Event NewEvent); /// <summary>
/// Ändern eines bestehenden Events
/// </summary>
/// <param name="UpdatedEvent">Das Eventobjekt mit aktualisierte Event</param>
/// <returns>das gespeicherte Event</returns>
Task<Event> UpdateEventAsync(Event UpdatedEvent);
/// <summary>
/// Löschen eines Events
/// </summary>
/// <param name="EventId">das zu löschende Event</param>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns></returns>
Task DeleteEventAsync(int EventId, int ModuleId); Task DeleteEventAsync(int EventId, int ModuleId);
/// <summary>
/* Events & Responses */ /// Eine neue Antwort zu einem Event hinzufügen
/// </summary>
/// <param name="Response">die Antwort</param>
/// <returns>die gespeicherte Antwort</returns>
Task<Response> AddResponseAsync(Response Response); Task<Response> AddResponseAsync(Response Response);
/// <summary>
/// Eine bestehende Antwort zu einem Event aktualisieren
/// </summary>
/// <param name="Response">die neue Antwort</param>
/// <returns>die gespeicherte neue Antwort</returns>
Task<Response> UpdateResponseAsync(Response Response); Task<Response> UpdateResponseAsync(Response Response);
/// <summary>
/// Details zu einem Event abrufen (Event + Antwort vom auktuellen Benutzer)
/// </summary>
/// <param name="EventId">das aufzurufende Event</param>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns>Tuple aus Event und Antwort</returns>
Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId); Task<(Event, Response)> GetEventDetails(int EventId, int ModuleId);
/// <summary>
/// Alle Antworten zu einem Event abrufen
/// </summary>
/// <param name="EventId">das Event, dessen Antworten geladen werden sollen</param>
/// <param name="ModuleId">das aufrufende Modul</param>
/// <returns>Liste aller Antworten auf das Event</returns>
Task<List<Response>> GetEventResponses(int EventId, int ModuleId); Task<List<Response>> GetEventResponses(int EventId, int ModuleId);
Task<List<User>> GetRecommendedResponses(int EventId, int ModuleId);
/// <summary>
/// 10 Antworten eines Events abrufen, welche gewichtet zurückgeliefert werden
/// </summary>
/// <param name="EventId">das aufzurufende Event</param>
/// <param name="MouleId">das aufrufende Modul</param>
/// <returns>Liste mit 10 </returns>
Task<List<Response>> GetRecommendedEventResponses(int EventId, int MouleId);
} }
} }