Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
d90e49e
simplify expand event range logic
mirmirmirr Jan 8, 2026
984c6f6
return day slots at once
mirmirmirr Jan 8, 2026
04bbfe6
Revert "return day slots at once"
mirmirmirr Jan 8, 2026
dc4cadf
add timeslots to reducer state
mirmirmirr Jan 8, 2026
e9565ce
upaate get event
mirmirmirr Jan 8, 2026
529e006
update dashboard handling
mirmirmirr Jan 8, 2026
fd2c8bd
update timezone handling
mirmirmirr Jan 8, 2026
0855a9e
create timeslot utils
mirmirmirr Jan 8, 2026
d978c5e
change time from int to string
mirmirmirr Jan 8, 2026
8fe32e7
formatApiTime
mirmirmirr Jan 8, 2026
f17f5b1
add the creator
mirmirmirr Jan 8, 2026
fb8cdf1
implement ios picker
mirmirmirr Jan 8, 2026
1de4a89
add disabled state for dropdown
mirmirmirr Jan 8, 2026
62f3c5e
Update page-client.tsx
mirmirmirr Jan 8, 2026
fa6a5f7
Merge branch 'editor-refactor' into api-updates
mirmirmirr Jan 8, 2026
0abb433
Merge branch 'v0.1.3' into api-updates
mirmirmirr Jan 8, 2026
0c3f964
three day range
mirmirmirr Jan 8, 2026
62d8618
add ring to selectors
mirmirmirr Jan 8, 2026
6a30543
Merge branch 'v0.1.3' into api-updates
mirmirmirr Jan 9, 2026
86e5dd4
Update src/core/event/lib/expand-event-range.ts
mirmirmirr Jan 9, 2026
c704935
Update src/features/event/editor/date-range/specific-date-display.tsx
mirmirmirr Jan 9, 2026
16f0db0
centralize time and date range validation
mirmirmirr Jan 9, 2026
0d32505
Merge branch 'api-updates' of https://github.com/plan-cake/frontend i…
mirmirmirr Jan 9, 2026
3d67479
universal datetime handling
mirmirmirr Jan 10, 2026
4741e58
add comments to date-time-format.ts
mirmirmirr Jan 10, 2026
ed45c95
Update src/lib/utils/date-time-format.ts
mirmirmirr Jan 11, 2026
23b77e5
display local details for dashboard information
mirmirmirr Jan 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions src/app/(event)/[event-code]/edit/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,17 @@ export default async function Page({ params }: EventCodePageProps) {
}

const eventData = await fetchEventDetails(eventCode);
const { eventName, eventRange } = processEventData(eventData);
const { eventName, eventRange, timeslots } = processEventData(eventData);

return (
<EventEditor
type="edit"
initialData={{ title: eventName, customCode: eventCode, eventRange }}
initialData={{
title: eventName,
customCode: eventCode,
eventRange,
timeslots,
}}
/>
);
}
6 changes: 5 additions & 1 deletion src/app/(event)/[event-code]/page-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,20 @@ export default function ClientPage({
eventCode,
eventName,
eventRange,
timeslots,
initialAvailabilityData,
isCreator,
}: {
eventCode: string;
eventName: string;
eventRange: EventRange;
timeslots: Date[];
initialAvailabilityData: AvailabilityDataResponse;
isCreator: boolean;
}) {
/* PARTICIPANT INFO */
const participated: boolean =
initialAvailabilityData.user_display_name != null;
const isCreator: boolean = initialAvailabilityData.is_creator || false;
const participants: string[] = initialAvailabilityData.participants || [];
const availabilities: ResultsAvailabilityMap =
initialAvailabilityData.availability || {};
Expand Down Expand Up @@ -95,6 +98,7 @@ export default function ClientPage({
setHoveredSlot={handleHoveredSlot}
availabilities={availabilities}
numParticipants={participants.length}
timeslots={timeslots}
/>

<div className="h-25" />
Expand Down
15 changes: 10 additions & 5 deletions src/app/(event)/[event-code]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { fetchAvailabilityData } from "@/features/event/availability/fetch-data"
import { EventCodePageProps } from "@/features/event/code-page-props";
import { fetchEventDetails } from "@/features/event/editor/fetch-data";
import { getAuthCookieString } from "@/lib/utils/api/cookie-utils";
import { processAvailabilityData } from "@/lib/utils/api/process-availability-data";
import { processEventData } from "@/lib/utils/api/process-event-data";

export default async function Page({ params }: EventCodePageProps) {
Expand All @@ -15,20 +16,24 @@ export default async function Page({ params }: EventCodePageProps) {
notFound();
}

const [initialEventData, availabilityData] = await Promise.all([
const [initialEventData, initialAvailabilityData] = await Promise.all([
fetchEventDetails(eventCode, authCookies),
fetchAvailabilityData(eventCode, authCookies),
]);

// Process the data here, on the server!
const { eventName, eventRange } = processEventData(initialEventData);
const { eventName, eventRange, timeslots, isCreator } =
processEventData(initialEventData);

const availabilityData = processAvailabilityData(initialAvailabilityData);

return (
<ClientPage
eventCode={eventCode}
eventName={eventName} // Pass the processed name
eventRange={eventRange} // Pass the processed range
eventName={eventName}
eventRange={eventRange}
timeslots={timeslots}
initialAvailabilityData={availabilityData}
isCreator={isCreator}
/>
);
}
19 changes: 10 additions & 9 deletions src/app/(event)/[event-code]/painting/page-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import RateLimitBanner from "@/components/banner/rate-limit";
import HeaderSpacer from "@/components/header-spacer";
import MobileFooterTray from "@/components/mobile-footer-tray";
import { useAvailability } from "@/core/availability/use-availability";
import { convertAvailabilityToGrid } from "@/core/availability/utils";
import { EventRange } from "@/core/event/types";
import ActionButton from "@/features/button/components/action";
import LinkButton from "@/features/button/components/link";
Expand All @@ -26,11 +25,13 @@ export default function ClientPage({
eventCode,
eventName,
eventRange,
timeslots,
initialData,
}: {
eventCode: string;
eventName: string;
eventRange: EventRange;
timeslots: Date[];
initialData: SelfAvailabilityResponse | null;
}) {
const router = useRouter();
Expand Down Expand Up @@ -93,15 +94,10 @@ export default function ClientPage({
return false;
}

const availabilityGrid = convertAvailabilityToGrid(
userAvailability,
eventRange,
);

const payload = {
event_code: eventCode,
display_name: displayName,
availability: availabilityGrid,
availability: Array.from(userAvailability),
time_zone: timeZone,
};

Expand Down Expand Up @@ -139,14 +135,18 @@ export default function ClientPage({
const cancelButton = (
<LinkButton
buttonStyle="transparent"
label={initialData ? "Cancel Edits" : "Cancel"}
label={initialData?.display_name ? "Cancel Edits" : "Cancel"}
href={`/${eventCode}`}
/>
);
const submitButton = (
<ActionButton
buttonStyle="primary"
label={initialData ? "Update Availability" : "Submit Availability"}
label={
initialData?.display_name
? "Update Availability"
: "Submit Availability"
}
onClick={handleSubmitAvailability}
loadOnSuccess
/>
Expand Down Expand Up @@ -227,6 +227,7 @@ export default function ClientPage({
timezone={timeZone}
onToggleSlot={toggleSlot}
userAvailability={userAvailability}
timeslots={timeslots}
/>
</div>

Expand Down
3 changes: 2 additions & 1 deletion src/app/(event)/[event-code]/painting/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ export default async function Page({ params }: EventCodePageProps) {
fetchEventDetails(eventCode),
fetchSelfAvailability(eventCode, authCookies),
]);
const { eventName, eventRange } = processEventData(eventData);
const { eventName, eventRange, timeslots } = processEventData(eventData);

return (
<ClientPage
eventCode={eventCode}
eventName={eventName}
eventRange={eventRange}
timeslots={timeslots}
initialData={initialAvailabilityData}
/>
);
Expand Down
3 changes: 2 additions & 1 deletion src/core/availability/use-availability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@ import {
} from "@/core/availability/reducers/reducer";
import { createUserAvailability } from "@/core/availability/utils";
import { SelfAvailabilityResponse } from "@/features/event/availability/fetch-data";
import { formatDateTime } from "@/lib/utils/date-time-format";

export function useAvailability(initialData: SelfAvailabilityResponse | null) {
const initialTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const isoStrings = [];
if (initialData && initialData.available_dates) {
for (const dateStr of initialData.available_dates) {
isoStrings.push(new Date(dateStr).toISOString());
isoStrings.push(formatDateTime(dateStr));
}
}

Expand Down
76 changes: 0 additions & 76 deletions src/core/availability/utils.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,4 @@
import { eachDayOfInterval, parseISO } from "date-fns";

import { AvailabilitySet } from "@/core/availability/types";
import {
EventRange,
SpecificDateRange,
WeekdayRange,
} from "@/core/event/types";
import {
getAbsoluteDateRangeInUTC,
getSelectedWeekdaysInTimezone,
} from "@/features/event/grid/lib/expand-event-range";

// Creates an empty UserAvailability object
export const createEmptyUserAvailability = (): AvailabilitySet => {
Expand Down Expand Up @@ -45,71 +34,6 @@ export function isSlotSelected(
return availability.has(timeSlot.toISOString());
}

// converts set to grid for api
export function convertAvailabilityToGrid(
availability: AvailabilitySet,
eventRange: EventRange,
): boolean[][] {
if (eventRange.type === "specific") {
return convertAvailabilityToGridForSpecificRange(availability, eventRange);
} else {
return convertAvailabilityToGridForWeekdayRange(availability, eventRange);
}
}

function convertAvailabilityToGridForSpecificRange(
availability: AvailabilitySet,
eventRange: SpecificDateRange,
): boolean[][] {
const { eventStartUTC, eventEndUTC } = getAbsoluteDateRangeInUTC(eventRange);
const startTime = eventStartUTC.getHours();
const endTime =
eventEndUTC.getMinutes() === 59
? eventEndUTC.getHours() + 1
: eventEndUTC.getHours();

const days = eachDayOfInterval({
start: parseISO(eventStartUTC.toISOString()),
end: parseISO(eventEndUTC.toISOString()),
});

const grid: boolean[][] = days.map((day) => {
const daySlots: boolean[] = [];

for (let hour = startTime; hour < endTime; hour++) {
for (let minute = 0; minute < 60; minute += 15) {
const slot = new Date(day);
slot.setHours(hour, minute);
daySlots.push(isSlotSelected(availability, slot));
}
}

return daySlots;
});
return grid;
}

function convertAvailabilityToGridForWeekdayRange(
availability: AvailabilitySet,
eventRange: WeekdayRange,
): boolean[][] {
const selectedDays = getSelectedWeekdaysInTimezone(eventRange);

const grid: boolean[][] = selectedDays.map((day) => {
const daySlots: boolean[] = [];
const { slotTimeUTC, dayEndUTC } = day;

while (slotTimeUTC < dayEndUTC) {
daySlots.push(isSlotSelected(availability, slotTimeUTC));
slotTimeUTC.setUTCMinutes(slotTimeUTC.getUTCMinutes() + 15);
}

return daySlots;
});

return grid;
}

function sortDateRange(start: Date, end: Date): [Date, Date] {
// given a start date and end date, it separately sorts the time and date components
// and returns two new dates, such that the first has both the earlier date and time
Expand Down
22 changes: 22 additions & 0 deletions src/core/event/lib/default-range.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { SpecificDateRange, WeekdayRange } from "@/core/event/types";

const defaultTimeRange = { from: "09:00", to: "17:00" };

export const DEFAULT_RANGE_SPECIFIC: SpecificDateRange = {
type: "specific" as const,
duration: 60,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
dateRange: {
from: new Date().toISOString(),
to: new Date(Date.now() + 2 * 24 * 60 * 60 * 1000).toISOString(),
},
timeRange: defaultTimeRange,
};

export const DEFAULT_RANGE_WEEKDAY: WeekdayRange = {
type: "weekday" as const,
duration: 30,
Comment on lines +7 to +18
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default durations should be set to "None" initially as it was before. It's an advanced option that users should only set if they explicitly want it.

timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
weekdays: { Sun: 0, Mon: 1, Tue: 1, Wed: 1, Thu: 0, Fri: 0, Sat: 0 },
timeRange: defaultTimeRange,
};
Loading
Loading