cal.pub0.org/packages/features/timezone-buddy/components/HoverOverview.tsx

150 lines
3.7 KiB
TypeScript
Raw Normal View History

feat: Availability slider for orgs (#10740) * Init + get timezone + offset data agh * Add 12/24h mode - style correctly * User users timezone + working hours. Still some stuff to figure out * Multiple working hours * move calc to once per day * Demo with two users and differnt timezones * availabillity control tab via search params * WIP hover overlay * THIS WORKS ISH * fix: multiple duration getSchedule calls [CAL-2336] (#10709) Co-authored-by: Omar López <zomars@me.com> * New Crowdin translations by Github Action * fix: If the input type "Name" is selected, the label can't be changed from our default label "Your Name" (#10618) Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> * New Crowdin translations by Github Action * test: Create unit tests for react components in packages/ui/components/form/step (#10442) Co-authored-by: gitstart-calcom <gitstart@users.noreply.github.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> * feat: element call app added (#10585) Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> * New Crowdin translations by Github Action * New Crowdin translations by Github Action * fix: e2e test for rescheduling overlapping time (#10721) Co-authored-by: CarinaWolli <wollencarina@gmail.com> * feat: mailhog fixture (#10606) * feat: mailhog fixture * fix: nodemailer to dispatch emails with e2e env * fix: remove space from email subject * feat: fixture getFirstEventAsOwner * feat: assert email subjects * fix: and enable dynamic booking test (#10642) * fix and enable dynamic booking test * remove page pause --------- Co-authored-by: Alex van Andel <me@alexvanandel.com> * fix: Broken team events if a user with the same name exists (#10724) * fix: Broken team events if a user with the same name exists * Fix tests + fix usernameList optionality * Try to list calendars, if not continue (#10720) Co-authored-by: Omar López <zomars@me.com> * v3.1.9 * link to org settings (#10718) * feat: app paypal payment (#8797) Co-authored-by: sean-brydon <55134778+sean-brydon@users.noreply.github.com> Co-authored-by: Omar López <zomars@me.com> * fix: RTL issues on booking pages + email confirmation (#10526) Co-authored-by: Peer Richelsen <peeroke@gmail.com> * fix: merge conflict * Fixing org slug (#10538) * fix: paypal build fixes * Fix avatar for org in Shell top (#10712) * feat: add range of dates for availability over-ride (#10462) * feat: add range of dates for availability over-ride * chore: changed range select to multiple select --------- Co-authored-by: Alex van Andel <me@alexvanandel.com> * fix: border issue for time slots (#10577) Co-authored-by: Raghul D <v-raghuld@microsoft.com> * style: Fix text wrapping issue in button (#10725) Co-authored-by: Omar López <zomars@me.com> * New Crowdin translations by Github Action * fix: App Install Dropdown Sort Properly [CAL-2285] (#10672) Co-authored-by: Peer Richelsen <peeroke@gmail.com> * fix: link escaping in booking page (#10360) Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> * chore: fix refund i18n message (#10731) * chore: remove tailwind-scrollbar warning (#10523) Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com> * New Crowdin translations by Github Action * chore: Simplified date overrides (#10728) * chore: Simplified date overrides * Fixed a test that had a date override that wasn't at midnight utc * Wrote test that showed a fixed Europe/Brussels * Lint fix * New Crowdin translations by Github Action * Fix offset time + fetching correct dates * Deal with awkward minute offsets * remove store overhead * Format H based on tz * Cleanup store logic * Cleanup * Remove comments * Remove comments * Remove yarn.lock * Dark mode & v-align text fixes * Move ButtonGroup to the left to prevent chevron from jumping * Shift based on timezone (non-hour) and have 15min granularity in hour display background color --------- Co-authored-by: Leo Giovanetti <hello@leog.me> Co-authored-by: Omar López <zomars@me.com> Co-authored-by: Crowdin Bot <support+bot@crowdin.com> Co-authored-by: Zain Gulbaz <zaingulbaz8@gmail.com> Co-authored-by: Carina Wollendorfer <30310907+CarinaWolli@users.noreply.github.com> Co-authored-by: GitStart-Cal.com <121884634+gitstart-calcom@users.noreply.github.com> Co-authored-by: gitstart-calcom <gitstart@users.noreply.github.com> Co-authored-by: Keith Williams <keithwillcode@gmail.com> Co-authored-by: Suyash Srivastava <suyashsrivastava5053@gmail.com> Co-authored-by: Hariom Balhara <hariombalhara@gmail.com> Co-authored-by: CarinaWolli <wollencarina@gmail.com> Co-authored-by: Shivam Kalra <shivamkalra98@gmail.com> Co-authored-by: alannnc <alannnc@gmail.com> Co-authored-by: Alex van Andel <me@alexvanandel.com> Co-authored-by: Joe Au-Yeung <65426560+joeauyeung@users.noreply.github.com> Co-authored-by: Peer Richelsen <peeroke@gmail.com> Co-authored-by: Anik Dhabal Babu <81948346+anikdhabal@users.noreply.github.com> Co-authored-by: Pradumn Kumar <pradumn@tealfeed.com> Co-authored-by: Raghul <123321540+Raghul18@users.noreply.github.com> Co-authored-by: Raghul D <v-raghuld@microsoft.com> Co-authored-by: ABDERRAHMANI IDRISSI HAMZA <97639117+idrissi-hamza@users.noreply.github.com> Co-authored-by: Nafees Nazik <84864519+G3root@users.noreply.github.com> Co-authored-by: Danila <daniil.demidovich@gmail.com> Co-authored-by: Udit Takkar <53316345+Udit-takkar@users.noreply.github.com>
2023-08-18 16:32:24 +00:00
import { useState, useRef, useEffect, useMemo } from "react";
import { DAY_CELL_WIDTH } from "../constants";
function rounded(x: number, dayCellWidth: number) {
let n = Math.round(x / dayCellWidth);
n = Math.max(0, n);
n = Math.min(24, n);
return n * dayCellWidth;
}
function useElementBounding<T extends HTMLDivElement>(ref: React.RefObject<T>): DOMRect | null {
const [boundingRect, setBoundingRect] = useState<DOMRect | null>(null);
const observer = useRef<ResizeObserver | null>(null);
useEffect(() => {
const target = ref.current;
function updateBoundingRect() {
if (target) {
const rect = target.getBoundingClientRect();
setBoundingRect(rect);
}
}
updateBoundingRect();
observer.current = new ResizeObserver(updateBoundingRect);
observer.current.observe(target as Element);
return () => {
if (observer.current) {
observer.current.disconnect();
observer.current = null;
}
};
}, [ref]);
return boundingRect;
}
function useMouse() {
const [x, setX] = useState(0);
const [y, setY] = useState(0);
const [isPressed, setIsPressed] = useState(false);
useEffect(() => {
function handleMouseMove(event: MouseEvent) {
setX(event.clientX);
setY(event.clientY);
}
function handleMouseDown() {
setIsPressed(true);
}
function handleMouseUp() {
setIsPressed(false);
}
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mousedown", handleMouseDown);
document.addEventListener("mouseup", handleMouseUp);
return () => {
document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mousedown", handleMouseDown);
document.removeEventListener("mouseup", handleMouseUp);
};
}, []);
return { x, y, isPressed };
}
export function HoverOverview() {
const top = useRef(0);
const bottom = useRef(0);
const edgeStart = useRef(0);
const edgeEnd = useRef(0);
const [leftEdge, setLeftEdge] = useState(0);
const [rightEdge, setRightEdge] = useState(0);
const [width, setWidth] = useState(0);
const { x, y, isPressed: pressed } = useMouse();
const el = useRef<HTMLDivElement | null>(null);
const box = useElementBounding(el);
useEffect(() => {
function updateEdge() {
const roundedX = rounded(x - (box?.left || 0), DAY_CELL_WIDTH);
edgeStart.current = roundedX;
edgeEnd.current = roundedX;
setLeftEdge(roundedX);
}
if (pressed) {
updateEdge();
}
}, [pressed, x, box]);
useEffect(() => {
if (pressed) {
const roundedX = rounded(x - (box?.left || 0), DAY_CELL_WIDTH);
edgeEnd.current = roundedX;
setRightEdge(roundedX);
}
}, [pressed, x, box]);
useEffect(() => {
setWidth(Math.abs(edgeStart.current - edgeEnd.current));
}, [edgeStart, edgeEnd]);
const position = useMemo(
() => ({
left: `${leftEdge}px`,
top: `${top}px`,
bottom: `${bottom}px`,
width: `${width}px`,
}),
[leftEdge, top, bottom, width]
);
const leftWhiteout = useMemo(
() => ({
left: "0",
top: `${top}px`,
bottom: `${bottom}px`,
width: `${leftEdge}px`,
}),
[leftEdge, top, bottom]
);
const rightWhiteout = useMemo(
() => ({
right: "0",
top: `${top}px`,
bottom: `${bottom}px`,
left: `${rightEdge}px`,
}),
[rightEdge, top, bottom]
);
return (
<div ref={el} className="absoulte inset-0 w-full">
<div className="bg-default/80 absolute" style={leftWhiteout} />
<div className="bg-default/80 absolute" style={rightWhiteout} />
<div className="border-emphasis border border-dashed" style={position} />
</div>
);
}