Skip to content

Commit c69d5c8

Browse files
jeremymanningclaude
andcommitted
Update event titles and dynamic calendar time range
Change calendar event title format to "FirstName/Jeremy: MeetingType". Store meetingTypeName in booking records for reschedule support. Dynamically adjust calendar visible time range to match available slot boundaries (default 9am-5pm when no slots visible). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 25de6d3 commit c69d5c8

3 files changed

Lines changed: 64 additions & 7 deletions

File tree

backend/Booking.gs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
var BookingStore = (function () {
77
var HEADERS = [
88
'token', 'tokenExpiresAt', 'eventId', 'status', 'meetingTypeId',
9-
'startTime', 'endTime', 'firstName', 'lastName', 'email',
10-
'format', 'location', 'purpose', 'notes', 'createdAt',
9+
'meetingTypeName', 'startTime', 'endTime', 'firstName', 'lastName',
10+
'email', 'format', 'location', 'purpose', 'notes', 'createdAt',
1111
'cancelledAt', 'rescheduledTo',
1212
];
1313

backend/Code.gs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,9 @@ function handleCreateBooking(data) {
157157
data.token = token;
158158

159159
// Create calendar event
160-
var eventTitle = data.meetingTypeName + ' — ' + data.firstName + ' ' + data.lastName;
160+
var ownerName = Config.get('OWNER_NAME') || 'Jeremy';
161+
var ownerFirst = ownerName.split(' ')[0];
162+
var eventTitle = data.firstName + '/' + ownerFirst + ': ' + data.meetingTypeName;
161163
var description = buildEventDescription(data);
162164
var calendar = CalendarApp.getCalendarById(Config.get('CALENDAR_ID'));
163165
var event = calendar.createEvent(eventTitle, startDate, endDate, {
@@ -172,6 +174,7 @@ function handleCreateBooking(data) {
172174
eventId: event.getId(),
173175
status: 'confirmed',
174176
meetingTypeId: data.meetingTypeId,
177+
meetingTypeName: data.meetingTypeName,
175178
startTime: data.start,
176179
endTime: data.end,
177180
firstName: data.firstName,
@@ -297,7 +300,7 @@ function handleRescheduleBooking(data) {
297300
// Create new booking with reschedule
298301
var newBookingData = {
299302
meetingTypeId: oldBooking.meetingTypeId,
300-
meetingTypeName: oldBooking.meetingTypeId, // Will be resolved from config
303+
meetingTypeName: oldBooking.meetingTypeName || oldBooking.meetingTypeId,
301304
start: data.newStart,
302305
end: data.newEnd,
303306
firstName: oldBooking.firstName,
@@ -352,7 +355,9 @@ function handleRescheduleBooking(data) {
352355
purpose: oldBooking.purpose,
353356
notes: oldBooking.notes,
354357
};
355-
var eventTitle = oldBooking.meetingTypeId + ' — ' + oldBooking.firstName + ' ' + oldBooking.lastName;
358+
var ownerName = Config.get('OWNER_NAME') || 'Jeremy';
359+
var ownerFirst = ownerName.split(' ')[0];
360+
var eventTitle = oldBooking.firstName + '/' + ownerFirst + ': ' + oldBooking.meetingTypeName;
356361
var description = buildEventDescription(descData);
357362
var calendar = CalendarApp.getCalendarById(Config.get('CALENDAR_ID'));
358363
var newEvent = calendar.createEvent(eventTitle, newStart, newEnd, {
@@ -368,6 +373,7 @@ function handleRescheduleBooking(data) {
368373
eventId: newEvent.getId(),
369374
status: 'confirmed',
370375
meetingTypeId: oldBooking.meetingTypeId,
376+
meetingTypeName: oldBooking.meetingTypeName || oldBooking.meetingTypeId,
371377
startTime: data.newStart,
372378
endTime: data.newEnd,
373379
firstName: oldBooking.firstName,

js/calendar.js

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
/**
22
* CalendarUI — FullCalendar wrapper for displaying available time slots.
33
* Fetches slots from the backend and renders them as clickable events.
4+
* Dynamically adjusts visible time range based on available slots.
45
*/
56

67
var CalendarUI = (function () {
78
var _calendar = null;
89
var _durationMinutes = 15;
910
var _onSlotSelected = null;
11+
var DEFAULT_MIN_TIME = '09:00:00';
12+
var DEFAULT_MAX_TIME = '17:00:00';
1013

1114
function init(durationMinutes, onSlotSelected) {
1215
_durationMinutes = durationMinutes;
@@ -23,8 +26,8 @@ var CalendarUI = (function () {
2326
right: 'timeGridWeek,timeGridDay',
2427
},
2528
allDaySlot: false,
26-
slotMinTime: '09:00:00',
27-
slotMaxTime: '17:00:00',
29+
slotMinTime: DEFAULT_MIN_TIME,
30+
slotMaxTime: DEFAULT_MAX_TIME,
2831
slotDuration: minutesToSlotDuration(durationMinutes),
2932
timeZone: 'local',
3033
height: 'auto',
@@ -89,8 +92,14 @@ var CalendarUI = (function () {
8992

9093
if (events.length === 0) {
9194
showNoSlotsMessage();
95+
// Reset to default 9-5 range when no slots
96+
if (_calendar) {
97+
_calendar.setOption('slotMinTime', DEFAULT_MIN_TIME);
98+
_calendar.setOption('slotMaxTime', DEFAULT_MAX_TIME);
99+
}
92100
} else {
93101
hideNoSlotsMessage();
102+
adjustTimeRange(events);
94103
}
95104

96105
successCallback(events);
@@ -101,6 +110,48 @@ var CalendarUI = (function () {
101110
});
102111
}
103112

113+
/**
114+
* Adjust the visible time range to span from the earliest slot start
115+
* to the latest slot end in the current view, with no extra padding.
116+
*/
117+
function adjustTimeRange(events) {
118+
if (!_calendar || events.length === 0) return;
119+
120+
var minHour = 23;
121+
var minMinute = 59;
122+
var maxHour = 0;
123+
var maxMinute = 0;
124+
125+
events.forEach(function (evt) {
126+
var start = new Date(evt.start);
127+
var end = new Date(evt.end);
128+
129+
var startH = start.getHours();
130+
var startM = start.getMinutes();
131+
var endH = end.getHours();
132+
var endM = end.getMinutes();
133+
134+
if (startH < minHour || (startH === minHour && startM < minMinute)) {
135+
minHour = startH;
136+
minMinute = startM;
137+
}
138+
if (endH > maxHour || (endH === maxHour && endM > maxMinute)) {
139+
maxHour = endH;
140+
maxMinute = endM;
141+
}
142+
});
143+
144+
var minTime = padTime(minHour) + ':' + padTime(minMinute) + ':00';
145+
var maxTime = padTime(maxHour) + ':' + padTime(maxMinute) + ':00';
146+
147+
_calendar.setOption('slotMinTime', minTime);
148+
_calendar.setOption('slotMaxTime', maxTime);
149+
}
150+
151+
function padTime(n) {
152+
return n < 10 ? '0' + n : String(n);
153+
}
154+
104155
function showNoSlotsMessage() {
105156
var container = document.getElementById('calendar-container');
106157
var existing = container.querySelector('.no-slots-message');

0 commit comments

Comments
 (0)