quasarframework / quasar-ui-qcalendar

QCalendar - Quasar App Extension, Vue CLI plug-in and UMD distributions available
https://quasarframework.github.io/quasar-ui-qcalendar
MIT License
421 stars 116 forks source link

Q Calendar event overlapping #404

Open nyh1234444 opened 1 year ago

nyh1234444 commented 1 year ago

Good Days, sorry for disturbing. May i ask some question regarding the q calendar event. If i got more than 2 event in one time-slot and had been overlapping . How to display cause i just find the resource for 2 event only. Thanks

zuck commented 1 year ago

This is what I'm doing currently (the list of events comes from an API, each event has a unique id). However I agree it would be great to a have a built-in support in the extension for that...

    function getEventStyle(event, events, timeStartPos, timeDurationHeight) {
      const { from, to, duration } = this.getEventRange(event);
      const matches = this.getMatchingEvents(event, events);
      const idx = matches.findIndex((id) => id === event.id);
      const gutter = (matches.length - 1) * 1.25;
      const width = (100 - gutter) / matches.length;
      const margin = matches.length ? gutter / (matches.length - 1) : 0;
      return {
        position: "absolute",
        background: "yellow",
        color: "black",
        top: timeStartPos(event.from) + "px",
        height: timeDurationHeight(duration) + "px",
        left: `${idx * (width + margin)}%`,
        width: `${width}%`,
      };
    }

    function getMatchingEvents(event, events) {
     return events
       filter((e) => {
        if (e.date !== event.date) {
          return false;
        }
        const { from: start, to: end } = this.getEventRange(e);
        return this.areOverlapping(from, to, start, end);
      })
      .map((e) => e.id);
    }

    function areOverlapping(start1, end1, start2, end2) {
      if (start1 <= start2 && start2 <= end1) return true; // b starts in a
      if (start1 <= end2 && end2 <= end1) return true; // b ends in a
      if (start2 < start1 && end1 < end2) return true; // a in b
      return false;
    }
yohn-cheung commented 1 year ago

This is what I'm doing currently (the list of events comes from an API, each event has a unique id). However I agree it would be great to a have a built-in support in the extension for that...

    function getEventStyle(event, events, timeStartPos, timeDurationHeight) {
      const { from, to, duration } = this.getEventRange(event);
      const matches = this.getMatchingEvents(event, events);
      const idx = matches.findIndex((id) => id === event.id);
      const gutter = (matches.length - 1) * 1.25;
      const width = (100 - gutter) / matches.length;
      const margin = matches.length ? gutter / (matches.length - 1) : 0;
      return {
        position: "absolute",
        background: "yellow",
        color: "black",
        top: timeStartPos(event.from) + "px",
        height: timeDurationHeight(duration) + "px",
        left: `${idx * (width + margin)}%`,
        width: `${width}%`,
      };
    }

    function getMatchingEvents(event, events) {
     return events
       filter((e) => {
        if (e.date !== event.date) {
          return false;
        }
        const { from: start, to: end } = this.getEventRange(e);
        return this.areOverlapping(from, to, start, end);
      })
      .map((e) => e.id);
    }

    function areOverlapping(start1, end1, start2, end2) {
      if (start1 <= start2 && start2 <= end1) return true; // b starts in a
      if (start1 <= end2 && end2 <= end1) return true; // b ends in a
      if (start2 < start1 && end1 < end2) return true; // a in b
      return false;
    }

Hello Zuck, can you explain what the function getEventRange is? I don't see the function getEventRange in your code snippet. I have the same problem.