Problem
ManageHub only supports booking workspace slots (desks, offices, meeting rooms). There is no way to book individual equipment or resources such as projectors, podcast booths, standing desks, or camera rigs. Hubs that offer these items have no way to manage or monetise them through the platform.
Proposed Solution
Create a new NestJS module at backend/src/resources/ with two entities.
Entity: Resource
id (UUID), name (string), description (text)
type (enum: projector | monitor | whiteboard | podcast_booth | camera | standing_desk | locker | other)
totalQuantity (integer), pricePerHour (integer, kobo — 0 for free resources)
isAvailable (boolean, default true)
images (JSONB array of URLs, nullable)
locationId (UUID FK → locations, nullable)
createdAt, updatedAt
Entity: ResourceBooking
id (UUID), resourceId (FK → resources), userId (FK → users)
startTime (timestamp), endTime (timestamp)
quantityRequested (integer, default 1)
status (enum: pending | confirmed | cancelled | completed)
paymentId (UUID FK → payments, nullable)
totalAmount (integer, kobo)
createdAt, updatedAt
Endpoints:
| Method |
Path |
Access |
POST |
/resources |
Admin |
GET |
/resources |
Public |
GET |
/resources/:id |
Public |
PATCH |
/resources/:id |
Admin |
DELETE |
/resources/:id |
Admin |
GET |
/resources/:id/availability |
Public — accepts date query param |
POST |
/resources/:id/book |
Authenticated member |
GET |
/resources/bookings/my |
Authenticated member |
Acceptance Criteria
Problem
ManageHub only supports booking workspace slots (desks, offices, meeting rooms). There is no way to book individual equipment or resources such as projectors, podcast booths, standing desks, or camera rigs. Hubs that offer these items have no way to manage or monetise them through the platform.
Proposed Solution
Create a new NestJS module at
backend/src/resources/with two entities.Entity:
Resourceid(UUID),name(string),description(text)type(enum:projector|monitor|whiteboard|podcast_booth|camera|standing_desk|locker|other)totalQuantity(integer),pricePerHour(integer, kobo —0for free resources)isAvailable(boolean, defaulttrue)images(JSONB array of URLs, nullable)locationId(UUID FK → locations, nullable)createdAt,updatedAtEntity:
ResourceBookingid(UUID),resourceId(FK → resources),userId(FK → users)startTime(timestamp),endTime(timestamp)quantityRequested(integer, default1)status(enum:pending|confirmed|cancelled|completed)paymentId(UUID FK → payments, nullable)totalAmount(integer, kobo)createdAt,updatedAtEndpoints:
POST/resourcesGET/resourcesGET/resources/:idPATCH/resources/:idDELETE/resources/:idGET/resources/:id/availabilitydatequery paramPOST/resources/:id/bookGET/resources/bookings/myAcceptance Criteria
totalQuantity - sum of confirmed bookingsfor the time slotPOST /resources/:id/bookinitiates payment viaPaymentsServicefor paid resourcesResourcesModuleis registered inAppModule