react-native-calendars icon indicating copy to clipboard operation
react-native-calendars copied to clipboard

TimelineList onEventPress, event is undefined

Open amorimcode opened this issue 1 year ago • 2 comments

This is how i managed the code:

onEventPress = (event: TimelineEventProps) => {
    console.log("TimelineCalendarScreen onEventPress: ", event);
  };`
        <TimelineList
          events={eventsByDate}
          timelineProps={this.timelineProps}
          showNowIndicator
          scrollToNow
          scrollToFirst
          initialTime={INITIAL_TIME}
        />
    format24h: true,
    onBackgroundLongPress: this.createNewEvent,
    onBackgroundLongPressOut: this.approveNewEvent,
    onEventPress: this.onEventPress,
    unavailableHours: [
      { start: 0, end: 16.5 },
      { start: 20, end: 24 },
    ],
    overlapEventsSpacing: 8,
    rightEdgeSpacing: 24,
  };

When i press the event in the calendar it logs undefined

Full code:

import { router } from "expo-router";
import filter from "lodash/filter";
import find from "lodash/find";
import groupBy from "lodash/groupBy";
import React, { Component } from "react";
import { Alert } from "react-native";
import {
  ExpandableCalendar,
  TimelineEventProps,
  TimelineList,
  CalendarProvider,
  TimelineProps,
  CalendarUtils,
} from "react-native-calendars";

import ScheduleRepository from "@/src/repositories/schedule";
import { showToast } from "@/src/services/message";
import useScheduleStore from "@/src/stores/schedule";
import useStore from "@/src/stores/store";
import Theme from "@/src/styles/theme";
import { convertFromISO, formatTimelineDate } from "@/src/utils/date";

export function getDate(offset = 0) {
  const today = new Date();
  const targetDate = new Date(today);
  targetDate.setDate(today.getDate() + offset);

  const year = targetDate.getFullYear();
  const month = String(targetDate.getMonth() + 1).padStart(2, "0");
  const day = String(targetDate.getDate()).padStart(2, "0");

  return `${year}-${month}-${day}`;
}

export const timelineEvents = [
  {
    id: "1",
    start: "2023-11-05T10:00:00",
    end: "2023-11-05T12:00:00",
    title: "Agendamento",
    color: Theme.colors.grayLighter,
  },
];

const INITIAL_TIME = { hour: 9, minutes: 0 };
const EVENTS: TimelineEventProps[] = timelineEvents;
export default class TimelineCalendarScreen extends Component {
  state = {
    currentDate: getDate(),
    events: EVENTS,
    eventsByDate: groupBy(EVENTS, (e) =>
      CalendarUtils.getCalendarDateString(e.start),
    ) as {
      [key: string]: TimelineEventProps[];
    },
  };

  // marked = {
  //   [`${getDate(-1)}`]: { marked: true },
  //   [`${getDate()}`]: { marked: true },
  //   [`${getDate(1)}`]: { marked: true },
  //   [`${getDate(2)}`]: { marked: true },
  //   [`${getDate(4)}`]: { marked: true },
  // };

  marked = {};

  async componentDidMount() {
    useStore.getState().actions.setIsLoading(true);
    await this.getServerEvents();
    useStore.getState().actions.setIsLoading(false);
  }

  onDateChanged = (date: string, source: string) => {
    console.log("TimelineCalendarScreen onDateChanged: ", date, source);
    this.setState({ currentDate: date });
  };

  onMonthChange = (month: any, updateSource: any) => {
    console.log("TimelineCalendarScreen onMonthChange: ", month, updateSource);
  };

  getServerEvents = async () => {
    const { eventsByDate } = this.state;
    try {
      const schedules: models.Schedule[] = await ScheduleRepository.getAll();

      const newEvents = schedules.map((schedule) => ({
        id: schedule.id,
        start: schedule.startAt,
        end: schedule.endAt,
        title: "Agendamento",
        color: Theme.colors.grayLighter,
      }));

      const newEventsByDate = groupBy(newEvents, (e) =>
        CalendarUtils.getCalendarDateString(e.start),
      );

      this.setState({
        events: [...newEvents, ...EVENTS],
        eventsByDate: { ...eventsByDate, ...newEventsByDate },
      });
    } catch (error) {
      console.log(error);
    }
  };

  onEventPress = (event: TimelineEventProps) => {
    console.log("TimelineCalendarScreen onEventPress: ", event);
  };

  createNewEvent: TimelineProps["onBackgroundLongPress"] = (
    timeString,
    timeObject,
  ) => {
    const { eventsByDate } = this.state;
    const hourString = `${(timeObject.hour + 3).toString().padStart(2, "0")}`;
    const minutesString = `${timeObject.minutes.toString().padStart(2, "0")}`;

    const conflictsWithOtherEvents = this.state.events.some(
      (event) =>
        event.start === formatTimelineDate(timeString) ||
        event.end === formatTimelineDate(timeString) ||
        (event.start < formatTimelineDate(timeString) &&
          event.end > formatTimelineDate(timeString)),
    );

    if (conflictsWithOtherEvents) {
      showToast("Horário indisponível");

      return;
    }

    const newEvent = {
      id: "draft",
      start: `${timeString}`,
      end: `${timeObject.date} ${hourString}:${minutesString}:00`,
      title: "Agendamento",
    };

    if (timeObject.date) {
      if (eventsByDate[timeObject.date]) {
        eventsByDate[timeObject.date] = [
          ...eventsByDate[timeObject.date],
          newEvent,
        ];
        this.setState({ eventsByDate });
      } else {
        eventsByDate[timeObject.date] = [newEvent];
        this.setState({ eventsByDate: { ...eventsByDate } });
      }
    }
  };

  approveNewEvent: TimelineProps["onBackgroundLongPressOut"] = (
    _timeString,
    timeObject,
  ) => {
    const { eventsByDate } = this.state;

    const conflictsWithOtherEvents = this.state.events.some(
      (event) =>
        event.start === formatTimelineDate(_timeString) ||
        event.end === formatTimelineDate(_timeString) ||
        (event.start < formatTimelineDate(_timeString) &&
          event.end > formatTimelineDate(_timeString)),
    );

    if (conflictsWithOtherEvents) {
      return;
    }

    Alert.alert(
      "Novo agendamento",
      `Tem certeza que que criar um agendamento no dia ${convertFromISO(
        timeObject.date,
      )} às ${timeObject.hour}:${timeObject.minutes
        .toString()
        .padStart(2, "0")}?
    `,
      [
        {
          text: "Cancelar",
          onPress: () => {
            if (timeObject.date) {
              eventsByDate[timeObject.date] = filter(
                eventsByDate[timeObject.date],
                (e) => e.id !== "draft",
              );

              this.setState({
                eventsByDate,
              });
            }
          },
        },
        {
          text: "Agendar",
          onPress: async () => {
            if (timeObject.date) {
              const draftEvent = find(eventsByDate[timeObject.date], {
                id: "draft",
              });

              await useScheduleStore.getState().actions.setSchedule({
                startAt: draftEvent?.start,
                endAt: draftEvent?.end,
              } as models.Schedule);

              // Navigate to the other screen (adjust the navigation logic accordingly)
              router.push("/pastoral-schedule/schedule-type/");

              setTimeout(() => {
                if (timeObject.date) {
                  eventsByDate[timeObject.date] = filter(
                    eventsByDate[timeObject.date],
                    (e) => e.id !== "draft",
                  );

                  this.setState({
                    eventsByDate,
                  });
                }
              }, 2000);
            }
          },
        },
      ],
    );
  };

  private timelineProps: Partial<TimelineProps> = {
    format24h: true,
    onBackgroundLongPress: this.createNewEvent,
    onBackgroundLongPressOut: this.approveNewEvent,
    onEventPress: this.onEventPress,
    unavailableHours: [
      { start: 0, end: 16.5 },
      { start: 20, end: 24 },
    ],
    overlapEventsSpacing: 8,
    rightEdgeSpacing: 24,
  };

  render() {
    const { currentDate, eventsByDate } = this.state;

    return (
      <CalendarProvider
        date={currentDate}
        onDateChanged={this.onDateChanged}
        onMonthChange={this.onMonthChange}
        showTodayButton
        disabledOpacity={0.6}
        theme={{
          selectedDayBackgroundColor: Theme.colors.primary,
          selectedDayTextColor: "#ffffff",
          todayTextColor: Theme.colors.primary,
          dotColor: Theme.colors.primary,
          selectedDotColor: "#ffffff",
          arrowColor: Theme.colors.primary,
          monthTextColor: Theme.colors.primary,
          textDayFontFamily: Theme.fonts.regular,
          textMonthFontFamily: Theme.fonts.regular,
          textDayHeaderFontFamily: Theme.fonts.regular,
        }}
      >
        <ExpandableCalendar
          minDate={getDate(-1)}
          disableAllTouchEventsForDisabledDays
          firstDay={1}
          markedDates={this.marked}
          theme={{
            selectedDayBackgroundColor: Theme.colors.grayLight,

            todayTextColor: Theme.colors.grayLight,
            dotColor: Theme.colors.grayLight,
            arrowColor: Theme.colors.primary,
            monthTextColor: Theme.colors.primary,
            textDayFontFamily: Theme.fonts.regular,
            textMonthFontFamily: Theme.fonts.regular,
            textDayHeaderFontFamily: Theme.fonts.regular,
          }}
        />
        <TimelineList
          events={eventsByDate}
          timelineProps={this.timelineProps}
          showNowIndicator
          scrollToNow
          scrollToFirst
          initialTime={INITIAL_TIME}
        />
      </CalendarProvider>
    );
  }
}

amorimcode avatar Dec 19 '23 14:12 amorimcode

Did you manage to fix this?

AnzeSavli avatar Mar 13 '24 21:03 AnzeSavli

Did you manage to fix this?

just add this patch

diff --git a/node_modules/react-native-calendars/src/timeline/Timeline.js b/node_modules/react-native-calendars/src/timeline/Timeline.js
index 12c7851..9bfb96f 100644
--- a/node_modules/react-native-calendars/src/timeline/Timeline.js
+++ b/node_modules/react-native-calendars/src/timeline/Timeline.js
@@ -14,6 +14,7 @@ import TimelineHours from './TimelineHours';
 import EventBlock from './EventBlock';
 import NowIndicator from './NowIndicator';
 import useTimelineOffset from './useTimelineOffset';
+import { set } from 'lodash';
 const Timeline = (props) => {
     const { format24h = true, start = 0, end = 24, date = '', events, onEventPress, onBackgroundLongPress, onBackgroundLongPressOut, renderEvent, theme, scrollToFirst, scrollToNow, initialTime, showNowIndicator, scrollOffset, onChangeOffset, overlapEventsSpacing = 0, rightEdgeSpacing = 0, unavailableHours, unavailableHoursColor, eventTapped, numberOfDays = 1, timelineLeftInset = 0 } = props;
     const pageDates = useMemo(() => {
@@ -46,32 +47,30 @@ const Timeline = (props) => {
         let initialPosition = 0;
         if (scrollToNow) {
             initialPosition = calcTimeOffset(HOUR_BLOCK_HEIGHT);
-        }
-        else if (scrollToFirst && packedEvents[0].length > 0) {
+        } else if (scrollToFirst && packedEvents[0].length > 0) {
             initialPosition = min(map(packedEvents[0], 'top')) ?? 0;
-        }
-        else if (initialTime) {
+        } else if (initialTime) {
             initialPosition = calcTimeOffset(HOUR_BLOCK_HEIGHT, initialTime.hour, initialTime.minutes);
         }
         if (initialPosition) {
-            setTimeout(() => {
+
                 scrollView?.current?.scrollTo({
                     y: Math.max(0, initialPosition - HOUR_BLOCK_HEIGHT),
                     animated: true
                 });
-            }, 0);
+        
         }
     }, []);
-    const _onEventPress = useCallback((dateIndex, eventIndex) => {
+    const _onEventPress = (dateIndex, eventIndex) => {
         const event = packedEvents[dateIndex][eventIndex];
         if (eventTapped) {
             //TODO: remove after deprecation
             eventTapped(event);
         }
         else {
-            onEventPress?.(event);
+                onEventPress(event);
         }
-    }, [onEventPress, eventTapped]);
+    };
     const renderEvents = (dayIndex) => {
         const events = packedEvents[dayIndex].map((event, eventIndex) => {
             const onEventPress = () => _onEventPress(dayIndex, eventIndex);

'

amorimcode avatar Mar 13 '24 22:03 amorimcode