Skip to content

Commit

Permalink
moved routes to hub map module
Browse files Browse the repository at this point in the history
  • Loading branch information
piggydoughnut committed Jan 25, 2024
1 parent 7a7b539 commit 4e01ef6
Show file tree
Hide file tree
Showing 9 changed files with 316 additions and 148 deletions.
2 changes: 1 addition & 1 deletion src/modules/events/client/components/EventsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const EventsList = ({
<H2 className="mt-10 mb-4 capitalize">{title}</H2>
<div className="flex flex-col gap-2">
{events?.map((x: any, i) => {
if (title === Titles.upcoming && !!x.applications?.length) {
if (title === Sections.upcoming && !!x.applications?.length) {
return
}
return (
Expand Down
8 changes: 6 additions & 2 deletions src/modules/hub-map/client/components/DailyEventsList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { useOfficeVisitsUpcoming } from '#modules/office-visits/client/queries'
import { FRIENDLY_DATE_FORMAT } from '#client/constants'
import { DailyEvent } from './DailyEvent'
import { useUpcoming } from '../queries'

export const DailyEventsList: React.FC<{
onChooseCard: (id: string | null, areaId: string | null, date: Dayjs) => void
Expand Down Expand Up @@ -46,8 +47,11 @@ export const DailyEventsList: React.FC<{
status: VisitStatus | RoomReservationStatus | GuestInviteStatus
}

const { data: myUpcomingVisits, refetch: refetchVisits } =
useOfficeVisitsUpcoming(officeId, dayjs().toString(), me?.id)
const { data: myUpcomingVisits, refetch: refetchVisits } = useUpcoming(
officeId,
dayjs().toString(),
me?.id
)

React.useEffect(() => {
if (!!myUpcomingVisits?.upcoming) {
Expand Down
9 changes: 7 additions & 2 deletions src/modules/hub-map/client/components/HubMap.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import { propEq } from '#shared/utils'
import { useOfficeVisitsUpcoming } from '#modules/office-visits/client/queries'
import { getPoints, goToMeetings, goToVisits } from '../helpers'
import { VisitType } from '#shared/types'
import { useMyEvents, useUpcomingEvents } from '#modules/events/client/queries'
import { useUpcoming } from '../queries'

export const HubMap = () => {
const officeId = useStore(stores.officeId)
Expand All @@ -32,8 +34,11 @@ export const HubMap = () => {
const [selectedDailyEvent, setSelectedDailyEvent] = React.useState<
string | null
>(null)
const { data: upcomingVisitsAll, refetch: refetchVisits } =
useOfficeVisitsUpcoming(officeId, dayjs().toString())

const { data: upcomingVisitsAll, refetch: refetchVisits } = useUpcoming(
officeId,
dayjs().toString()
)

React.useEffect(() => {
setOfficeVisits(upcomingVisitsAll?.byDate[date.format(DATE_FORMAT)])
Expand Down
16 changes: 16 additions & 0 deletions src/modules/hub-map/client/queries.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useQuery, useMutation } from 'react-query'
import { AxiosError, AxiosResponse } from 'axios'
import { api } from '#client/utils/api'
import dayjs from 'dayjs'
import { DATE_FORMAT } from '#server/constants'
// import { Entity } from '#shared/types'

// export const useCreateEntity = (cb: () => void) =>
Expand All @@ -17,3 +19,17 @@ import { api } from '#client/utils/api'
// async () => (await api.get<Entity[]>(path)).data
// )
// }

export const useUpcoming = (
officeId: string,
date: string,
userId?: string
) => {
const path = '/user-api/hub-map/upcoming'
return useQuery<any, AxiosError>(
[path, { officeId, date: dayjs(date).format(DATE_FORMAT), userId }],
async ({ queryKey }) =>
(await api.get<any>(path, { params: queryKey[1] })).data,
{ enabled: !!officeId }
)
}
8 changes: 7 additions & 1 deletion src/modules/hub-map/manifest.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
{
"id": "hub-map",
"name": "HubMap",
"dependencies": ["users"],
"dependencies": [
"visits",
"guest-invites",
"room-reservation",
"users",
"events"
],
"requiredIntegrations": [],
"recommendedIntegrations": [],
"models": [],
Expand Down
123 changes: 123 additions & 0 deletions src/modules/hub-map/server/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
import { appConfig } from '#server/app-config'
import { DATE_FORMAT } from '#server/constants'
import { Event, RoomReservation, User, Visit, VisitType } from '#shared/types'
import dayjs from 'dayjs'
import { FastifyInstance } from 'fastify'
import { Op } from 'sequelize'

export const getTime = (date: string | Date) => dayjs(date).format('LT')

export const formatRoomReservationsResult = (
reservation: RoomReservation,
officeId: string,
areaId: string
): any => {
// @todo put this somewhere central
const office = appConfig.offices.find((o) => o.id === officeId)
const area = office?.areas?.find((a) => a.id === areaId)
const officeRoom = area?.meetingRooms?.find(
(m) => m.id === reservation.roomId
)
return {
id: reservation.id,
dateTime: `${getTime(reservation.startDate)} - ${getTime(
reservation.endDate
)}`,
objectId: reservation.roomId,
areaId,
date: dayjs(reservation.startDate).format('YYYY-MM-DD'),
value: 'Room ' + officeRoom?.name ?? '',
description: officeRoom?.description ?? '',
type: VisitType.RoomReservation,
status: reservation.status,
}
}

export const formatVisit = (v: Visit, user?: User | null): any => {
return {
id: v.id,
value: `Desk ${v.deskName}`,
type: VisitType.Visit,
deskId: v.deskId,
objectId: v.deskId,
description: v.areaName,
areaId: v.areaId,
date: v.date,
status: v.status,
userId: v.userId,
user: user
? {
id: user?.id,
avatar: user?.avatar,
}
: null,
}
}

export const formatEvent = (event: Event) => {
const url = `/event/${event.id}`
const now = dayjs()
const start = dayjs(event.startDate)
const end = dayjs(event.endDate)
const isToday = now >= start && now <= end
const isSingleDay = start.isSame(end, 'day')

return {
id: event.id,
value: event.title,
url: url,
// @todo add different types
type: 'event',
date: start.format(DATE_FORMAT),
description: isToday
? 'Today'
: isSingleDay
? event.startDate
: `${start.format(DATE_FORMAT)} - ${end.format(DATE_FORMAT)}`,
}
}

export const getVisits = async (
fastify: FastifyInstance,
officeId: string,
date: string,
userId: string
) => {
const q = {
officeId,
status: {
[Op.in]: ['confirmed', 'pending'],
},
date: {
[Op.gte]: dayjs(date).toDate(),
},
}
if (userId) {
q['userId'] = userId
}
return fastify.db.Visit.findAll({
where: q,
order: ['date'],
})
}

export const getRoomReservations = async (
fastify: FastifyInstance,
officeId: string,
creatorUserId: string,
date: string
) => {
return fastify.db.RoomReservation.findAll({
where: {
office: officeId,
creatorUserId,
status: {
[Op.in]: ['confirmed', 'pending'],
},
startDate: {
[Op.gte]: dayjs(date).toDate(),
},
},
order: ['startDate'],
})
}
155 changes: 154 additions & 1 deletion src/modules/hub-map/server/router.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,161 @@
import { User } from '#modules/users/server/models'
import { appConfig } from '#server/app-config'
import {
DailyEventType,
EntityVisibility,
EventApplicationStatus,
GenericVisit,
VisitType,
} from '#shared/types'
import dayjs from 'dayjs'
import { FastifyPluginCallback, FastifyRequest } from 'fastify'
import {
formatEvent,
formatRoomReservationsResult,
formatVisit,
getRoomReservations,
getVisits,
} from './helpers'
import { getDate } from '#modules/office-visits/server/helpers'
import { Op } from 'sequelize'
import { Event } from '#modules/events/server/models'

const publicRouter: FastifyPluginCallback = async function (fastify, opts) {}

const userRouter: FastifyPluginCallback = async function (fastify, opts) {}
const addToUpcomingByDate = (
upcomingByDate: Record<string, any>,
value: GenericVisit,
date: string,
type: string
) => {
const dateKey = getDate(date)
upcomingByDate[dateKey] = upcomingByDate[dateKey] || {}
upcomingByDate[dateKey][type] = upcomingByDate[dateKey][type] || []
upcomingByDate[dateKey][type].push(value)
}

const userRouter: FastifyPluginCallback = async function (fastify, opts) {
fastify.get(
'/upcoming',
async (
req: FastifyRequest<{
Querystring: {
date: string
limit: number
officeId: string
userId: string
}
}>,
reply
) => {
const { date, officeId } = req.query
if (!officeId) {
return reply.throw.badParams('Missing office ID')
}
const office = appConfig.getOfficeById(officeId)

let visits = await getVisits(fastify, officeId, date, req.query.userId)
let roomReservations = await getRoomReservations(
fastify,
officeId,
req.user.id,
date
)

const upcomingItems: Array<DailyEventType> = []
const upcomingByDate: Record<string, any> = {}

const dailyEventsReservations = roomReservations.map(
(reservation, idx) => {
const area = office?.areas?.find((area) =>
area.meetingRooms?.find((room) => room.id === reservation.roomId)
)
const item = formatRoomReservationsResult(
reservation,
officeId,
area?.id
)
// add the first item in array to show at the top of the map in a list
if (!idx) {
upcomingItems.push(item)
}
addToUpcomingByDate(
upcomingByDate,
item,
dayjs(reservation.startDate).toString(),
VisitType.RoomReservation
)
return item
}
)

let dailyEventsVisits = []
for (const [idx, v] of visits.entries()) {
const item = formatVisit(v)
if (!idx) {
upcomingItems.push(item)
}
const user = await User.findByPk(v.userId)
addToUpcomingByDate(
upcomingByDate,
formatVisit(v, user),
v.date,
VisitType.Visit
)
dailyEventsVisits.push(item)
}

const eventApplications = await fastify.db.EventApplication.findAll({
include: {
model: Event,
as: 'event',
where: {
endDate: {
[Op.gte]: new Date(),
},
visibility: {
[Op.in]: [EntityVisibility.Visible, EntityVisibility.Url],
},
},
attributes: ['id', 'title', 'startDate', 'endDate'],
required: true,
order: [['startDate', 'ASC']],
},
where: {
status: {
[Op.in]: [
EventApplicationStatus.Opened,
EventApplicationStatus.Pending,
EventApplicationStatus.Confirmed,
],
},
userId: req.user.id,
},
attributes: ['eventId'],
})

const myEvents = eventApplications.map((application) =>
formatEvent(application?.event)
)

if (!!myEvents.length) {
upcomingItems.push(myEvents[0])
}

return {
upcoming: upcomingItems.sort((a: DailyEventType, b: DailyEventType) =>
dayjs(a.date).isAfter(dayjs(b.date)) ? 1 : -1
),
byType: {
[VisitType.Visit]: dailyEventsVisits,
[VisitType.RoomReservation]: dailyEventsReservations,
event: myEvents,
},
byDate: upcomingByDate,
}
}
)
}

const adminRouter: FastifyPluginCallback = async function (fastify, opts) {}

Expand Down
Loading

0 comments on commit 4e01ef6

Please sign in to comment.