diff --git a/availabili.tf/src/client/index.ts b/availabili.tf/src/client/index.ts index 6b3f507..5e6f045 100644 --- a/availabili.tf/src/client/index.ts +++ b/availabili.tf/src/client/index.ts @@ -13,8 +13,11 @@ export type { OpenAPIConfig } from './core/OpenAPI'; export type { AbstractTeamIntegrationSchema } from './models/AbstractTeamIntegrationSchema'; export type { AddPlayerJson } from './models/AddPlayerJson'; export type { AvailabilitySchema } from './models/AvailabilitySchema'; +export type { CreateEventJson } from './models/CreateEventJson'; export type { CreateTeamJson } from './models/CreateTeamJson'; export type { EditMemberRolesJson } from './models/EditMemberRolesJson'; +export type { EventSchema } from './models/EventSchema'; +export type { EventSchemaList } from './models/EventSchemaList'; export type { PlayerSchema } from './models/PlayerSchema'; export type { PlayerTeamAvailabilityRoleSchema } from './models/PlayerTeamAvailabilityRoleSchema'; export type { PutScheduleForm } from './models/PutScheduleForm'; diff --git a/availabili.tf/src/client/models/CreateEventJson.ts b/availabili.tf/src/client/models/CreateEventJson.ts new file mode 100644 index 0000000..1866ba6 --- /dev/null +++ b/availabili.tf/src/client/models/CreateEventJson.ts @@ -0,0 +1,11 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type CreateEventJson = { + description: string; + name: string; + playerIds: Array; + startTime: string; +}; + diff --git a/availabili.tf/src/client/models/EventSchema.ts b/availabili.tf/src/client/models/EventSchema.ts new file mode 100644 index 0000000..e6d3f84 --- /dev/null +++ b/availabili.tf/src/client/models/EventSchema.ts @@ -0,0 +1,13 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +export type EventSchema = { + createdAt: string; + description: string; + id: number; + name: string; + startTime: string; + teamId: number; +}; + diff --git a/availabili.tf/src/client/models/EventSchemaList.ts b/availabili.tf/src/client/models/EventSchemaList.ts new file mode 100644 index 0000000..b425d11 --- /dev/null +++ b/availabili.tf/src/client/models/EventSchemaList.ts @@ -0,0 +1,6 @@ +/* generated using openapi-typescript-codegen -- do not edit */ +/* istanbul ignore file */ +/* tslint:disable */ +/* eslint-disable */ +import type { EventSchema } from './EventSchema'; +export type EventSchemaList = Array; diff --git a/availabili.tf/src/client/services/DefaultService.ts b/availabili.tf/src/client/services/DefaultService.ts index 3ef0c22..c5c1fb0 100644 --- a/availabili.tf/src/client/services/DefaultService.ts +++ b/availabili.tf/src/client/services/DefaultService.ts @@ -4,8 +4,11 @@ /* eslint-disable */ import type { AbstractTeamIntegrationSchema } from '../models/AbstractTeamIntegrationSchema'; import type { AddPlayerJson } from '../models/AddPlayerJson'; +import type { CreateEventJson } from '../models/CreateEventJson'; import type { CreateTeamJson } from '../models/CreateTeamJson'; import type { EditMemberRolesJson } from '../models/EditMemberRolesJson'; +import type { EventSchema } from '../models/EventSchema'; +import type { EventSchemaList } from '../models/EventSchemaList'; import type { PlayerSchema } from '../models/PlayerSchema'; import type { PutScheduleForm } from '../models/PutScheduleForm'; import type { SetUsernameJson } from '../models/SetUsernameJson'; @@ -45,6 +48,104 @@ export class DefaultService { url: '/api/debug/set-cookie', }); } + /** + * get_team_events + * @param teamId + * @returns EventSchemaList OK + * @throws ApiError + */ + public getTeamEvents( + teamId: number, + ): CancelablePromise { + return this.httpRequest.request({ + method: 'GET', + url: '/api/events/team/id/{team_id}', + path: { + 'team_id': teamId, + }, + errors: { + 422: `Unprocessable Entity`, + }, + }); + } + /** + * create_event + * @param teamId + * @param requestBody + * @returns EventSchema OK + * @throws ApiError + */ + public postApiEventsTeamIdTeamId( + teamId: number, + requestBody?: CreateEventJson, + ): CancelablePromise { + return this.httpRequest.request({ + method: 'POST', + url: '/api/events/team/id/{team_id}', + path: { + 'team_id': teamId, + }, + body: requestBody, + mediaType: 'application/json', + errors: { + 422: `Unprocessable Entity`, + }, + }); + } + /** + * get_user_events + * @param userId + * @returns void + * @throws ApiError + */ + public getApiEventsUserIdUserId( + userId: number, + ): CancelablePromise { + return this.httpRequest.request({ + method: 'GET', + url: '/api/events/user/id/{user_id}', + path: { + 'user_id': userId, + }, + }); + } + /** + * get_event + * @param eventId + * @returns EventSchema OK + * @throws ApiError + */ + public getEvent( + eventId: number, + ): CancelablePromise { + return this.httpRequest.request({ + method: 'GET', + url: '/api/events/{event_id}', + path: { + 'event_id': eventId, + }, + errors: { + 422: `Unprocessable Entity`, + }, + }); + } + /** + * set_event_players + * @param eventId + * @returns void + * @throws ApiError + */ + public patchApiEventsEventIdPlayers( + eventId: number, + ): CancelablePromise { + return this.httpRequest.request({ + method: 'PATCH', + url: '/api/events/{event_id}/players', + path: { + 'event_id': eventId, + }, + }); + } /** * logout * @returns void diff --git a/availabili.tf/src/components/EventCard.vue b/availabili.tf/src/components/EventCard.vue new file mode 100644 index 0000000..520a2e8 --- /dev/null +++ b/availabili.tf/src/components/EventCard.vue @@ -0,0 +1,113 @@ + + + + + diff --git a/availabili.tf/src/components/EventList.vue b/availabili.tf/src/components/EventList.vue new file mode 100644 index 0000000..8210e39 --- /dev/null +++ b/availabili.tf/src/components/EventList.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/availabili.tf/src/components/MembersList.vue b/availabili.tf/src/components/MembersList.vue index c659165..a4c6655 100644 --- a/availabili.tf/src/components/MembersList.vue +++ b/availabili.tf/src/components/MembersList.vue @@ -34,9 +34,7 @@ function leaveTeam() { Members - {{ teamMembers?.length }} member(s), - {{ availableMembers?.length }} currently available, - {{ availableMembersNextHour?.length }} available in the next hour + {{ teamMembers?.length }} member(s)
diff --git a/availabili.tf/src/stores/events.ts b/availabili.tf/src/stores/events.ts new file mode 100644 index 0000000..3d8fd06 --- /dev/null +++ b/availabili.tf/src/stores/events.ts @@ -0,0 +1,31 @@ +import type { EventSchema } from "@/client"; +import { defineStore } from "pinia"; +import { computed, reactive, ref } from "vue"; +import { useClientStore } from "./client"; + +export const useEventsStore = defineStore("events", () => { + const clientStore = useClientStore(); + const client = clientStore.client; + + const events = ref([ ]); + + const eventsById = computed(() => { + return events.value + .reduce((acc, event) => { + return { ...acc, [event.id]: event }; + }, { } as { [id: number]: EventSchema }); + }); + + function fetchEvent(id: number) { + return clientStore.call( + fetchEvent.name, + () => client.default.getEvent(id), + ); + } + + return { + events, + eventsById, + fetchEvent, + } +}); diff --git a/availabili.tf/src/stores/teams/events.test.ts b/availabili.tf/src/stores/teams/events.test.ts new file mode 100644 index 0000000..328c7c4 --- /dev/null +++ b/availabili.tf/src/stores/teams/events.test.ts @@ -0,0 +1,38 @@ +import { createPinia, setActivePinia } from "pinia"; +import { beforeEach, describe, expect, it } from "vitest"; +import { useEventsStore } from "../events"; +import { useTeamsEventsStore } from "./events"; + +describe("Team events store", () => { + beforeEach(() => { + setActivePinia(createPinia()); + }) + + it("should reflect the same events as the events store", () => { + const eventsStore = useEventsStore(); + eventsStore.events = [ + { + createdAt: "", + description: "", + id: 0, + name: "test", + startTime: "", + teamId: 5, + }, + { + createdAt: "", + description: "", + id: 2, + name: "test", + startTime: "", + teamId: 5, + } + ]; + + const teamEventsStore = useTeamsEventsStore(); + const teamEvents = teamEventsStore.teamEvents[5]; + + expect(teamEvents.length).toEqual(eventsStore.events.length); + expect(teamEvents).toEqual(eventsStore.events); + }); +}); diff --git a/availabili.tf/src/stores/teams/events.ts b/availabili.tf/src/stores/teams/events.ts new file mode 100644 index 0000000..ea8a614 --- /dev/null +++ b/availabili.tf/src/stores/teams/events.ts @@ -0,0 +1,45 @@ +import { defineStore } from "pinia"; +import { useClientStore } from "../client"; +import type { EventSchema, EventSchemaList } from "@/client"; +import { useEventsStore } from "../events"; +import { computed } from "vue"; + +export const useTeamsEventsStore = defineStore("teamsEvents", () => { + const clientStore = useClientStore(); + const client = clientStore.client; + const eventsStore = useEventsStore(); + + const teamEvents = computed(() => { + console.log("Recomputing teamEvents"); + + // map events to objects with teamId as key, and array of events as value + return eventsStore.events + .reduce((acc, event) => { + if (!acc[event.teamId]) { + acc[event.teamId] = []; + } + acc[event.teamId].push(event); + return acc; + }, { } as { [teamId: number]: EventSchema[] }); + }); + + function fetchTeamEvents(teamId: number) { + return clientStore.call( + fetchTeamEvents.name, + () => client.default.getTeamEvents(teamId), + (result: EventSchemaList) => { + result.forEach((event) => { + // insert into event store + //eventsStore.events[event.id] = event; + eventsStore.events.push(event); + }); + return result; + } + ); + } + + return { + teamEvents, + fetchTeamEvents, + } +}); diff --git a/availabili.tf/src/views/TeamDetailsView.vue b/availabili.tf/src/views/TeamDetailsView.vue index c341c2f..5b9b30b 100644 --- a/availabili.tf/src/views/TeamDetailsView.vue +++ b/availabili.tf/src/views/TeamDetailsView.vue @@ -1,14 +1,17 @@