From ae0fab301adfe0e84b4ac433d180e3eefb9c664f Mon Sep 17 00:00:00 2001 From: eee4 <41441600+eee4@users.noreply.github.com> Date: Mon, 2 Jun 2025 06:50:21 +0200 Subject: [PATCH] feat: user page with volunteerskills picking support --- WebApp/Endpoints/EventsEndpoints.cs | 8 +- WebApp/ts/eventCreate.ts | 2 + WebApp/ts/eventList.ts | 21 +-- WebApp/ts/userSkills.ts | 192 ++++++++++++++++++++++++++++ WebApp/wwwroot/create.html | 2 +- WebApp/wwwroot/css/style.css | 23 ++++ WebApp/wwwroot/index.html | 2 +- WebApp/wwwroot/js/eventList.js | 33 ++--- WebApp/wwwroot/js/userSkills.js | 183 ++++++++++++++++++++++++++ WebApp/wwwroot/user.html | 85 ++++++++++++ WebApp/wwwroot/view.html | 2 +- 11 files changed, 522 insertions(+), 31 deletions(-) create mode 100644 WebApp/ts/userSkills.ts create mode 100644 WebApp/wwwroot/js/userSkills.js create mode 100644 WebApp/wwwroot/user.html diff --git a/WebApp/Endpoints/EventsEndpoints.cs b/WebApp/Endpoints/EventsEndpoints.cs index 8067c77..8c994bf 100644 --- a/WebApp/Endpoints/EventsEndpoints.cs +++ b/WebApp/Endpoints/EventsEndpoints.cs @@ -201,10 +201,10 @@ namespace WebApp.Endpoints // Uwaga! Zanim to zrobisz, sprawdź, czy użytkownik // jest twórcą danego wydarzenia! Jeżeli nim nie jest, // wyzeruj EventRegistrations! - if (org is null || e.OrganisationId != org.OrganisationId) - { - e.EventRegistrations.Clear(); - } + //if (org is null || e.OrganisationId != org.OrganisationId) + //{ + // e.EventRegistrations.Clear(); + //} if (matchFound) SearchResults.Add(e); } diff --git a/WebApp/ts/eventCreate.ts b/WebApp/ts/eventCreate.ts index 9721b9f..56181c4 100644 --- a/WebApp/ts/eventCreate.ts +++ b/WebApp/ts/eventCreate.ts @@ -1,5 +1,7 @@ import { getEvent, getMyAccount, unhideElementById } from './generalUseHelpers.js'; + + async function createEvent() { // Pobieranie danych z formularza const title = (document.getElementById('title') as HTMLInputElement).value; diff --git a/WebApp/ts/eventList.ts b/WebApp/ts/eventList.ts index 7b3feaf..c3ea842 100644 --- a/WebApp/ts/eventList.ts +++ b/WebApp/ts/eventList.ts @@ -7,24 +7,29 @@ function toggleListSortOrder(org_id: number) { loadEvents(org_id); } -async function getEvents(titleOrDescription?: string) { +async function getEvents(titleOrDescription?: string, fDate?: Date, tDate?: Date) { var res: Response; + var searchbar = document.getElementById("searchbar") as HTMLInputElement; if (titleOrDescription == null) { - res = await fetch("/api/events" + (isAscending ? "?sort=asc" : "")); - if (!res.ok) throw new Error("Couldn't load events"); - } else { - const payload = { - titleOrDescription + titleOrDescription = searchbar.value; + //res = await fetch("/api/events" + (isAscending ? "?sort=asc" : "")); + //if (!res.ok) throw new Error("Couldn't load events"); + } + + var payload = { + titleOrDescription, + fDate, + tDate }; - res = await fetch('/api/events/search', { + + res = await fetch('/api/events/search' + (isAscending ? "?sort=asc" : ""), { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(payload) }); if (!res.ok) throw new Error("Failed to get search results"); - } const events = await res.json(); return events; diff --git a/WebApp/ts/userSkills.ts b/WebApp/ts/userSkills.ts new file mode 100644 index 0000000..98d6057 --- /dev/null +++ b/WebApp/ts/userSkills.ts @@ -0,0 +1,192 @@ +import { getEvent, getMyAccount, unhideElementById, getMyRegisteredEventIds } from './generalUseHelpers.js'; + +var redirected = false; + +document.addEventListener("DOMContentLoaded", async () => { + + var container = document.getElementById("mainContainer"); + const modifyBtn = document.getElementById("editBtn"); + const removeBtn = document.getElementById("removeBtn"); + const applyBtn = document.getElementById("applyBtn"); + const leaveBtn = document.getElementById("leaveBtn"); + var org_id: number = -1; + var org_name: string = ""; + + try { + var user = await getMyAccount(); + if (user && user.isOrganisation) { + const org_id = user.organisationId; + fetch('/api/organizations/' + org_id) + .then(response => response.json()) + .then(data => { + org_name = data.name; + unhideElementById(document, "orgname"); + }) + .catch(error => { + console.error('Failed to fetch organization:', error); + }); + } else { + unhideElementById(document, "orgno"); + } + } catch { + window.location.href = "login.html"; + } + + var thisAccount = null; + thisAccount = await getMyAccount(); + if (thisAccount.isOrganisation) org_id = thisAccount.organisationId; + + if (thisAccount == null) { + if (container !== null) container.innerHTML = `
Błąd we wczytywaniu wydarzenia. Powrót ->
`; + } else { + + const nameText = document.getElementById("nameText") as HTMLElement; + const orgnameText = document.getElementById( "orgname") as HTMLElement; + const dateText = document.getElementById("dateText") as HTMLElement; + const newdateText = new Date(thisAccount.createdAt).toLocaleDateString('pl-PL'); + const newtimeText = new Date(thisAccount.createdAt).toLocaleTimeString('pl-PL'); + + + nameText.innerHTML = thisAccount.firstName + " " + thisAccount.lastName + " (" + thisAccount.email + ")"; + dateText.innerHTML = "📅 Account creation date: " + newdateText + " " + newtimeText; + orgnameText.innerHTML = "👥 Organization: " + org_name; + + if (org_id == -1) { + unhideElementById(document, "skillscont"); + } else if (org_id == -1) { + // Użytkownik jest wolontariuszem + try { + const registeredIds = await getMyRegisteredEventIds(); + } catch { + + } + + } + + unhideElementById(document, "mainContainer"); + + } + +}); + +window.onload = () => { + const selectedSkillsContainer = document.getElementById('selected-skills') as HTMLDivElement; + const dropdown = document.getElementById('skill-dropdown') as HTMLSelectElement; + + dropdown.addEventListener('change', () => { + const skillName = dropdown.options[dropdown.selectedIndex].text; + const skillId = dropdown.options[dropdown.selectedIndex].value; + if (skillName) { + addSkill(skillName, skillId, false); + dropdown.value = ''; // Reset dropdown + } + }); + + function fetchSkills() { + fetch('/api/skills') + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + populateDropdown(data); + }) + .catch(error => { + console.error('There was a problem with the fetch operation:', error); + }); + } + + function fetchUserSkills() { + fetch('/api/auth/skills') + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + populateSkills(data); + }) + .catch(error => { + console.error('There was a problem with the fetch operation:', error); + }); + } + + // Populate dropdown with fetched skills + function populateDropdown(skills: { skillId: number; skillName: string; }[]) { + skills.forEach(skill => { + const option = document.createElement('option'); + option.value = skill.skillId.toString(); + option.textContent = skill.skillName; + dropdown.appendChild(option); + }); + } + + function populateSkills(skills: { skillId: number; skillName: string; }[]) { + skills.forEach(skill => { + addSkill(skill.skillName, skill.skillId, true); + }); + } + + // Call fetchSkills to populate dropdown on load, same for fetchUserSkills() + fetchSkills(); + fetchUserSkills(); + + function getRandomColor(): string { + + const r = Math.floor(Math.random() * 256); + const g = Math.floor(Math.random() * 256); + const b = Math.floor(Math.random() * 256); + + return `rgb(${r}, ${g}, ${b})`; + } + + async function addSkill(skillName: string, skillId: number, dummy_add: boolean) { + if (!document.querySelector(`#selected-skills .skill[data-skill="${skillName}"]`)) { + const skillDiv = document.createElement('div'); + skillDiv.className = 'skill'; + skillDiv.textContent = skillName; + skillDiv.setAttribute('data-skill', skillName); + skillDiv.style.backgroundColor = getRandomColor(); + + if (!dummy_add) { + var skill = skillId; + var payload = { + skill + }; + + var res = await fetch('/api/auth/add_skill', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + var data = await res.json(); + if (res.ok) skillDiv.remove(); + else alert(data.message); + } + + const removeButton = document.createElement('button'); + removeButton.textContent = 'X'; + removeButton.addEventListener('click', async () => { + var skill = skillId; + var payload = { + skill + }; + + var res = await fetch('/api/auth/remove_skill', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + var data = await res.json(); + if (res.ok) skillDiv.remove(); + else alert(data.message); + }); + + skillDiv.appendChild(removeButton); + selectedSkillsContainer.appendChild(skillDiv); + } + } +}; diff --git a/WebApp/wwwroot/create.html b/WebApp/wwwroot/create.html index 47d63a5..45603fa 100644 --- a/WebApp/wwwroot/create.html +++ b/WebApp/wwwroot/create.html @@ -37,7 +37,7 @@Błąd we wczytywaniu wydarzenia. Powrót ->
`; + } + else { + const nameText = document.getElementById("nameText"); + const orgnameText = document.getElementById("orgname"); + const dateText = document.getElementById("dateText"); + const newdateText = new Date(thisAccount.createdAt).toLocaleDateString('pl-PL'); + const newtimeText = new Date(thisAccount.createdAt).toLocaleTimeString('pl-PL'); + nameText.innerHTML = thisAccount.firstName + " " + thisAccount.lastName + " (" + thisAccount.email + ")"; + dateText.innerHTML = "📅 Account creation date: " + newdateText + " " + newtimeText; + orgnameText.innerHTML = "👥 Organization: " + org_name; + if (org_id == -1) { + unhideElementById(document, "skillscont"); + } + else if (org_id == -1) { + // Użytkownik jest wolontariuszem + try { + const registeredIds = yield getMyRegisteredEventIds(); + } + catch (_b) { + } + } + unhideElementById(document, "mainContainer"); + } +})); +window.onload = () => { + const selectedSkillsContainer = document.getElementById('selected-skills'); + const dropdown = document.getElementById('skill-dropdown'); + dropdown.addEventListener('change', () => { + const skillName = dropdown.options[dropdown.selectedIndex].text; + const skillId = dropdown.options[dropdown.selectedIndex].value; + if (skillName) { + addSkill(skillName, skillId, false); + dropdown.value = ''; // Reset dropdown + } + }); + function fetchSkills() { + fetch('/api/skills') + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + populateDropdown(data); + }) + .catch(error => { + console.error('There was a problem with the fetch operation:', error); + }); + } + function fetchUserSkills() { + fetch('/api/auth/skills') + .then(response => { + if (!response.ok) { + throw new Error('Network response was not ok'); + } + return response.json(); + }) + .then(data => { + populateSkills(data); + }) + .catch(error => { + console.error('There was a problem with the fetch operation:', error); + }); + } + // Populate dropdown with fetched skills + function populateDropdown(skills) { + skills.forEach(skill => { + const option = document.createElement('option'); + option.value = skill.skillId.toString(); + option.textContent = skill.skillName; + dropdown.appendChild(option); + }); + } + function populateSkills(skills) { + skills.forEach(skill => { + addSkill(skill.skillName, skill.skillId, true); + }); + } + // Call fetchSkills to populate dropdown on load, same for fetchUserSkills() + fetchSkills(); + fetchUserSkills(); + function getRandomColor() { + const r = Math.floor(Math.random() * 256); + const g = Math.floor(Math.random() * 256); + const b = Math.floor(Math.random() * 256); + return `rgb(${r}, ${g}, ${b})`; + } + function addSkill(skillName, skillId, dummy_add) { + return __awaiter(this, void 0, void 0, function* () { + if (!document.querySelector(`#selected-skills .skill[data-skill="${skillName}"]`)) { + const skillDiv = document.createElement('div'); + skillDiv.className = 'skill'; + skillDiv.textContent = skillName; + skillDiv.setAttribute('data-skill', skillName); + skillDiv.style.backgroundColor = getRandomColor(); + if (!dummy_add) { + var skill = skillId; + var payload = { + skill + }; + var res = yield fetch('/api/auth/add_skill', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + var data = yield res.json(); + if (res.ok) + skillDiv.remove(); + else + alert(data.message); + } + const removeButton = document.createElement('button'); + removeButton.textContent = 'X'; + removeButton.addEventListener('click', () => __awaiter(this, void 0, void 0, function* () { + var skill = skillId; + var payload = { + skill + }; + var res = yield fetch('/api/auth/remove_skill', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload) + }); + var data = yield res.json(); + if (res.ok) + skillDiv.remove(); + else + alert(data.message); + })); + skillDiv.appendChild(removeButton); + selectedSkillsContainer.appendChild(skillDiv); + } + }); + } +}; diff --git a/WebApp/wwwroot/user.html b/WebApp/wwwroot/user.html new file mode 100644 index 0000000..8ed630c --- /dev/null +++ b/WebApp/wwwroot/user.html @@ -0,0 +1,85 @@ + + + + +