holy ravioli

This commit is contained in:
Laurent
2025-03-20 17:36:46 +01:00
parent fd7bdace3b
commit 609ef2b705
28 changed files with 245 additions and 93 deletions

View File

@@ -5,7 +5,4 @@ import java.util.Set;
public class AttendeeDTO {
public String name;
public Set<EventDateDTO> dates;
}

View File

@@ -1,10 +1,11 @@
package be.naaturel.letsmeet.dto.httpRequest;
import java.util.Map;
import java.util.Set;
public class EventDTO {
public String name;
public Set<AttendeeDTO> attendees;
public Map<String, Set<AttendeeDTO>> dates;
}

View File

@@ -22,13 +22,12 @@ public class AttendeeDTOMapper implements Mapper<Attendee, AttendeeDTO> {
public AttendeeDTO toEntity(Attendee d) {
AttendeeDTO dto = new AttendeeDTO();
dto.name = d.getName();
dto.dates = dateMapper.toEntities(d.getDates(), HashSet::new);
return dto;
}
@Override
public Attendee toModel(AttendeeDTO d) {
return new Attendee(d.name, dateMapper.toModels(d.dates, HashSet::new));
return null;
}
@Override

View File

@@ -1,30 +1,58 @@
package be.naaturel.letsmeet.mappers.requests;
import be.naaturel.letsmeet.core.models.EventDate;
import be.naaturel.letsmeet.dto.httpRequest.EventDTO;
import be.naaturel.letsmeet.dto.httpRequest.AttendeeDTO;
import be.naaturel.letsmeet.dto.httpRequest.EventDateDTO;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.core.models.Event;
import be.naaturel.letsmeet.core.models.Attendee;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;
public class EventDTOMapper implements Mapper<Event, EventDTO> {
private final Mapper<Attendee, AttendeeDTO> attendeeMapper = new AttendeeDTOMapper();
private final Mapper<EventDate, EventDateDTO> dateMapper = new EventDateDTOMapper();
@Override
public EventDTO toEntity(Event event) {
EventDTO eventDTO = new EventDTO();
eventDTO.name = event.getName();
eventDTO.attendees = attendeeMapper.toEntities(event.getAttendees(), HashSet::new);
//eventDTO.dates = attendeeMapper.toEntities(event.getAttendees(), HashSet::new);
//TODO : MUST BE CLEANED
eventDTO.dates = new HashMap<>();
event.getAttendees().forEach(a -> {
a.getDates().forEach(d -> {
EventDateDTO dtoD = dateMapper.toEntity(d);
AttendeeDTO dtoA = attendeeMapper.toEntity(a);
String key = String.valueOf(d.getTimeStamp());
if(eventDTO.dates.containsKey(key)){
eventDTO.dates.get(key).add(dtoA);
} else {
Set<AttendeeDTO> s = new HashSet<>();
s.add(dtoA);
eventDTO.dates.put(key, s);
}
});
});
return eventDTO;
}
@Override
public Event toModel(EventDTO dto) {
return new Event(dto.name, attendeeMapper.toModels(dto.attendees, HashSet::new));
//return new Event(dto.name, attendeeMapper.toModels(dto.dates, HashSet::new));
Set<Attendee> set = new HashSet<>();
for (String key : dto.dates.keySet()) {
set.addAll(attendeeMapper.toModels(dto.dates.get(key), HashSet::new));
}
return new Event(dto.name, set);
}
@Override

View File

@@ -1,6 +1,7 @@
package be.naaturel.letsmeet.mappers;
import be.naaturel.letsmeet.dto.database.EventDateEntity;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.mappers.database.EventDateMapper;
import be.naaturel.letsmeet.core.models.EventDate;
import org.junit.jupiter.api.BeforeAll;

View File

@@ -0,0 +1,56 @@
package be.naaturel.letsmeet.mappers.dto;
import be.naaturel.letsmeet.core.models.Event;
import be.naaturel.letsmeet.dto.httpRequest.EventDTO;
import be.naaturel.letsmeet.mappers.Mapper;
import be.naaturel.letsmeet.mappers.requests.EventDTOMapper;
import be.naaturel.letsmeet.mock.dto.MockEventDTO;
import be.naaturel.letsmeet.mock.models.MockEventModel;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class EventDTOMapperTest {
private static MockEventDTO mockDto;
private static MockEventModel mockModel;
private static Mapper<Event, EventDTO> mapper;
@BeforeAll
static void setup(){
mockDto = new MockEventDTO();
mockModel = new MockEventModel();
mapper = new EventDTOMapper();
}
@Test
void single_dto_to_model_test(){
Event res = mapper.toModel(mockDto);
assertEquals(res.getName(), mockDto.name);
}
@Test
void single_model_to_dto_test(){
EventDTO res = mapper.toEntity(mockModel);
assertEquals(res.name, mockModel.getName());
}
@Test
void multiple_dto_to_models_test(){
List<Event> res = mapper.toModels(Set.of(mockDto), ArrayList::new);
assertEquals(res.size(), 1);
assertEquals(res.getFirst().getName(), mockDto.name);
}
@Test
void mulitple_models_to_dto_test(){
List<EventDTO> res = mapper.toEntities(Set.of(mockModel), ArrayList::new);
assertEquals(res.size(), 1);
assertEquals(res.getFirst().name, mockModel.getName());
}
}

View File

@@ -0,0 +1,11 @@
package be.naaturel.letsmeet.mock.dto;
import be.naaturel.letsmeet.dto.httpRequest.AttendeeDTO;
public class MockAttendeeDTO extends AttendeeDTO {
public MockAttendeeDTO(){
}
}

View File

@@ -0,0 +1,24 @@
package be.naaturel.letsmeet.mock.dto;
import be.naaturel.letsmeet.core.models.Attendee;
import be.naaturel.letsmeet.dto.httpRequest.AttendeeDTO;
import be.naaturel.letsmeet.dto.httpRequest.EventDTO;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
public class MockEventDTO extends EventDTO {
public MockEventDTO() {
this.name = "Mocked event";
this.dates = new HashMap<>();
populate(0, new HashSet<>());
populate(1, new HashSet<>());
populate(2, new HashSet<>());
}
private void populate(long timestamp, Set<AttendeeDTO> attendees){
this.dates.put(String.valueOf(timestamp), attendees);
}
}

View File

@@ -0,0 +1,11 @@
package be.naaturel.letsmeet.mock.jpa;
import be.naaturel.letsmeet.dto.database.EventEntity;
public class MockEventEntity extends EventEntity {
public MockEventEntity(){
}
}

View File

@@ -0,0 +1,13 @@
package be.naaturel.letsmeet.mock.models;
import be.naaturel.letsmeet.core.models.Attendee;
import be.naaturel.letsmeet.core.models.Event;
import java.util.HashSet;
import java.util.Set;
public class MockEventModel extends Event {
public MockEventModel() {
super("Mock event model", new HashSet<>());
}
}

View File

Before

Width:  |  Height:  |  Size: 251 B

After

Width:  |  Height:  |  Size: 251 B

View File

Before

Width:  |  Height:  |  Size: 254 B

After

Width:  |  Height:  |  Size: 254 B

View File

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 7.1 KiB

View File

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import ArrowRight from "@/assets/arrow-right.svg"
import ArrowLeft from "@/assets/arrow-left.svg";
import ArrowRight from "@/assets/svg/arrow-right.svg"
import ArrowLeft from "@/assets/svg/arrow-left.svg";
import {ref, onMounted, watch} from "vue";
import { datePickerStore } from "@/stores/CalendarStore.ts";
import { Calendar } from "@/models/Calendar.ts";

View File

@@ -10,7 +10,6 @@ const props = defineProps({
}
});
// Method to handle the update
const updateValue = (event : any) => {
emit('update:value', event.target.value);
};

View File

@@ -1,17 +1,17 @@
import type {Attendee} from "@/models/Attendee.ts";
import type {TimeStamp} from "@/models/TimeStamp.ts";
import type {EventDate} from "@/models/EventDate.ts";
import type {AttendeeDto} from "@/dto/AttendeeDto.ts";
export class EventDto {
public name: string;
public token: string;
public attendees: AttendeeDto[];
public dates : Map<EventDate, Attendee[]>
public constructor(name: string, token: string, attendees: AttendeeDto[]) {
public constructor(name: string, token: string, dates: Map<EventDate, Attendee[]>) {
this.name = name;
this.token = token;
this.attendees = attendees;
this.dates = dates;
}
}

View File

@@ -1,25 +1,18 @@
import type {TimeStamp, TimeStampState} from "@/models/TimeStamp.ts";
import type {EventDate, EventDateState} from "@/models/EventDate.ts";
export class Attendee {
private name: string;
private dates: TimeStamp[];
public constructor(name: string, dates: TimeStamp[]) {
public constructor(name: string) {
this.name = name;
this.dates = dates;
}
public getName() : string {
return this.name;
}
public getDates() : TimeStamp[] {
return this.dates;
}
}
export interface AttendeeState {
name : string
dates : TimeStampState[]
}

View File

@@ -1,18 +1,16 @@
import type {Attendee, AttendeeState} from "@/models/Attendee.ts";
import type {TimeStamp} from "@/models/TimeStamp.ts";
import type {EventDate, EventDateState} from "@/models/EventDate.ts";
export class Event {
private name: string;
private token: string;
private attendees: Attendee[];
private groups : Map<number, string[]>;
private dates: Map<number, Attendee[]>;
public constructor(name: string, token: string, attendees: Attendee[]) {
public constructor(name: string, token: string, dates : Map<number, Attendee[]>) {
this.name = name;
this.token = token;
this.attendees = attendees;
this.groups = this.byDates();
this.dates = dates;
}
public getName() : string {
@@ -23,34 +21,14 @@ export class Event {
return this.token;
}
public getAttendees() : Attendee[] {
return this.attendees;
public getDates() : Map<number, Attendee[]> {
return this.dates;
}
public getGroups() : Map<number, string[]> { return this.groups; }
private byDates() : Map<number, string[]> {
let res : Map<number, string[]> = new Map();
this.attendees.forEach((attendee: Attendee) => {
attendee.getDates().forEach((timeStamp: TimeStamp) => {
let value : number = timeStamp.getValue();
if(res.has(value)) {
res.get(value)?.push(attendee.getName());
} else {
res.set(value, []);
res.get(value)?.push(attendee.getName());
}
});
});
return res;
}
}
export interface EventState {
name : String
token : String
attendees: AttendeeState[];
name : string
token : string
dates: Map<EventDateState, AttendeeState[]>;
}

View File

@@ -1,4 +1,4 @@
export class TimeStamp {
export class EventDate {
private readonly value : number;
@@ -9,8 +9,13 @@ export class TimeStamp {
public getValue() : number{
return this.value;
}
public toString() {
this.value.toString();
}
}
export interface TimeStampState {
export interface EventDateState {
value : number;
}

View File

@@ -23,8 +23,22 @@ export class EventRequests {
let url = this.formatUrl([this.baseUrl, this.endpoints.EVENTS, token]);
return fetch(url)
.then(response => response.json())
.then(data => {
return new EventDto(data.name, data.token, data.dates)
})
.catch(error => console.error(error));
}
public async createEvent(event : EventDto){
let url = this.formatUrl([this.baseUrl, this.endpoints.CREATE]);
return fetch(url, {
method: "POST",
body : JSON.stringify(event)
})
.then(response => response.json())
.then(data => new EventDto(data.name, data.token, data.attendees))
.catch(error => console.error(error));
}
}

View File

@@ -1,22 +1,22 @@
import { defineStore } from 'pinia'
import {TimeStamp} from "@/models/TimeStamp.ts";
import {EventDate} from "@/models/EventDate.ts";
export const datePickerStore = defineStore('datePicker', {
state: () => {
return { dates: [] as TimeStamp[] }
return { dates: [] as EventDate[] }
},
getters: {
value: (state) : TimeStamp[] => state.dates as TimeStamp[],
value: (state) : EventDate[] => state.dates as EventDate[],
},
actions: {
getValue(){
return this.dates;
},
update(dates : Date[]) : void {
this.dates = dates.map(date => new TimeStamp(date));
this.dates = dates.map(date => new EventDate(date));
},
clear() : void {
this.dates = [] as TimeStamp[];
this.dates = [] as EventDate[];
},
},
})

View File

@@ -1,50 +1,69 @@
import {defineStore} from 'pinia'
import {EventRequests} from "@/requests/EventRequests.ts";
import type {EventDto} from "@/dto/EventDto.ts";
import {EventDto} from "@/dto/EventDto.ts";
import {Event, type EventState} from "@/models/Event.ts";
import type {AttendeeDto} from "@/dto/AttendeeDto.ts";
import {Attendee, type AttendeeState} from "@/models/Attendee.ts";
import {TimeStamp, type TimeStampState} from "@/models/TimeStamp.ts";
import type {TimeStampDto} from "@/dto/TimeStampDto.ts";
import {EventDate, type EventDateState} from "@/models/EventDate.ts";
const requests = new EventRequests();
function mapToDto() : EventDto{
return new EventDto("", "", new Map());
}
function mapToModel(state : EventState) : Event{
let dates: Map<number, Attendee[]> = new Map();
for (let [date, attendeesState] of state.dates.entries()) {
let attendees : Attendee[] = attendeesState.map(attendee => {
return new Attendee(attendee.name);
})
dates.set(date.value, attendees);
}
return new Event(state.name, state.token, dates);
}
function mapToState(dto : EventDto) : EventState {
let event : EventState = {name : "", token : "", dates: new Map<EventDateState, AttendeeState[]>()};
event.name = dto.name;
event.token = dto.token;
Object.entries(dto.dates).forEach(([key, attendees]) => {
let dateState : EventDateState = { value: Number(key) };
event.dates.set(dateState, attendees);
});
return event;
}
export const eventStore = defineStore('eventStore', {
state: (): {event : EventState} => {
return {
event : {
name: "",
token: "",
attendees: [] as AttendeeState[]
dates: new Map<EventDateState, AttendeeState[]>()
}};
},
getters : {
getEvent(state) : Event {
let attendees : Attendee[] = state.event.attendees.map((a : AttendeeState) => {
let dates: TimeStamp[] = a.dates.map(d => new TimeStamp(new Date(d.value)))
return new Attendee(a.name, dates);
});
return new Event(state.event.name.toString(), "", attendees);
return mapToModel(state.event);
}
},
actions: {
setName(name : string){
this.event.name = name;
},
async fetch(token: string): Promise<void> {
try{
let data : EventDto | void = await requests.queryEvent(token);
if(!data) throw new Error("No event found");
this.event.name = data.name;
this.event.token = data.token;
this.event.attendees = data.attendees.map((a: AttendeeDto) => ({
name: a.name,
dates: a.dates.map((date: TimeStampDto) => ({
value: date.timestamp
})) as TimeStampState[]
}));
this.event = mapToState(data);
} catch (error) {
console.error(error);
throw new Error("Unable to fetch.");
throw new Error("Unable to fetch. " + error);
}
},
async create(){
let event = mapToDto();
await requests.createEvent(event)
}
},
});

View File

@@ -1,11 +1,11 @@
import type {TimeStamp} from "@/models/TimeStamp.ts";
import type {EventDate} from "@/models/EventDate.ts";
import type {Attendee} from "@/models/Attendee.ts";
/**
* I hate JavaScript and TypeScript with every single inch of my body
*/
export class CustomMap extends Map<TimeStamp, Attendee> {
has(obj: TimeStamp): boolean {
export class CustomMap extends Map<EventDate, Attendee> {
has(obj: EventDate): boolean {
obj.getValue()
return false;
}

View File

@@ -4,6 +4,10 @@ import Calendar from "@/components/Calendar.vue";
import TextBlock from "@/components/TextBlock.vue";
import NavLink from "@/components/NavLink.vue";
import InputField from "@/components/InputField.vue";
import {eventStore} from "@/stores/EventStore.ts";
const store = eventStore();
</script>
<template>
@@ -13,7 +17,7 @@ import InputField from "@/components/InputField.vue";
<h1>Create an <span class="colored-text">event</span></h1>
</TextBlock>
<div class="event-form">
<InputField placeholder="Event name"/>
<InputField placeholder="Event name" @update:value="(newValue) => { store.setName(newValue) }"/>
<Calendar class="calendar"/>
<NavLink name="Create" description="Create" class="create-button"></NavLink>
</div>

View File

@@ -43,12 +43,11 @@ function formatDate(timestamp : number) : String{
<div v-else>
Name : {{ event.getName() }} <br>
<div v-for="(timestamp) in event.getGroups().keys()" >
{{ formatDate(timestamp) }}
<div v-for="(attendee) in event.getGroups().get(timestamp)">
{{ attendee }}
<div v-for="(date) in event.getDates().keys()">
{{formatDate(date)}}
<div v-for="(attendee) in event.getDates().get(date)">
{{attendee.getName()}}
</div>
=================
</div>
</div>

View File

@@ -11,7 +11,7 @@ import TextBlock from "@/components/TextBlock.vue";
<h1>Welcome !</h1>
<p>
This website is currently under <span class="colored-text">development</span> and might look ugly as fuck
bla bla bla I'm just writting things nobody will read to fill the space and see how it looks.
bla bla bla I'm just writing things nobody will read to fill the space and see how it looks.
</p>
<p>
Yes I know i could have use

View File

@@ -19,7 +19,7 @@ const token = ref("");
<div class="actions-group">
<h1>Event <span class="colored-text">code</span></h1>
<InputField @update:value="(newValue) => {token = newValue}" />
<NavLink description="Go for it !" name="event" :params="{ token: token }" />
<NavLink description="Go for it !" name="event" :params="{ token: token }"/>
</div>
</div>