Skip to content

Commit 9dba6d3

Browse files
committed
wip
1 parent 7c328e6 commit 9dba6d3

41 files changed

Lines changed: 1334 additions & 602 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { atom } from "jotai";
2+
3+
export const selectedDisplayItemIdsAtom = atom<string[]>([]);
4+
5+
export const isDisplayItemSelected = (displayItemId: string) =>
6+
atom((get) => {
7+
const items = get(selectedDisplayItemIdsAtom);
8+
9+
return items.includes(displayItemId);
10+
});
11+
12+
export const isEventSelected = (eventId: string) =>
13+
atom((get) => {
14+
const items = get(selectedDisplayItemIdsAtom);
15+
16+
return items.includes(`event_${eventId}`);
17+
});
18+
19+
export const selectedEventIdsAtom = atom(
20+
(get) => {
21+
return get(selectedDisplayItemIdsAtom)
22+
.filter((id) => id.startsWith("event_"))
23+
.map((id) => id.slice(6));
24+
},
25+
(get, set, eventIds: string[]) => {
26+
const otherItems = get(selectedDisplayItemIdsAtom).filter(
27+
(id) => !id.startsWith("event_"),
28+
);
29+
30+
set(selectedDisplayItemIdsAtom, [
31+
...otherItems,
32+
...eventIds.map((id) => `event_${id}`),
33+
]);
34+
},
35+
);

apps/web/src/atoms/selected-events.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.

apps/web/src/atoms/window-stack.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { atom } from "jotai";
22

33
import { StackWindowEntry } from "@/components/command-bar/stacked-window";
4-
import { selectedEventIdsAtom } from "./selected-events";
4+
import { selectedEventIdsAtom } from "./selected-display-items";
55

66
function createWindowId() {
77
return `window-${crypto.randomUUID()}`;

apps/web/src/atoms/window-state.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { atom } from "jotai";
22

3-
import { selectedEventIdsAtom } from "@/atoms/selected-events";
3+
import { selectedEventIdsAtom } from "@/atoms/selected-display-items";
44

55
export const windowStateAtom = atom<"default" | "expanded">((get) => {
66
const events = get(selectedEventIdsAtom);

apps/web/src/components/calendar-view.tsx

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,12 @@ import { CalendarHeader } from "@/components/calendar/header/calendar-header";
2222
import { MonthView } from "@/components/calendar/month-view/month-view";
2323
import { WeekView } from "@/components/calendar/week-view/week-view";
2424
import { db, mapEventQueryInput } from "@/lib/db";
25+
import { DisplayItem, isEvent } from "@/lib/display-item";
2526
import { cn } from "@/lib/utils";
2627
import { applyOptimisticActions } from "./calendar/hooks/apply-optimistic-actions";
2728
import { optimisticActionsByEventIdAtom } from "./calendar/hooks/optimistic-actions";
2829
import { useEventsForDisplay } from "./calendar/hooks/use-events";
29-
import { filterPastEvents } from "./calendar/utils/event";
30+
import { filterPastItems } from "./calendar/utils/event";
3031

3132
interface CalendarContentProps {
3233
scrollContainerRef: React.RefObject<HTMLDivElement | null>;
@@ -54,22 +55,26 @@ function CalendarContent({ scrollContainerRef }: CalendarContentProps) {
5455
);
5556
}, [data?.events, data?.recurringMasterEvents]);
5657

57-
const events = React.useMemo(() => {
58-
const events = applyOptimisticActions({
58+
const displayItems = React.useMemo(() => {
59+
const eventItems = applyOptimisticActions({
5960
items: data?.events ?? [],
6061
timeZone: defaultTimeZone,
6162
optimisticActions,
6263
});
6364

64-
const pastFiltered = showPastEvents
65-
? events
66-
: filterPastEvents(events, defaultTimeZone);
65+
const pastFiltered: DisplayItem[] = showPastEvents
66+
? eventItems
67+
: filterPastItems(eventItems, defaultTimeZone);
68+
69+
return pastFiltered.filter((item) => {
70+
if (!isEvent(item)) {
71+
return true;
72+
}
6773

68-
return pastFiltered.filter((eventItem) => {
6974
const preference = getCalendarPreference(
7075
calendarPreferences,
71-
eventItem.event.calendar.provider.accountId,
72-
eventItem.event.calendar.id,
76+
item.event.calendar.provider.accountId,
77+
item.event.calendar.id,
7378
);
7479

7580
return !(preference?.hidden === true);
@@ -83,24 +88,26 @@ function CalendarContent({ scrollContainerRef }: CalendarContentProps) {
8388
]);
8489

8590
if (view === "month") {
86-
return <MonthView currentDate={currentDate} events={events} />;
91+
return <MonthView currentDate={currentDate} items={displayItems} />;
8792
}
8893

8994
if (view === "week") {
90-
return <WeekView events={events} scrollContainerRef={scrollContainerRef} />;
95+
return (
96+
<WeekView items={displayItems} scrollContainerRef={scrollContainerRef} />
97+
);
9198
}
9299

93100
if (view === "day") {
94101
return (
95102
<DayView
96103
currentDate={currentDate}
97-
events={events}
104+
items={displayItems}
98105
scrollContainerRef={scrollContainerRef}
99106
/>
100107
);
101108
}
102109

103-
return <AgendaView currentDate={currentDate} items={events} />;
110+
return <AgendaView currentDate={currentDate} items={displayItems} />;
104111
}
105112

106113
interface CalendarViewProps {

apps/web/src/components/calendar/agenda-view/agenda-view-day.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import { Temporal } from "temporal-polyfill";
88
import { isToday } from "@repo/temporal";
99

1010
import { calendarSettingsAtom } from "@/atoms/calendar-settings";
11-
import { eventOverlapsDay } from "@/components/calendar/utils/positioning";
12-
import { EventCollectionItem } from "../hooks/event-collection";
13-
import { AgendaViewEvent } from "./agenda-view-event";
11+
import { displayItemOverlapsDay } from "@/components/calendar/utils/positioning";
12+
import { DisplayItem, isInlineItem } from "@/lib/display-item";
13+
import { AgendaViewItem } from "./agenda-view-event";
1414

1515
interface AgendaViewDayHeaderProps {
1616
day: Temporal.PlainDate;
@@ -51,24 +51,26 @@ function AgendaViewDayContainer({ children }: AgendaViewDayContainerProps) {
5151

5252
interface AgendaViewDayProps {
5353
day: Temporal.PlainDate;
54-
items: EventCollectionItem[];
54+
items: DisplayItem[];
5555
}
5656

5757
export function AgendaViewDay({ day, items }: AgendaViewDayProps) {
58-
const events = React.useMemo(() => {
59-
return items.filter((item) => eventOverlapsDay(item, day));
58+
const dayItems = React.useMemo(() => {
59+
return items.filter(
60+
(item) => isInlineItem(item) && displayItemOverlapsDay(item, day),
61+
);
6062
}, [day, items]);
6163

62-
if (events.length === 0) {
64+
if (dayItems.length === 0) {
6365
return null;
6466
}
6567

6668
return (
6769
<AgendaViewDayContainer>
6870
<AgendaViewDayHeader day={day} />
6971
<AgendaViewDayContent>
70-
{events.map((event) => (
71-
<AgendaViewEvent key={event.event.id} item={event} />
72+
{dayItems.map((item) => (
73+
<AgendaViewItem key={item.id} item={item} />
7274
))}
7375
</AgendaViewDayContent>
7476
</AgendaViewDayContainer>

apps/web/src/components/calendar/agenda-view/agenda-view-event.tsx

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,47 @@
22

33
import * as React from "react";
44

5-
import { EventItem } from "@/components/calendar/event/event-item";
6-
import type { EventCollectionItem } from "@/components/calendar/hooks/event-collection";
5+
import { DisplayItemComponent } from "@/components/calendar/display-item/display-item";
76
import { useSelectAction } from "@/components/calendar/hooks/use-optimistic-mutations";
7+
import {
8+
DisplayItem,
9+
InlineDisplayItem,
10+
isEvent,
11+
isInlineItem,
12+
} from "@/lib/display-item";
813

9-
interface AgendaViewEventProps {
10-
item: EventCollectionItem;
14+
interface AgendaViewItemProps {
15+
item: DisplayItem;
1116
}
1217

13-
export function AgendaViewEvent({ item }: AgendaViewEventProps) {
18+
export function AgendaViewItem({ item }: AgendaViewItemProps) {
19+
if (!isInlineItem(item)) {
20+
return null;
21+
}
22+
23+
return <AgendaViewInlineItem item={item} />;
24+
}
25+
26+
interface AgendaViewInlineItemProps {
27+
item: InlineDisplayItem;
28+
}
29+
30+
function AgendaViewInlineItem({ item }: AgendaViewInlineItemProps) {
1431
const selectAction = useSelectAction();
1532

1633
const onClick = React.useCallback(
1734
(e: React.MouseEvent) => {
1835
e.stopPropagation();
19-
selectAction(item.event);
36+
if (isEvent(item)) {
37+
selectAction(item.event);
38+
}
2039
},
21-
[selectAction, item.event],
40+
[selectAction, item],
2241
);
2342

2443
return (
25-
<EventItem
26-
key={item.event.id}
44+
<DisplayItemComponent
45+
key={item.id}
2746
item={item}
2847
view="agenda"
2948
onClick={onClick}

apps/web/src/components/calendar/agenda-view/agenda-view.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { RiCalendarEventLine } from "@remixicon/react";
55
import { Temporal } from "temporal-polyfill";
66

77
import { AgendaDaysToShow } from "@/components/calendar/constants";
8-
import type { EventCollectionItem } from "@/components/calendar/hooks/event-collection";
8+
import type { DisplayItem } from "@/lib/display-item";
99
import { AgendaViewDay } from "./agenda-view-day";
1010

1111
function AgendaViewEmpty() {
@@ -15,17 +15,17 @@ function AgendaViewEmpty() {
1515
size={32}
1616
className="mb-2 text-muted-foreground/50"
1717
/>
18-
<h3 className="text-lg font-medium">No events found</h3>
18+
<h3 className="text-lg font-medium">No items found</h3>
1919
<p className="text-muted-foreground">
20-
There are no events scheduled for this time period.
20+
There are no items scheduled for this time period.
2121
</p>
2222
</div>
2323
);
2424
}
2525

2626
interface AgendaViewProps {
2727
currentDate: Temporal.PlainDate;
28-
items: EventCollectionItem[];
28+
items: DisplayItem[];
2929
}
3030

3131
export function AgendaView({ currentDate, items }: AgendaViewProps) {

0 commit comments

Comments
 (0)