Skip to content

Commit

Permalink
feature(web): Context menu edit event POC
Browse files Browse the repository at this point in the history
This commit demonstrates a POC for editing an event and inner functionality of how the context menu will interact with an event in its draft state.
  • Loading branch information
that-one-arab committed Feb 7, 2025
1 parent 3682675 commit 5acb05d
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 7 deletions.
4 changes: 3 additions & 1 deletion packages/web/src/ducks/events/slices/draft.slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface State_DraftEvent {
const initialDraft = {
status: {
activity: null,
source: null,
isDrafting: false,
eventType: null,
dateToResize: null,
Expand All @@ -29,12 +30,13 @@ export const draftSlice = createSlice({
reducers: {
discard: () => initialDraft,
start: (state, action: Action_DraftEvent) => {
const { activity, event, eventType } = action.payload;
const { activity, event, eventType, source = "grid" } = action.payload;

state.event = event;
state.status = {
...state.status,
activity,
source,
isDrafting: true,
eventType,
};
Expand Down
1 change: 1 addition & 0 deletions packages/web/src/ducks/events/slices/draft.slice.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ interface Payload_DraftEvent {
event?: Schema_Event;
eventType: Categories_Event;
activity?: "createShortcut" | "dragging" | "resizing";
source?: "grid" | "contextMenu";
}

interface Payload_Draft_Resize {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,13 @@ const _GridEvent = (
left: position.left,
lineClamp,
onMouseDown: (e: MouseEvent) => {
if (isOptimistic) return;
const isRightBtnClick = e.button === 2;

if (
isOptimistic || // Event is in the process of being created, don't allow any interactions until it's completely saved
isRightBtnClick
)
return;

onEventMouseDown(event, e);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ export const MainGridEvents = ({ measurements, weekProps }: Props) => {

const editTimedEvent = (event: Schema_GridEvent) => {
dispatch(
// TODO: `actions.startDragging` is confusing, it appears to mix concerns for both dragging
// and editing. Need to refactor to separate these concerns.
draftSlice.actions.startDragging({
event,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import React, { useState, useEffect, useRef } from "react";
import styled from "styled-components";
import { Priorities } from "@core/constants/core.constants";
import { ContextMenuPosition } from "./GridContextMenuWrapper";
import { Schema_GridEvent } from "@web/common/types/web.event.types";
import { useAppDispatch } from "@web/store/store.hooks";
import { draftSlice } from "@web/ducks/events/slices/draft.slice";

interface ContextMenuProps {
event: Schema_GridEvent;
position: ContextMenuPosition | null;
onClose: () => void;
}
Expand Down Expand Up @@ -61,7 +65,9 @@ const MenuItem = styled.li`
}
`;

const ContextMenu = ({ position, onClose }: ContextMenuProps) => {
const ContextMenu = ({ event, position, onClose }: ContextMenuProps) => {
const dispatch = useAppDispatch();

const menuRef = useRef<HTMLUListElement>(null);
const [selectedPriority, setSelectedPriority] = useState(
Priorities.UNASSIGNED
Expand All @@ -79,7 +85,21 @@ const ContextMenu = ({ position, onClose }: ContextMenuProps) => {
];

const actions = [
{ id: "edit", label: "✏️ Edit", onClick: () => alert("Edit clicked") },
{
id: "edit",
label: "✏️ Edit",
onClick: () => {
dispatch(
draftSlice.actions.start({
source: "contextMenu",
event: {
...event,
isOpen: true,
},
})
);
},
},
{
id: "delete",
label: "🗑️ Delete",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import React, { ReactNode, useState, useRef } from "react";
import { getCalendarEventIdFromElement } from "@web/common/utils/event.util";
import ContextMenu from "./ContextMenu";
import { useAppSelector } from "@web/store/store.hooks";
import { selectGridEvents } from "@web/ducks/events/selectors/event.selectors";
import { Schema_GridEvent } from "@web/common/types/web.event.types";

export interface ContextMenuPosition {
x: number;
y: number;
}

const GridContextMenuWrapper = ({ children }: { children: ReactNode }) => {
interface GridContextMenuWrapper {
children: ReactNode;
}

const GridContextMenuWrapper = ({ children }: GridContextMenuWrapper) => {
const timedEvents = useAppSelector(selectGridEvents);
const [contextMenuPos, setContextMenuPos] =
useState<ContextMenuPosition | null>(null);
const [event, setEvent] = useState<Schema_GridEvent | null>(null);

const wrapperRef = useRef(null);

Expand All @@ -24,27 +33,33 @@ const GridContextMenuWrapper = ({ children }: { children: ReactNode }) => {

if (hasClickedOnCalendarEvent) {
e.preventDefault();

const event = timedEvents.find((e) => e._id === calendarEventId);
if (!event) return; // TS guard

setContextMenuPos({
x: e.pageX,
y: e.pageY,
});
setEvent(event);
}
};

const closeMenu = () => {
setContextMenuPos(null);
setEvent(null);
};

return (
<div
ref={wrapperRef}
style={{ display: "contents" }}
onContextMenu={handleContextMenu}
>
{children}
{contextMenuPos && (
{contextMenuPos && event && (
<ContextMenu
position={{ x: contextMenuPos.x, y: contextMenuPos.y }}
event={event}
onClose={closeMenu}
/>
)}
Expand Down

0 comments on commit 5acb05d

Please sign in to comment.