import { useEntity, useReplicache } from "src/replicache";
import { BlockProps } from "./Block";
import { ChevronProps, DayPicker } from "react-day-picker";
import { Popover } from "components/Popover";
import { useEffect, useMemo, useState } from "react";
import { useEntitySetContext } from "components/EntitySetProvider";
import { useUIState } from "src/useUIState";
import { setHours, setMinutes } from "date-fns";
import { Separator } from "react-aria-components";
import { Checkbox } from "components/Checkbox";
import { useHasPageLoaded } from "components/InitialPageLoadProvider";
import { useSpring, animated } from "@react-spring/web";
import { ArrowRightTiny } from "components/Icons/ArrowRightTiny";
import { BlockCalendarSmall } from "components/Icons/BlockCalendarSmall";
export function DateTimeBlock(props: BlockProps) {
const [isClient, setIsClient] = useState(false);
let initialPageLoad = useHasPageLoaded();
useEffect(() => {
setIsClient(true);
}, []);
if (!isClient && !initialPageLoad)
return (
);
return ;
}
export function BaseDateTimeBlock(
props: BlockProps & { initalLoad?: boolean },
) {
let { rep } = useReplicache();
let { permissions } = useEntitySetContext();
let dateFact = useEntity(props.entityID, "block/date-time");
let selectedDate = useMemo(() => {
if (!dateFact) return new Date();
let d = new Date(dateFact.data.value);
return d;
}, [dateFact]);
const [timeValue, setTimeValue] = useState(
() =>
`${selectedDate.getHours().toString().padStart(2, "0")}:${selectedDate.getMinutes().toString().padStart(2, "0")}`,
);
let isSelected = useUIState((s) =>
s.selectedBlocks.find((b) => b.value === props.entityID),
);
let isLocked = !!useEntity(props.entityID, "block/is-locked")?.data.value;
let alignment = useEntity(props.entityID, "block/text-alignment")?.data.value;
const handleTimeChange: React.ChangeEventHandler = (e) => {
const time = e.target.value;
setTimeValue(time);
if (!dateFact) {
return;
}
const [hours, minutes] = time.split(":").map((str) => parseInt(str, 10));
const newSelectedDate = setHours(setMinutes(selectedDate, minutes), hours);
rep?.mutate.assertFact({
entity: props.entityID,
data: {
type: "date-time",
value: newSelectedDate.toISOString(),
dateOnly: dateFact?.data.dateOnly,
originalTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
},
attribute: "block/date-time",
});
};
const handleDaySelect = (date: Date | undefined) => {
if (!timeValue || !date) {
if (date)
rep?.mutate.assertFact({
entity: props.entityID,
data: {
originalTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
type: "date-time",
value: date.toISOString(),
dateOnly: dateFact?.data.dateOnly,
},
attribute: "block/date-time",
});
return;
}
const [hours, minutes] = timeValue
.split(":")
.map((str) => parseInt(str, 10));
const newDate = new Date(
date.getFullYear(),
date.getMonth(),
date.getDate(),
hours,
minutes,
);
rep?.mutate.assertFact({
entity: props.entityID,
data: {
type: "date-time",
value: newDate.toISOString(),
originalTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
dateOnly: dateFact?.data.dateOnly,
},
attribute: "block/date-time",
});
};
return (
{dateFact ? (
{selectedDate.toLocaleDateString(undefined, {
month: "short",
year:
new Date().getFullYear() !== selectedDate.getFullYear()
? "numeric"
: undefined,
day: "numeric",
})}{" "}
{!dateFact.data.dateOnly ? (
|{" "}
{selectedDate.toLocaleTimeString([], {
hour: "numeric",
minute: "numeric",
})}
) : null}
) : (
{permissions.write ? "add a date and time..." : "TBD..."}
)}
}
>
,
}}
classNames={{
months: "relative",
month_caption:
"font-bold text-center w-full bg-border-light mb-2 py-1 rounded-md",
button_next:
"absolute right-0 top-1 p-1 text-secondary hover:text-accent-contrast flex align-center",
button_previous:
"absolute left-0 top-1 p-1 text-secondary hover:text-accent-contrast rotate-180 flex align-center ",
chevron: "text-inherit",
month_grid: "w-full table-fixed",
weekdays: "text-secondary text-sm",
selected: "bg-accent-1! text-accent-2 rounded-md font-bold",
day: "h-[34px] text-center rounded-md sm:hover:bg-border-light",
outside: "text-border",
today: "font-bold",
}}
mode="single"
selected={dateFact ? selectedDate : undefined}
onSelect={handleDaySelect}
/>
{
rep?.mutate.assertFact({
entity: props.entityID,
data: {
type: "date-time",
value: dateFact?.data.value || new Date().toISOString(),
originalTimezone:
dateFact?.data.originalTimezone ||
Intl.DateTimeFormat().resolvedOptions().timeZone,
dateOnly: e.currentTarget.checked,
},
attribute: "block/date-time",
});
}}
>
All day
);
}
let FadeIn = (props: { children: React.ReactNode; active: boolean }) => {
let spring = useSpring({ opacity: props.active ? 1 : 0 });
return {props.children};
};
const CustomChevron = (props: ChevronProps) => {
return (
);
};