(WEB_PORTAL) Building an Integrated Calendar and Syncing with an External Messenger's Calendar
Overview
We built an integrated calendar that shows announcements, personal schedules, and approved leave all on a single screen, and connected it to the calendar feature of a domestic messenger service that employees already use personally, so they wouldn't have to register the same event twice.
Key Implementation Points
1. The Integrated Calendar Screen
We created a new table to hold event data and built a calendar screen that can be navigated month by month. Clicking a date opens that day's detailed schedule along with a registration modal, and events are shown with different colored badges depending on their type (leave/announcement/personal schedule) so they can be told apart at a glance. Admins are able to register company-wide announcement events.
2. External Calendar Integration
We implemented an integration flow with the external messenger service's account using the OAuth2 authorization code method. Issued tokens are stored in the server DB, and expired tokens are automatically refreshed.
User completes authorization → Token issued → Stored in DB
On each subsequent API call:
Make the request with the stored token
If the response is 401 (expired) → automatically reissue via refresh_token → retry the request
We also connected leave approvals so that, once a leave request is approved, an event is automatically created on the employee's external calendar too, eliminating the need to manually copy it over to their personal calendar. Handling all-day events required a bit of conversion logic to match the date format the external API expects (representing the end date as midnight of the following day).
3. Mobile Responsiveness
We configured the regular employee screen with a hamburger menu plus a sliding drawer, and the admin screen with an overlay-style drawer, providing mobile navigation suited to the nature of each screen.
Retrospective
- We were reminded that when integrating with an external service, its API's date/time conventions can subtly differ from our own (for example, whether the end point is treated as inclusive or exclusive). We only fully understood this after making several actual test calls, rather than just reading the documentation carefully.
- We found a real advantage in integrating with an external service that users are already comfortable with: instead of making people learn a new tool, we could layer the feature on top of their existing habits, which lowered resistance to adoption.