|
|
|
|
@@ -1,9 +1,26 @@
|
|
|
|
|
import { withTitle } from "@/constructors/Component";
|
|
|
|
|
import { UrlsTitle } from "@/enums/urls";
|
|
|
|
|
import { cn } from "@/utils/class-merge";
|
|
|
|
|
import { BackwardIcon } from "@heroicons/react/24/solid";
|
|
|
|
|
import { FunctionComponent, h } from "preact";
|
|
|
|
|
import { useState } from "preact/hooks";
|
|
|
|
|
|
|
|
|
|
interface BackButtonProps {
|
|
|
|
|
selectedDate: Date;
|
|
|
|
|
onClick: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const BackButton: FunctionComponent<BackButtonProps> = ({ selectedDate, onClick }: BackButtonProps) => {
|
|
|
|
|
const currentDate = new Date();
|
|
|
|
|
|
|
|
|
|
return currentDate.getMonth() !== selectedDate.getMonth() ? (
|
|
|
|
|
<div
|
|
|
|
|
class="fixed bottom-4 left-8 hidden aspect-square h-24 cursor-pointer flex-col items-center justify-center rounded-full bg-[rgb(251,194,199,0.53)] shadow-[0px_4px_4px_0px_rgba(0,0,0,0.25)] hover:bg-[rgb(251,194,199,0.7)] md:flex"
|
|
|
|
|
onClick={onClick}
|
|
|
|
|
>
|
|
|
|
|
<BackwardIcon class="size-8 text-sm text-white" />
|
|
|
|
|
</div>
|
|
|
|
|
) : null;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
type MarkedDateType = "event" | "holiday" | "important" | string;
|
|
|
|
|
type MarkedDates = Record<string, MarkedDateType>;
|
|
|
|
|
|
|
|
|
|
@@ -44,7 +61,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|
|
|
|
|
|
|
|
|
const getFirstDayOfMonth = (year: number, month: number): number => {
|
|
|
|
|
const day = new Date(year, month, 1).getDay();
|
|
|
|
|
return day === 0 ? 6 : day - 1;
|
|
|
|
|
return day === 0 ? 6 : day;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const handlePrevMonth = (): void => {
|
|
|
|
|
@@ -60,7 +77,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|
|
|
|
setCurrentDate(new Date(date.getFullYear(), date.getMonth(), 1));
|
|
|
|
|
}
|
|
|
|
|
setSelectedDate(date);
|
|
|
|
|
onDateSelect?.(date);
|
|
|
|
|
onDateSelect(date);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const isDateMarked = (date: Date): MarkedDateType | undefined => {
|
|
|
|
|
@@ -70,7 +87,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|
|
|
|
|
|
|
|
|
const getLastDayOfMonth = (year: number, month: number): number => {
|
|
|
|
|
const day = new Date(year, month + 1, 0).getDay();
|
|
|
|
|
return day === 0 ? 6 : day - 1;
|
|
|
|
|
return day === 0 ? 6 : day;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const renderDays = (): h.JSX.Element[] => {
|
|
|
|
|
@@ -84,12 +101,11 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|
|
|
|
const days: h.JSX.Element[] = [];
|
|
|
|
|
|
|
|
|
|
// Дни предыдущего месяца
|
|
|
|
|
//TODO: work on click on 31 march
|
|
|
|
|
const prevMonthDays = getDaysInMonth(year, month - 1);
|
|
|
|
|
const daysFromPrevMonth = firstDayOfMonth === 0 ? 6 : firstDayOfMonth;
|
|
|
|
|
for (let i = daysFromPrevMonth - 1; i >= 0; i--) {
|
|
|
|
|
const day = prevMonthDays - i;
|
|
|
|
|
const date = new Date(year, month - 1, day + 1);
|
|
|
|
|
const date = new Date(year, month - 1, day);
|
|
|
|
|
const dateStr = date.toISOString().split("T")[0];
|
|
|
|
|
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
|
|
|
|
const markType = isDateMarked(date);
|
|
|
|
|
@@ -122,7 +138,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|
|
|
|
|
|
|
|
|
// Дни текущего месяца
|
|
|
|
|
for (let day = 1; day <= daysInMonth; day++) {
|
|
|
|
|
const date = new Date(year, month, day + 1);
|
|
|
|
|
const date = new Date(year, month, day);
|
|
|
|
|
const dateStr = date.toISOString().split("T")[0];
|
|
|
|
|
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
|
|
|
|
const markType = isDateMarked(date);
|
|
|
|
|
@@ -166,9 +182,9 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Дни следующего месяца
|
|
|
|
|
const daysToAdd = 6 - (lastDayOfMonth === 6 ? 4 : lastDayOfMonth);
|
|
|
|
|
const daysToAdd = 6 - (lastDayOfMonth === 6 ? 3 : lastDayOfMonth);
|
|
|
|
|
for (let day = 1; day <= daysToAdd; day++) {
|
|
|
|
|
const date = new Date(year, month + 1, day + 1);
|
|
|
|
|
const date = new Date(year, month + 1, day);
|
|
|
|
|
const dateStr = date.toISOString().split("T")[0];
|
|
|
|
|
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
|
|
|
|
const markType = isDateMarked(date);
|
|
|
|
|
@@ -203,7 +219,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<div className={`flex flex-col ${className}`}>
|
|
|
|
|
<div className={`flex w-full flex-col ${className}`}>
|
|
|
|
|
<div className="mb-4 flex items-center justify-between px-2">
|
|
|
|
|
<button
|
|
|
|
|
onClick={handlePrevMonth}
|
|
|
|
|
@@ -235,7 +251,6 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|
|
|
|
</svg>
|
|
|
|
|
</button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="mb-2 grid grid-cols-7 gap-1 text-center text-sm font-medium text-gray-500">
|
|
|
|
|
{dayNames.map((day) => (
|
|
|
|
|
<div key={day} className="flex h-10 items-center justify-center">
|
|
|
|
|
@@ -243,10 +258,10 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|
|
|
|
</div>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="grid flex-1 grid-cols-7 gap-1">{renderDays()}</div>
|
|
|
|
|
<BackButton selectedDate={currentDate} onClick={() => setCurrentDate(new Date())} />
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default withTitle(UrlsTitle.CALENDAR, BigCalendar);
|
|
|
|
|
export default BigCalendar;
|