feat: calendar fixes
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
import { cn } from "@/utils/class-merge";
|
||||||
import { FunctionComponent, h } from "preact";
|
import { FunctionComponent, h } from "preact";
|
||||||
import { useState } from "preact/hooks";
|
import { useState } from "preact/hooks";
|
||||||
|
|
||||||
@@ -11,7 +12,7 @@ interface BigCalendarProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
||||||
onDateSelect,
|
onDateSelect = () => {},
|
||||||
markedDates = {},
|
markedDates = {},
|
||||||
className = "",
|
className = "",
|
||||||
}: BigCalendarProps) => {
|
}: BigCalendarProps) => {
|
||||||
@@ -33,14 +34,15 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|||||||
"Декабрь",
|
"Декабрь",
|
||||||
];
|
];
|
||||||
|
|
||||||
const dayNames: string[] = ["Вс", "Пн", "Вт", "Ср", "Чт", "Пт", "Сб"];
|
const dayNames: string[] = ["Пн", "Вт", "Ср", "Чт", "Пт", "Сб", "Вс"];
|
||||||
|
|
||||||
const getDaysInMonth = (year: number, month: number): number => {
|
const getDaysInMonth = (year: number, month: number): number => {
|
||||||
return new Date(year, month + 1, 0).getDate();
|
return new Date(year, month + 1, 0).getDate();
|
||||||
};
|
};
|
||||||
|
|
||||||
const getFirstDayOfMonth = (year: number, month: number): number => {
|
const getFirstDayOfMonth = (year: number, month: number): number => {
|
||||||
return new Date(year, month, 1).getDay();
|
const day = new Date(year, month, 1).getDay();
|
||||||
|
return day === 0 ? 6 : day - 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handlePrevMonth = (): void => {
|
const handlePrevMonth = (): void => {
|
||||||
@@ -64,21 +66,28 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|||||||
return markedDates[dateStr];
|
return markedDates[dateStr];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getLastDayOfMonth = (year: number, month: number): number => {
|
||||||
|
const day = new Date(year, month + 1, 0).getDay();
|
||||||
|
return day === 0 ? 6 : day - 1;
|
||||||
|
};
|
||||||
|
|
||||||
const renderDays = (): h.JSX.Element[] => {
|
const renderDays = (): h.JSX.Element[] => {
|
||||||
const year: number = currentDate.getFullYear();
|
const year: number = currentDate.getFullYear();
|
||||||
const month: number = currentDate.getMonth();
|
const month: number = currentDate.getMonth();
|
||||||
|
|
||||||
const daysInMonth: number = getDaysInMonth(year, month);
|
const daysInMonth: number = getDaysInMonth(year, month);
|
||||||
const firstDayOfMonth: number = getFirstDayOfMonth(year, month);
|
const firstDayOfMonth: number = getFirstDayOfMonth(year, month);
|
||||||
const lastDayOfMonth: number = new Date(year, month, daysInMonth).getDay();
|
const lastDayOfMonth: number = getLastDayOfMonth(year, month);
|
||||||
|
|
||||||
const days: h.JSX.Element[] = [];
|
const days: h.JSX.Element[] = [];
|
||||||
|
|
||||||
// Дни предыдущего месяца
|
// Дни предыдущего месяца
|
||||||
|
//TODO: work on click on 31 march
|
||||||
const prevMonthDays = getDaysInMonth(year, month - 1);
|
const prevMonthDays = getDaysInMonth(year, month - 1);
|
||||||
for (let i = firstDayOfMonth - 1; i >= 0; i--) {
|
const daysFromPrevMonth = firstDayOfMonth === 0 ? 6 : firstDayOfMonth;
|
||||||
|
for (let i = daysFromPrevMonth - 1; i >= 0; i--) {
|
||||||
const day = prevMonthDays - i;
|
const day = prevMonthDays - i;
|
||||||
const date = new Date(year, month - 1, day);
|
const date = new Date(year, month - 1, day + 1);
|
||||||
const dateStr = date.toISOString().split("T")[0];
|
const dateStr = date.toISOString().split("T")[0];
|
||||||
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
||||||
const markType = isDateMarked(date);
|
const markType = isDateMarked(date);
|
||||||
@@ -86,13 +95,21 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|||||||
days.push(
|
days.push(
|
||||||
<div
|
<div
|
||||||
key={`prev-${day}`}
|
key={`prev-${day}`}
|
||||||
className={`relative flex h-24 cursor-pointer flex-col border border-gray-200 p-2 opacity-50 hover:opacity-70 ${isSelected ? "bg-gray-200" : ""} `}
|
className={cn(
|
||||||
|
"relative flex h-24 cursor-pointer flex-col border border-gray-200 p-2 opacity-50 hover:opacity-70",
|
||||||
|
{ "bg-gray-200": isSelected }
|
||||||
|
)}
|
||||||
onClick={() => handleDateClick(date, false)}
|
onClick={() => handleDateClick(date, false)}
|
||||||
>
|
>
|
||||||
<div className="flex h-8 w-8 items-center justify-center self-end rounded-full text-gray-600">{day}</div>
|
<div className="flex h-8 w-8 items-center justify-center self-end rounded-full text-gray-600">{day}</div>
|
||||||
{markType && (
|
{markType && (
|
||||||
<div
|
<div
|
||||||
className={`mb-1 truncate rounded p-1 text-xs ${markType === "event" ? "bg-green-100 text-green-800" : ""} ${markType === "holiday" ? "bg-red-100 text-red-800" : ""} ${markType === "important" ? "bg-yellow-100 text-yellow-800" : ""} `}
|
className={cn(
|
||||||
|
"mb-1 truncate rounded p-1 text-xs",
|
||||||
|
{ "bg-green-100 text-green-800": markType === "event" },
|
||||||
|
{ "bg-red-100 text-red-800": markType === "holiday" },
|
||||||
|
{ "bg-yellow-100 text-yellow-800": markType === "important" }
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{markType}
|
{markType}
|
||||||
</div>
|
</div>
|
||||||
@@ -103,7 +120,7 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|||||||
|
|
||||||
// Дни текущего месяца
|
// Дни текущего месяца
|
||||||
for (let day = 1; day <= daysInMonth; day++) {
|
for (let day = 1; day <= daysInMonth; day++) {
|
||||||
const date = new Date(year, month, day);
|
const date = new Date(year, month, day + 1);
|
||||||
const dateStr = date.toISOString().split("T")[0];
|
const dateStr = date.toISOString().split("T")[0];
|
||||||
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
||||||
const markType = isDateMarked(date);
|
const markType = isDateMarked(date);
|
||||||
@@ -112,18 +129,32 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|||||||
days.push(
|
days.push(
|
||||||
<div
|
<div
|
||||||
key={`current-${day}`}
|
key={`current-${day}`}
|
||||||
className={`relative flex h-24 flex-col border border-gray-200 p-2 ${isSelected ? "border-blue-400 bg-blue-100" : ""} ${isToday ? "border-yellow-400" : ""} cursor-pointer hover:bg-gray-50`}
|
className={cn(
|
||||||
onClick={() => handleDateClick(date, true)}
|
"relative flex h-24 flex-col border border-gray-200 p-2",
|
||||||
|
{ "border-blue-400 bg-blue-100": isSelected },
|
||||||
|
{ "border-yellow-400": isToday },
|
||||||
|
"cursor-pointer hover:bg-gray-50"
|
||||||
|
)}
|
||||||
|
onClick={() => (selectedDate ? setSelectedDate(null) : handleDateClick(date, true))}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
className={`flex h-8 w-8 items-center justify-center self-end rounded-full ${isSelected ? "bg-blue-600 text-white" : ""} ${isToday && !isSelected ? "bg-yellow-100 text-yellow-800" : ""} `}
|
className={cn(
|
||||||
|
"flex h-8 w-8 items-center justify-center self-end rounded-full",
|
||||||
|
{ "bg-blue-600 text-white": isSelected },
|
||||||
|
{ "bg-yellow-100 text-yellow-800": isToday && !isSelected }
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{day}
|
{day}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{markType && (
|
{markType && (
|
||||||
<div
|
<div
|
||||||
className={`mb-1 truncate rounded p-1 text-xs ${markType === "event" ? "bg-green-100 text-green-800" : ""} ${markType === "holiday" ? "bg-red-100 text-red-800" : ""} ${markType === "important" ? "bg-yellow-100 text-yellow-800" : ""} `}
|
className={cn(
|
||||||
|
"mb-1 truncate rounded p-1 text-xs",
|
||||||
|
{ "bg-green-100 text-green-800": markType === "event" },
|
||||||
|
{ "bg-red-100 text-red-800": markType === "holiday" },
|
||||||
|
{ "bg-yellow-100 text-yellow-800": markType === "important" }
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{markType}
|
{markType}
|
||||||
</div>
|
</div>
|
||||||
@@ -133,9 +164,9 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Дни следующего месяца
|
// Дни следующего месяца
|
||||||
const daysToAdd = 6 - lastDayOfMonth;
|
const daysToAdd = 6 - (lastDayOfMonth === 6 ? 4 : lastDayOfMonth);
|
||||||
for (let day = 1; day <= daysToAdd; day++) {
|
for (let day = 1; day <= daysToAdd; day++) {
|
||||||
const date = new Date(year, month + 1, day);
|
const date = new Date(year, month + 1, day + 1);
|
||||||
const dateStr = date.toISOString().split("T")[0];
|
const dateStr = date.toISOString().split("T")[0];
|
||||||
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
const isSelected = selectedDate?.toISOString().split("T")[0] === dateStr;
|
||||||
const markType = isDateMarked(date);
|
const markType = isDateMarked(date);
|
||||||
@@ -143,13 +174,21 @@ const BigCalendar: FunctionComponent<BigCalendarProps> = ({
|
|||||||
days.push(
|
days.push(
|
||||||
<div
|
<div
|
||||||
key={`next-${day}`}
|
key={`next-${day}`}
|
||||||
className={`relative flex h-24 cursor-pointer flex-col border border-gray-200 p-2 opacity-50 hover:opacity-70 ${isSelected ? "bg-gray-200" : ""} `}
|
className={cn(
|
||||||
|
"relative flex h-24 cursor-pointer flex-col border border-gray-200 p-2 opacity-50 hover:opacity-70",
|
||||||
|
{ "bg-gray-200": isSelected }
|
||||||
|
)}
|
||||||
onClick={() => handleDateClick(date, false)}
|
onClick={() => handleDateClick(date, false)}
|
||||||
>
|
>
|
||||||
<div className="flex h-8 w-8 items-center justify-center self-end rounded-full text-gray-600">{day}</div>
|
<div className="flex h-8 w-8 items-center justify-center self-end rounded-full text-gray-600">{day}</div>
|
||||||
{markType && (
|
{markType && (
|
||||||
<div
|
<div
|
||||||
className={`mb-1 truncate rounded p-1 text-xs ${markType === "event" ? "bg-green-100 text-green-800" : ""} ${markType === "holiday" ? "bg-red-100 text-red-800" : ""} ${markType === "important" ? "bg-yellow-100 text-yellow-800" : ""} `}
|
className={cn(
|
||||||
|
"mb-1 truncate rounded p-1 text-xs",
|
||||||
|
{ "bg-green-100 text-green-800": markType === "event" },
|
||||||
|
{ "bg-red-100 text-red-800": markType === "holiday" },
|
||||||
|
{ "bg-yellow-100 text-yellow-800": markType === "important" }
|
||||||
|
)}
|
||||||
>
|
>
|
||||||
{markType}
|
{markType}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user