Created
May 9, 2024 12:09
-
-
Save Shaxadhere/7f6ed85d106bfe685b9b7f66da23634c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useState } from "react"; | |
import { | |
Flex, | |
Box, | |
Text, | |
IconButton, | |
Icon, | |
SimpleGrid, | |
VStack, | |
} from "@chakra-ui/react"; | |
import { MdChevronLeft, MdChevronRight } from "react-icons/md"; | |
const CalendarMonth = ({ | |
currentDate, | |
setCurrentDate, | |
toggleYearDropdown, | |
isMonthDropdownOpen, | |
toggleMonthDropdown, | |
}) => { | |
const handleMonthChange = (month) => { | |
setCurrentDate(new Date(currentDate.getFullYear(), month, 1)); | |
toggleMonthDropdown(); | |
}; | |
const getMonthData = (year) => { | |
return Array.from( | |
{ length: 12 }, | |
(_, monthIndex) => new Date(year, monthIndex, 1) | |
); | |
}; | |
const renderMonthDropdown = () => { | |
return isMonthDropdownOpen ? ( | |
<Box position="absolute" zIndex="1"> | |
<Flex | |
flexDirection="column" | |
bg="white" | |
boxShadow="md" | |
borderRadius="md" | |
> | |
{getMonthData(currentDate.getFullYear()).map((monthDate, index) => ( | |
<Box | |
key={index} | |
p={2} | |
cursor="pointer" | |
onClick={() => handleMonthChange(index)} | |
_hover={{ bg: "gray.100" }} | |
> | |
<Text> | |
{monthDate.toLocaleString("default", { month: "long" })} | |
</Text> | |
</Box> | |
))} | |
</Flex> | |
</Box> | |
) : null; | |
}; | |
return ( | |
<Flex gap={1} alignItems="center" position="relative"> | |
<Text onClick={toggleMonthDropdown} cursor="pointer"> | |
{currentDate.toLocaleString("default", { month: "long" })} | |
</Text> | |
<Text onClick={toggleYearDropdown} cursor="pointer"> | |
{currentDate.getFullYear()} | |
</Text> | |
{renderMonthDropdown()} | |
</Flex> | |
); | |
}; | |
const CalendarMonth2 = ({ | |
currentDate, | |
setCurrentDate, | |
isMonthDropdownOpen, | |
toggleMonthDropdown, | |
}) => { | |
const handleMonthChange = (month) => { | |
setCurrentDate(new Date(currentDate.getFullYear(), month, 1)); | |
toggleMonthDropdown(); | |
}; | |
const getMonthData = (year) => { | |
return Array.from( | |
{ length: 12 }, | |
(_, monthIndex) => new Date(year, monthIndex, 1) | |
); | |
}; | |
const renderYearButtons = () => { | |
const currentYear = currentDate.getFullYear(); | |
const years = []; | |
for (let i = currentYear - 5; i <= currentYear + 5; i++) { | |
years.push(i); | |
} | |
return ( | |
<Flex px={1} py={2}> | |
{isMonthDropdownOpen ? ( | |
<VStack align={"stretch"}> | |
<Flex justify={"space-between"} w="full"> | |
<IconButton | |
aria-label="Previous Year" | |
icon={<Icon as={MdChevronLeft} />} | |
onClick={() => | |
setCurrentDate( | |
new Date( | |
currentDate.getFullYear() - 1, | |
currentDate.getMonth(), | |
1 | |
) | |
) | |
} | |
/> | |
<Text>{currentYear}</Text> | |
<IconButton | |
aria-label="Next Year" | |
icon={<Icon as={MdChevronRight} />} | |
onClick={() => | |
setCurrentDate( | |
new Date( | |
currentDate.getFullYear() + 1, | |
currentDate.getMonth(), | |
1 | |
) | |
) | |
} | |
/> | |
</Flex> | |
<SimpleGrid columns={3} spacing={3}> | |
{getMonthData(currentDate.getFullYear()).map( | |
(monthDate, index) => ( | |
<Box | |
key={monthDate} | |
p={2} | |
cursor="pointer" | |
onClick={() => handleMonthChange(monthDate.getDate())} | |
bg={monthDate === currentYear ? "gray.200" : "transparent"} | |
borderRadius="md" | |
mx={1} | |
> | |
<Text> | |
{monthDate.toLocaleString("default", { month: "short" })} | |
</Text> | |
</Box> | |
) | |
)} | |
</SimpleGrid> | |
</VStack> | |
) : null} | |
</Flex> | |
); | |
}; | |
return ( | |
<Flex flexDirection="column" alignItems="center" position="relative"> | |
{renderYearButtons()} | |
</Flex> | |
); | |
}; | |
const CalendarYear = ({ | |
currentDate, | |
setCurrentDate, | |
isYearDropdownOpen, | |
toggleYearDropdown, | |
}) => { | |
const handleYearChange = (year) => { | |
setCurrentDate(new Date(year, currentDate.getMonth(), 1)); | |
toggleYearDropdown(); | |
}; | |
const renderYearButtons = () => { | |
const currentYear = currentDate.getFullYear(); | |
const years = []; | |
for (let i = currentYear - 5; i <= currentYear + 5; i++) { | |
years.push(i); | |
} | |
return ( | |
<Flex px={1} py={2}> | |
{isYearDropdownOpen ? ( | |
<VStack align={"stretch"}> | |
<Flex justify={"space-between"} w="full"> | |
<IconButton | |
aria-label="Previous Year" | |
icon={<Icon as={MdChevronLeft} />} | |
onClick={() => | |
setCurrentDate( | |
new Date( | |
currentDate.getFullYear() - 1, | |
currentDate.getMonth(), | |
1 | |
) | |
) | |
} | |
/> | |
<Text>{currentYear}</Text> | |
<IconButton | |
aria-label="Next Year" | |
icon={<Icon as={MdChevronRight} />} | |
onClick={() => | |
setCurrentDate( | |
new Date( | |
currentDate.getFullYear() + 1, | |
currentDate.getMonth(), | |
1 | |
) | |
) | |
} | |
/> | |
</Flex> | |
<SimpleGrid columns={3} spacing={3}> | |
{years.map((year) => ( | |
<Box | |
key={year} | |
p={2} | |
cursor="pointer" | |
onClick={() => handleYearChange(year)} | |
bg={year === currentYear ? "gray.200" : "transparent"} | |
borderRadius="md" | |
mx={1} | |
> | |
<Text>{year}</Text> | |
</Box> | |
))} | |
</SimpleGrid> | |
</VStack> | |
) : null} | |
</Flex> | |
); | |
}; | |
return ( | |
<Flex flexDirection="column" alignItems="center" position="relative"> | |
{renderYearButtons()} | |
</Flex> | |
); | |
}; | |
const DateInput = () => { | |
const [isYearDropdownOpen, setIsYearDropdownOpen] = useState(false); | |
const [isMonthDropdownOpen, setIsMonthDropdownOpen] = useState(false); | |
const [currentDate, setCurrentDate] = useState(new Date()); | |
const getMonthData = (year, month) => { | |
const firstDay = new Date(year, month, 1); | |
const lastDay = new Date(year, month + 1, 0); | |
const monthData = []; | |
let day = new Date(firstDay); | |
while (day <= lastDay) { | |
monthData.push(new Date(day)); | |
day.setDate(day.getDate() + 1); | |
} | |
return monthData; | |
}; | |
const toggleYearDropdown = () => { | |
setIsYearDropdownOpen(!isYearDropdownOpen); | |
}; | |
const toggleMonthDropdown = () => { | |
setIsMonthDropdownOpen(!isMonthDropdownOpen); | |
}; | |
const renderCalendar = () => { | |
const monthData = getMonthData( | |
currentDate.getFullYear(), | |
currentDate.getMonth() | |
); | |
const firstDayOfMonth = monthData[0].getDay(); | |
const calendar = []; | |
let currentWeek = []; | |
for (let i = 0; i < firstDayOfMonth; i++) { | |
currentWeek.push(null); | |
} | |
monthData.forEach((day, index) => { | |
currentWeek.push(day); | |
if (currentWeek.length === 7) { | |
calendar.push(currentWeek); | |
currentWeek = []; | |
} | |
}); | |
while (currentWeek.length < 7) { | |
currentWeek.push(null); | |
} | |
calendar.push(currentWeek); | |
return ( | |
<Box> | |
<Box> | |
<CalendarYear | |
currentDate={currentDate} | |
setCurrentDate={setCurrentDate} | |
isYearDropdownOpen={isYearDropdownOpen} | |
toggleYearDropdown={toggleYearDropdown} | |
isMonthDropdownOpen={isMonthDropdownOpen} | |
toggleMonthDropdown={toggleMonthDropdown} | |
/> | |
</Box> | |
<Box> | |
<CalendarMonth2 | |
currentDate={currentDate} | |
setCurrentDate={setCurrentDate} | |
isMonthDropdownOpen={isMonthDropdownOpen} | |
toggleMonthDropdown={toggleMonthDropdown} | |
/> | |
</Box> | |
{!isYearDropdownOpen && !isMonthDropdownOpen && ( | |
<> | |
<Flex justifyContent="space-between" mb={4}> | |
<IconButton | |
aria-label="Previous Month" | |
icon={<Icon as={MdChevronLeft} />} | |
onClick={() => | |
setCurrentDate( | |
new Date( | |
currentDate.getFullYear(), | |
currentDate.getMonth() - 1 | |
) | |
) | |
} | |
/> | |
<Flex gap={1} alignItems="center" position="relative"> | |
<Text onClick={toggleMonthDropdown} cursor="pointer"> | |
{currentDate.toLocaleString("default", { month: "long" })} | |
</Text> | |
<Text onClick={toggleYearDropdown} cursor="pointer"> | |
{currentDate.getFullYear()} | |
</Text> | |
</Flex> | |
<IconButton | |
aria-label="Next Month" | |
icon={<Icon as={MdChevronRight} />} | |
onClick={() => | |
setCurrentDate( | |
new Date( | |
currentDate.getFullYear(), | |
currentDate.getMonth() + 1 | |
) | |
) | |
} | |
/> | |
</Flex> | |
<Flex flexDirection="column"> | |
{calendar.map((week, index) => ( | |
<Flex key={index}> | |
{week.map((day, index) => ( | |
<Box | |
key={index} | |
flex="1" | |
textAlign="center" | |
p={2} | |
bg={ | |
day && (day.getDay() === 0 || day.getDay() === 6) | |
? "yellow.200" | |
: "gray.100" | |
} | |
> | |
{day && day.getDate()} | |
</Box> | |
))} | |
</Flex> | |
))} | |
</Flex> | |
</> | |
)} | |
</Box> | |
); | |
}; | |
return ( | |
<Flex flexDirection="column" alignItems="center"> | |
{renderCalendar()} | |
</Flex> | |
); | |
}; | |
export default DateInput; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment