diff --git a/package.json b/package.json
index abf1ade0..1bac513c 100644
--- a/package.json
+++ b/package.json
@@ -58,6 +58,7 @@
"lodash.debounce": "4.0.8",
"path": "0.12.7",
"react": "18.3.1",
+ "react-datepicker": "^7.4.0",
"react-dom": "18.3.1",
"styled-components": "5.3.8",
"styled-normalize": "8.0.7"
diff --git a/src/assets/icons/index.ts b/src/assets/icons/index.ts
index 65995ee1..07037fbf 100644
--- a/src/assets/icons/index.ts
+++ b/src/assets/icons/index.ts
@@ -12,6 +12,7 @@ import { ReactComponent as search } from "./svgs/search.svg";
import { ReactComponent as close } from "./svgs/close.svg";
import { ReactComponent as moon } from "./svgs/moon.svg";
import { ReactComponent as sun } from "./svgs/sun.svg";
+import { ReactComponent as calendar } from "./svgs/calendar.svg";
import { Icon, IconsNames } from "./types";
const icons: { [key in IconsNames]: Icon } = {
@@ -28,7 +29,8 @@ const icons: { [key in IconsNames]: Icon } = {
search,
close,
moon,
- sun
+ sun,
+ calendar
};
export default icons;
diff --git a/src/assets/icons/svgs/calendar.svg b/src/assets/icons/svgs/calendar.svg
new file mode 100644
index 00000000..e6064e00
--- /dev/null
+++ b/src/assets/icons/svgs/calendar.svg
@@ -0,0 +1,12 @@
+
diff --git a/src/assets/icons/types.ts b/src/assets/icons/types.ts
index ae04925a..4fea587f 100644
--- a/src/assets/icons/types.ts
+++ b/src/assets/icons/types.ts
@@ -14,6 +14,7 @@ export type IconsNames =
| "search"
| "close"
| "moon"
- | "sun";
+ | "sun"
+ | "calendar";
export type Icon = FunctionComponent & { title?: string }>;
diff --git a/src/components/Calendar/Header/Topbar/Topbar.tsx b/src/components/Calendar/Header/Topbar/Topbar.tsx
index 6a0ffafc..cbbb8e8c 100644
--- a/src/components/Calendar/Header/Topbar/Topbar.tsx
+++ b/src/components/Calendar/Header/Topbar/Topbar.tsx
@@ -1,5 +1,7 @@
import { useTheme } from "styled-components";
import { FC, MouseEventHandler } from "react";
+import DatePicker from "react-datepicker";
+import dayjs from "dayjs";
import { Icon, IconButton, Toggle } from "@/components";
import { useCalendar } from "@/context/CalendarProvider";
import { useLanguage } from "@/context/LocaleProvider";
@@ -10,7 +12,9 @@ import {
Today,
Zoom,
Filters,
- OptionsContainer
+ OptionsContainer,
+ TodayWrapper,
+ NavCalendarButton
} from "./styles";
import { TopbarProps } from "./types";
@@ -22,6 +26,7 @@ const Topbar: FC = ({ width, showThemeToggle, toggleTheme }) => {
handleGoNext,
handleGoPrev,
handleGoToday,
+ handleGoDate,
zoomIn,
zoomOut,
isNextZoom,
@@ -61,7 +66,18 @@ const Topbar: FC = ({ width, showThemeToggle, toggleTheme }) => {
{topbar.prev}
- {topbar.today}
+
+ {topbar.today}
+ handleGoDate(dayjs(date))}
+ customInput={
+
+
+
+ }
+ />
+
{topbar.next}
diff --git a/src/components/Calendar/Header/Topbar/styles.ts b/src/components/Calendar/Header/Topbar/styles.ts
index 569aff3a..8c73a250 100644
--- a/src/components/Calendar/Header/Topbar/styles.ts
+++ b/src/components/Calendar/Header/Topbar/styles.ts
@@ -25,6 +25,32 @@ export const Wrapper = styled.div`
z-index: 3;
`;
+export const TodayWrapper = styled.div`
+ ${resetBtnStyles};
+ display: flex;
+ align-items: center;
+ position: relative;
+
+ .react-datepicker-wrapper {
+ margin-top: 3px;
+ }
+
+ &::before,
+ &::after {
+ content: "";
+ position: absolute;
+ width: 1px;
+ height: 1.5rem;
+ background-color: ${({ theme }) => theme.colors.textPrimary};
+ }
+ &::before {
+ left: -1.125rem;
+ }
+ &::after {
+ right: -1.125rem;
+ }
+`;
+
export const NavigationWrapper = styled.div`
display: flex;
gap: 1.875rem;
@@ -43,6 +69,13 @@ export const NavBtn = styled.button`
}
`;
+export const NavCalendarButton = styled.button`
+ ${resetBtnStyles};
+ display: flex;
+ align-items: center;
+ cursor: pointer;
+`;
+
export const Today = styled.button`
${resetBtnStyles};
position: relative;
@@ -50,21 +83,6 @@ export const Today = styled.button`
cursor: pointer;
line-height: 1.5rem;
color: ${({ theme }) => theme.colors.textPrimary};
-
- &::before,
- &::after {
- content: "";
- position: absolute;
- width: 1px;
- height: 1.5rem;
- background-color: ${({ theme }) => theme.colors.textPrimary};
- }
- &::before {
- left: -1.125rem;
- }
- &::after {
- right: -1.125rem;
- }
`;
export const Zoom = styled.div`
diff --git a/src/context/CalendarProvider/CalendarProvider.tsx b/src/context/CalendarProvider/CalendarProvider.tsx
index 7953af0b..4178c8f9 100644
--- a/src/context/CalendarProvider/CalendarProvider.tsx
+++ b/src/context/CalendarProvider/CalendarProvider.tsx
@@ -197,6 +197,16 @@ const CalendarProvider = ({
}, 300)();
}, [isLoading, loadMore, moveHorizontalScroll]);
+ const handleGoDate = useCallback(
+ (date: dayjs.Dayjs) => {
+ if (isLoading) return;
+
+ setDate(date);
+ onRangeChange?.(range);
+ },
+ [isLoading, onRangeChange, range]
+ );
+
const zoomIn = () => changeZoom(zoom + 1);
const zoomOut = () => changeZoom(zoom - 1);
@@ -222,6 +232,7 @@ const CalendarProvider = ({
handleGoPrev,
handleScrollPrev,
handleGoToday,
+ handleGoDate,
zoomIn,
zoomOut,
zoom,
diff --git a/src/context/CalendarProvider/calendarContext.tsx b/src/context/CalendarProvider/calendarContext.tsx
index 23086412..823c3961 100644
--- a/src/context/CalendarProvider/calendarContext.tsx
+++ b/src/context/CalendarProvider/calendarContext.tsx
@@ -8,6 +8,7 @@ export const calendarContext = createContext({
handleGoPrev: () => {},
handleScrollPrev: () => {},
handleGoToday: () => {},
+ handleGoDate: () => {},
zoomIn: () => {},
zoomOut: () => {},
handleFilterData: () => {},
diff --git a/src/context/CalendarProvider/types.ts b/src/context/CalendarProvider/types.ts
index f8324b3a..c80cbfdb 100644
--- a/src/context/CalendarProvider/types.ts
+++ b/src/context/CalendarProvider/types.ts
@@ -9,6 +9,7 @@ export type CalendarContextType = {
handleGoPrev: () => void;
handleScrollPrev: () => void;
handleGoToday: () => void;
+ handleGoDate: (date: dayjs.Dayjs) => void;
zoomIn: () => void;
zoomOut: () => void;
handleFilterData: () => void;
diff --git a/src/index.ts b/src/index.ts
index f0349a61..5539f8b8 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,5 +1,6 @@
import { Scheduler } from "./components";
import "./styles.css";
+import "react-datepicker/dist/react-datepicker.css";
export type { SchedulerProps } from "./components/Scheduler/types";
export type { SchedulerData, SchedulerProjectData, ZoomLevel, Config } from "./types/global";
diff --git a/yarn.lock b/yarn.lock
index 063e2a73..8dd4ad12 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -386,6 +386,42 @@
resolved "https://registry.npmjs.org/@faker-js/faker/-/faker-7.6.0.tgz"
integrity sha512-XK6BTq1NDMo9Xqw/YkYyGjSsg44fbNwYRx7QK2CuoQgyy+f1rrTDHoExVM5PsyXCtfl2vs2vVJ0MN0yN6LppRw==
+"@floating-ui/core@^1.6.0":
+ version "1.6.8"
+ resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.8.tgz#aa43561be075815879305965020f492cdb43da12"
+ integrity sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==
+ dependencies:
+ "@floating-ui/utils" "^0.2.8"
+
+"@floating-ui/dom@^1.0.0":
+ version "1.6.11"
+ resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.11.tgz#8631857838d34ee5712339eb7cbdfb8ad34da723"
+ integrity sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==
+ dependencies:
+ "@floating-ui/core" "^1.6.0"
+ "@floating-ui/utils" "^0.2.8"
+
+"@floating-ui/react-dom@^2.1.2":
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.2.tgz#a1349bbf6a0e5cb5ded55d023766f20a4d439a31"
+ integrity sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==
+ dependencies:
+ "@floating-ui/dom" "^1.0.0"
+
+"@floating-ui/react@^0.26.23":
+ version "0.26.24"
+ resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.24.tgz#072b9dfeca4e79ef4e3000ef1c28e0ffc86f4ed4"
+ integrity sha512-2ly0pCkZIGEQUq5H8bBK0XJmc1xIK/RM3tvVzY3GBER7IOD1UgmC2Y2tjj4AuS+TC+vTE1KJv2053290jua0Sw==
+ dependencies:
+ "@floating-ui/react-dom" "^2.1.2"
+ "@floating-ui/utils" "^0.2.8"
+ tabbable "^6.0.0"
+
+"@floating-ui/utils@^0.2.8":
+ version "0.2.8"
+ resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.8.tgz#21a907684723bbbaa5f0974cf7730bd797eb8e62"
+ integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==
+
"@humanwhocodes/config-array@^0.11.8":
version "0.11.8"
resolved "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.8.tgz"
@@ -1141,6 +1177,11 @@ cliui@^8.0.1:
strip-ansi "^6.0.1"
wrap-ansi "^7.0.0"
+clsx@^2.1.1:
+ version "2.1.1"
+ resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
+ integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
+
code-block-writer@^11.0.3:
version "11.0.3"
resolved "https://registry.npmjs.org/code-block-writer/-/code-block-writer-11.0.3.tgz"
@@ -1234,6 +1275,11 @@ csstype@^3.0.2:
resolved "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz"
integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==
+date-fns@^3.6.0:
+ version "3.6.0"
+ resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-3.6.0.tgz#f20ca4fe94f8b754951b24240676e8618c0206bf"
+ integrity sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==
+
dayjs@1.11.7:
version "1.11.7"
resolved "https://registry.npmjs.org/dayjs/-/dayjs-1.11.7.tgz"
@@ -2781,6 +2827,16 @@ queue-microtask@^1.2.2:
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
+react-datepicker@^7.4.0:
+ version "7.4.0"
+ resolved "https://registry.yarnpkg.com/react-datepicker/-/react-datepicker-7.4.0.tgz#127a9c3ce24260f6e21cf4211c910f3eb6d83383"
+ integrity sha512-vSSok4DTZ9/Os8O4HjZLxh4SZVFU6dQvoCX6mfbNdBqMsBBdzftrvMz0Nb4UUVVbgj9o8PfX84K3/31oPrTqmg==
+ dependencies:
+ "@floating-ui/react" "^0.26.23"
+ clsx "^2.1.1"
+ date-fns "^3.6.0"
+ prop-types "^15.8.1"
+
react-dom@18.3.1:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-18.3.1.tgz#c2265d79511b57d479b3dd3fdfa51536494c5cb4"
@@ -3175,6 +3231,11 @@ synckit@^0.8.5:
"@pkgr/utils" "^2.3.1"
tslib "^2.5.0"
+tabbable@^6.0.0:
+ version "6.2.0"
+ resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97"
+ integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==
+
tapable@^2.2.0:
version "2.2.1"
resolved "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz"