add locals on MyCalendar app

This commit is contained in:
Julien Fastré 2022-07-02 15:13:02 +02:00
parent 2d71ba9078
commit e5aada5561
9 changed files with 159 additions and 3 deletions

View File

@ -1,5 +1,6 @@
import {EventInput} from '@fullcalendar/vue3';
import {DateTime, Location, User, UserAssociatedInterface} from '../../../ChillMainBundle/Resources/public/types' ;
import {Person} from "../../../ChillPersonBundle/Resources/public/types";
export interface CalendarRange {
id: number;
@ -30,6 +31,15 @@ export interface Calendar {
id: number;
}
export interface CalendarLight {
id: number;
endDate: DateTime;
startDate: DateTime;
mainUser: User;
persons: Person[];
status: "valid" | "moved" | "canceled";
}
export interface CalendarRemote {
id: number;
endDate: DateTime;

View File

@ -1,7 +1,7 @@
import {fetchResults} from '../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods';
import {datetimeToISO} from '../../../../../ChillMainBundle/Resources/public/chill/js/date';
import {User} from '../../../../../ChillMainBundle/Resources/public/types';
import {CalendarRange, CalendarRemote} from '../../types';
import {CalendarLight, CalendarRange, CalendarRemote} from '../../types';
// re-export whoami
export {whoami} from "../../../../../ChillMainBundle/Resources/public/lib/api/user";
@ -28,3 +28,11 @@ export const fetchCalendarRemoteForUser = (user: User, start: Date, end: Date):
return fetchResults<CalendarRemote>(uri, {dateFrom, dateTo});
}
export const fetchCalendarLocalForUser = (user: User, start: Date, end: Date): Promise<CalendarLight[]> => {
const uri = `/api/1.0/calendar/calendar/by-user/${user.id}.json`;
const dateFrom = datetimeToISO(start);
const dateTo = datetimeToISO(end);
return fetchResults<CalendarLight>(uri, {dateFrom, dateTo});
}

View File

@ -1,7 +1,7 @@
import {COLORS} from '../const';
import {ISOToDatetime} from '../../../../../../ChillMainBundle/Resources/public/chill/js/date';
import {DateTime, User} from '../../../../../../ChillMainBundle/Resources/public/types';
import {CalendarRange, CalendarRemote} from '../../../types';
import {CalendarLight, CalendarRange, CalendarRemote} from '../../../types';
import type {EventInputCalendarRange} from '../../../types';
import {EventInput} from '@fullcalendar/vue3';
@ -90,3 +90,14 @@ export const remoteToFullCalendarEvent = (entity: CalendarRemote): EventInput &
is: 'remote',
};
}
export const localsToFullCalendarEvent = (entity: CalendarLight): EventInput & {id: string} => {
return {
id: `local_${entity.id}`,
title: entity.persons.map(p => p.text).join(', '),
start: entity.startDate.datetime8601,
end: entity.endDate.datetime8601,
allDay: false,
is: 'local',
};
}

View File

@ -74,6 +74,7 @@
<span :class="eventClasses(arg.event)">
<b v-if="arg.event.extendedProps.is === 'remote'">{{ arg.event.title}}</b>
<b v-else-if="arg.event.extendedProps.is === 'range'">{{ arg.timeText }} - {{ arg.event.extendedProps.locationName }}</b>
<b v-else-if="arg.event.extendedProps.is === 'local'">{{ arg.event.title}}</b>
<b v-else >no 'is'</b>
<a v-if="arg.event.extendedProps.is === 'range'" class="fa fa-fw fa-times delete"
@click.prevent="onClickDelete(arg.event)">

View File

@ -8,12 +8,14 @@ import calendarRemotes, {CalendarRemotesState} from './modules/calendarRemotes';
import {whoami} from "../../../../../../ChillMainBundle/Resources/public/lib/api/user";
import {User} from '../../../../../../ChillMainBundle/Resources/public/types';
import locations, {LocationState} from "./modules/location";
import calendarLocals, {CalendarLocalsState} from "./modules/calendarLocals";
const debug = process.env.NODE_ENV !== 'production';
export interface State {
calendarRanges: CalendarRangesState,
calendarRemotes: CalendarRemotesState,
calendarLocals: CalendarLocalsState,
fullCalendar: FullCalendarState,
me: MeState,
locations: LocationState
@ -30,6 +32,7 @@ const futureStore = function(): Promise<Store<State>> {
fullCalendar,
calendarRanges,
calendarRemotes,
calendarLocals,
locations,
},
mutations: {}

View File

@ -0,0 +1,95 @@
import {State} from './../index';
import {ActionContext, Module} from 'vuex';
import {CalendarLight} from '../../../../types';
import {fetchCalendarLocalForUser} from '../../../Calendar/api';
import {EventInput} from '@fullcalendar/vue3';
import {localsToFullCalendarEvent} from "../../../Calendar/store/utils";
import {TransportExceptionInterface} from "../../../../../../../ChillMainBundle/Resources/public/lib/api/apiMethods";
import {COLORS} from "../../../Calendar/const";
export interface CalendarLocalsState {
locals: EventInput[],
localsLoaded: {start: number, end: number}[],
localsIndex: Set<string>,
key: number
}
type Context = ActionContext<CalendarLocalsState, State>;
export default <Module<CalendarLocalsState, State>> {
namespaced: true,
state: (): CalendarLocalsState => ({
locals: [],
localsLoaded: [],
localsIndex: new Set<string>(),
key: 0
}),
getters: {
isLocalsLoaded: (state: CalendarLocalsState) => ({start, end}: {start: Date, end: Date}): boolean => {
for (let range of state.localsLoaded) {
if (start.getTime() === range.start && end.getTime() === range.end) {
return true;
}
}
return false;
},
},
mutations: {
addLocals(state: CalendarLocalsState, ranges: CalendarLight[]) {
console.log('addLocals', ranges);
const toAdd = ranges
.map(cr => localsToFullCalendarEvent(cr))
.filter(r => !state.localsIndex.has(r.id));
toAdd.forEach((r) => {
state.localsIndex.add(r.id);
state.locals.push(r);
});
state.key = state.key + toAdd.length;
},
addLoaded(state: CalendarLocalsState, payload: {start: Date, end: Date}) {
state.localsLoaded.push({start: payload.start.getTime(), end: payload.end.getTime()});
},
},
actions: {
fetchLocals(ctx: Context, payload: {start: Date, end: Date}): Promise<null> {
const start = payload.start;
const end = payload.end;
if (ctx.rootGetters['me/getMe'] === null) {
return Promise.resolve(null);
}
if (ctx.getters.isLocalsLoaded({start, end})) {
return Promise.resolve(ctx.getters.getRangeSource);
}
ctx.commit('addLoaded', {
start: start,
end: end,
});
return fetchCalendarLocalForUser(
ctx.rootGetters['me/getMe'],
start,
end
)
.then((remotes: CalendarLight[]) => {
// to be add when reactivity problem will be solve ?
//ctx.commit('addRemotes', remotes);
const inputs = remotes
.map(cr => localsToFullCalendarEvent(cr))
.map(cr => ({...cr, backgroundColor: COLORS[0], textColor: 'black', editable: false}))
ctx.commit('calendarRanges/addExternals', inputs, {root: true});
return Promise.resolve(null);
})
.catch((e: TransportExceptionInterface) => {
console.error(e);
return Promise.resolve(null);
});
}
}
};

View File

@ -41,7 +41,8 @@ export default {
return Promise.all([
ctx.dispatch('calendarRanges/fetchRanges', {start, end}, {root: true}).then(_ => Promise.resolve(null)),
ctx.dispatch('calendarRemotes/fetchRemotes', {start, end}, {root: true}).then(_ => Promise.resolve(null))
ctx.dispatch('calendarRemotes/fetchRemotes', {start, end}, {root: true}).then(_ => Promise.resolve(null)),
ctx.dispatch('calendarLocals/fetchLocals', {start, end}, {root: true}).then(_ => Promise.resolve(null))
]
).then(_ => Promise.resolve(null));

View File

@ -3,6 +3,11 @@ export interface DateTime {
datetime8601: string
}
export interface Civility {
id: number;
// TODO
}
export interface Job {
id: number;
type: "user_job";

View File

@ -0,0 +1,22 @@
import {Address, Center, Civility, DateTime} from "../../../ChillMainBundle/Resources/public/types";
export interface Person {
id: number;
type: "person";
text: string;
textAge: string;
firstName: string;
lastName: string;
current_household_address: Address | null;
birthdate: DateTime | null;
deathdate: DateTime | null;
age: number;
phonenumber: string;
mobilenumber: string;
email: string;
gender: "woman" | "man" | "other";
centers: Center[];
civility: Civility | null;
current_household_id: number;
current_residential_addresses: Address[];
}