Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
2595e32f
Commit
2595e32f
authored
May 31, 2025
by
Johnny
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: simplify date editor
parent
673026ff
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
83 additions
and
84 deletions
+83
-84
package.json
web/package.json
+0
-1
pnpm-lock.yaml
web/pnpm-lock.yaml
+0
-41
DateTimeInput.tsx
web/src/components/DateTimeInput.tsx
+49
-0
index.tsx
web/src/components/MemoEditor/index.tsx
+30
-20
MonthNavigator.tsx
web/src/components/StatisticsView/MonthNavigator.tsx
+4
-22
No files found.
web/package.json
View file @
2595e32f
...
@@ -32,7 +32,6 @@
...
@@ -32,7 +32,6 @@
"mobx"
:
"^6.13.7"
,
"mobx"
:
"^6.13.7"
,
"mobx-react-lite"
:
"^4.1.0"
,
"mobx-react-lite"
:
"^4.1.0"
,
"react"
:
"^18.3.1"
,
"react"
:
"^18.3.1"
,
"react-datepicker"
:
"^8.4.0"
,
"react-dom"
:
"^18.3.1"
,
"react-dom"
:
"^18.3.1"
,
"react-force-graph-2d"
:
"^1.27.1"
,
"react-force-graph-2d"
:
"^1.27.1"
,
"react-hot-toast"
:
"^2.5.2"
,
"react-hot-toast"
:
"^2.5.2"
,
...
...
web/pnpm-lock.yaml
View file @
2595e32f
...
@@ -80,9 +80,6 @@ importers:
...
@@ -80,9 +80,6 @@ importers:
react
:
react
:
specifier
:
^18.3.1
specifier
:
^18.3.1
version
:
18.3.1
version
:
18.3.1
react-datepicker
:
specifier
:
^8.4.0
version
:
8.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
react-dom
:
react-dom
:
specifier
:
^18.3.1
specifier
:
^18.3.1
version
:
18.3.1(react@18.3.1)
version
:
18.3.1(react@18.3.1)
...
@@ -1021,12 +1018,6 @@ packages:
...
@@ -1021,12 +1018,6 @@ packages:
react
:
'
>=16.8.0'
react
:
'
>=16.8.0'
react-dom
:
'
>=16.8.0'
react-dom
:
'
>=16.8.0'
'
@floating-ui/react@0.27.9'
:
resolution
:
{
integrity
:
sha512-Y0aCJBNtfVF6ikI1kVzA0WzSAhVBz79vFWOhvb5MLCRNODZ1ylGSLTuncchR7JsLyn9QzV6JD44DyZhhOtvpRw==
}
peerDependencies
:
react
:
'
>=17.0.0'
react-dom
:
'
>=17.0.0'
'
@floating-ui/utils@0.2.9'
:
'
@floating-ui/utils@0.2.9'
:
resolution
:
{
integrity
:
sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==
}
resolution
:
{
integrity
:
sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==
}
...
@@ -2267,9 +2258,6 @@ packages:
...
@@ -2267,9 +2258,6 @@ packages:
resolution
:
{
integrity
:
sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==
}
resolution
:
{
integrity
:
sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==
}
engines
:
{
node
:
'
>=
0.4'
}
engines
:
{
node
:
'
>=
0.4'
}
date-fns@4.1.0
:
resolution
:
{
integrity
:
sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==
}
dayjs@1.11.13
:
dayjs@1.11.13
:
resolution
:
{
integrity
:
sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
}
resolution
:
{
integrity
:
sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==
}
...
@@ -3306,12 +3294,6 @@ packages:
...
@@ -3306,12 +3294,6 @@ packages:
queue-microtask@1.2.3
:
queue-microtask@1.2.3
:
resolution
:
{
integrity
:
sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
}
resolution
:
{
integrity
:
sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
}
react-datepicker@8.4.0
:
resolution
:
{
integrity
:
sha512-6nPDnj8vektWCIOy9ArS3avus9Ndsyz5XgFCJ7nBxXASSpBdSL6lG9jzNNmViPOAOPh6T5oJyGaXuMirBLECag==
}
peerDependencies
:
react
:
^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc
react-dom
:
^16.9.0 || ^17 || ^18 || ^19 || ^19.0.0-rc
react-dom@18.3.1
:
react-dom@18.3.1
:
resolution
:
{
integrity
:
sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
}
resolution
:
{
integrity
:
sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==
}
peerDependencies
:
peerDependencies
:
...
@@ -3695,9 +3677,6 @@ packages:
...
@@ -3695,9 +3677,6 @@ packages:
systemjs@6.15.1
:
systemjs@6.15.1
:
resolution
:
{
integrity
:
sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA==
}
resolution
:
{
integrity
:
sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA==
}
tabbable@6.2.0
:
resolution
:
{
integrity
:
sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==
}
tailwind-merge@2.6.0
:
tailwind-merge@2.6.0
:
resolution
:
{
integrity
:
sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==
}
resolution
:
{
integrity
:
sha512-P+Vu1qXfzediirmHOC3xKGAYeZtPcV9g76X+xg2FD4tYgR71ewMA35Y3sCz3zhiN/dwefRpJX0yBcgwi1fXNQA==
}
...
@@ -4925,14 +4904,6 @@ snapshots:
...
@@ -4925,14 +4904,6 @@ snapshots:
react
:
18.3.1
react
:
18.3.1
react-dom
:
18.3.1(react@18.3.1)
react-dom
:
18.3.1(react@18.3.1)
'
@floating-ui/react@0.27.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)'
:
dependencies
:
'
@floating-ui/react-dom'
:
2.1.2(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'
@floating-ui/utils'
:
0.2.9
react
:
18.3.1
react-dom
:
18.3.1(react@18.3.1)
tabbable
:
6.2.0
'
@floating-ui/utils@0.2.9'
:
{}
'
@floating-ui/utils@0.2.9'
:
{}
'
@github/relative-time-element@4.4.8'
:
{}
'
@github/relative-time-element@4.4.8'
:
{}
...
@@ -6248,8 +6219,6 @@ snapshots:
...
@@ -6248,8 +6219,6 @@ snapshots:
es-errors
:
1.3.0
es-errors
:
1.3.0
is-data-view
:
1.0.2
is-data-view
:
1.0.2
date-fns@4.1.0
:
{}
dayjs@1.11.13
:
{}
dayjs@1.11.13
:
{}
debug@4.4.1
:
debug@4.4.1
:
...
@@ -7407,14 +7376,6 @@ snapshots:
...
@@ -7407,14 +7376,6 @@ snapshots:
queue-microtask@1.2.3
:
{}
queue-microtask@1.2.3
:
{}
react-datepicker@8.4.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
:
dependencies
:
'
@floating-ui/react'
:
0.27.9(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
clsx
:
2.1.1
date-fns
:
4.1.0
react
:
18.3.1
react-dom
:
18.3.1(react@18.3.1)
react-dom@18.3.1(react@18.3.1)
:
react-dom@18.3.1(react@18.3.1)
:
dependencies
:
dependencies
:
loose-envify
:
1.4.0
loose-envify
:
1.4.0
...
@@ -7872,8 +7833,6 @@ snapshots:
...
@@ -7872,8 +7833,6 @@ snapshots:
systemjs@6.15.1
:
{}
systemjs@6.15.1
:
{}
tabbable@6.2.0
:
{}
tailwind-merge@2.6.0
:
{}
tailwind-merge@2.6.0
:
{}
tailwindcss-animate@1.0.7(tailwindcss@3.4.17)
:
tailwindcss-animate@1.0.7(tailwindcss@3.4.17)
:
...
...
web/src/components/DateTimeInput.tsx
0 → 100644
View file @
2595e32f
import
{
isEqual
}
from
"lodash-es"
;
import
toast
from
"react-hot-toast"
;
import
{
cn
}
from
"@/utils"
;
// Helper function to convert Date to local datetime string.
const
toLocalDateTimeString
=
(
date
:
Date
|
undefined
):
string
=>
{
if
(
!
date
)
return
""
;
return
new
Date
(
date
.
getTime
()
-
date
.
getTimezoneOffset
()
*
60000
).
toISOString
().
slice
(
0
,
-
1
);
};
interface
Props
{
label
:
string
;
value
:
Date
|
undefined
;
originalValue
:
Date
|
undefined
;
onChange
:
(
date
:
Date
)
=>
void
;
}
const
DateTimeInput
:
React
.
FC
<
Props
>
=
({
label
,
value
,
originalValue
,
onChange
})
=>
{
return
(
<
div
className=
"w-full flex items-center gap-2"
>
<
span
>
{
label
}
</
span
>
<
input
type=
"text"
className=
{
cn
(
"flex-1 px-1 bg-transparent rounded text-xs transition-all"
,
"border-transparent focus:border-gray-300 dark:focus:border-zinc-700"
,
!
isEqual
(
value
,
originalValue
)
&&
"border-gray-300 dark:border-zinc-700"
,
"border"
,
)
}
defaultValue=
{
toLocalDateTimeString
(
value
)
}
onBlur=
{
(
e
)
=>
{
const
inputValue
=
e
.
target
.
value
;
if
(
inputValue
)
{
const
date
=
new
Date
(
inputValue
);
if
(
!
isNaN
(
date
.
getTime
()))
{
onChange
(
date
);
}
else
{
toast
.
error
(
"Invalid datetime format. Use format: 2023-12-31T23:59:59"
);
e
.
target
.
value
=
toLocalDateTimeString
(
value
);
}
}
}
}
placeholder=
"YYYY-MM-DDTHH:mm:ss"
/>
</
div
>
);
};
export
default
DateTimeInput
;
web/src/components/MemoEditor/index.tsx
View file @
2595e32f
...
@@ -3,7 +3,6 @@ import { isEqual } from "lodash-es";
...
@@ -3,7 +3,6 @@ import { isEqual } from "lodash-es";
import
{
LoaderIcon
,
SendIcon
}
from
"lucide-react"
;
import
{
LoaderIcon
,
SendIcon
}
from
"lucide-react"
;
import
{
observer
}
from
"mobx-react-lite"
;
import
{
observer
}
from
"mobx-react-lite"
;
import
React
,
{
useEffect
,
useMemo
,
useRef
,
useState
}
from
"react"
;
import
React
,
{
useEffect
,
useMemo
,
useRef
,
useState
}
from
"react"
;
import
DatePicker
from
"react-datepicker"
;
import
{
toast
}
from
"react-hot-toast"
;
import
{
toast
}
from
"react-hot-toast"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
useLocalStorage
from
"react-use/lib/useLocalStorage"
;
import
useLocalStorage
from
"react-use/lib/useLocalStorage"
;
...
@@ -19,6 +18,7 @@ import { UserSetting } from "@/types/proto/api/v1/user_service";
...
@@ -19,6 +18,7 @@ import { UserSetting } from "@/types/proto/api/v1/user_service";
import
{
cn
}
from
"@/utils"
;
import
{
cn
}
from
"@/utils"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
convertVisibilityFromString
}
from
"@/utils/memo"
;
import
{
convertVisibilityFromString
}
from
"@/utils/memo"
;
import
DateTimeInput
from
"../DateTimeInput"
;
import
AddMemoRelationPopover
from
"./ActionButton/AddMemoRelationPopover"
;
import
AddMemoRelationPopover
from
"./ActionButton/AddMemoRelationPopover"
;
import
LocationSelector
from
"./ActionButton/LocationSelector"
;
import
LocationSelector
from
"./ActionButton/LocationSelector"
;
import
MarkdownMenu
from
"./ActionButton/MarkdownMenu"
;
import
MarkdownMenu
from
"./ActionButton/MarkdownMenu"
;
...
@@ -30,7 +30,6 @@ import RelationListView from "./RelationListView";
...
@@ -30,7 +30,6 @@ import RelationListView from "./RelationListView";
import
ResourceListView
from
"./ResourceListView"
;
import
ResourceListView
from
"./ResourceListView"
;
import
{
handleEditorKeydownWithMarkdownShortcuts
,
hyperlinkHighlightedText
}
from
"./handlers"
;
import
{
handleEditorKeydownWithMarkdownShortcuts
,
hyperlinkHighlightedText
}
from
"./handlers"
;
import
{
MemoEditorContext
}
from
"./types"
;
import
{
MemoEditorContext
}
from
"./types"
;
import
"react-datepicker/dist/react-datepicker.css"
;
export
interface
Props
{
export
interface
Props
{
className
?:
string
;
className
?:
string
;
...
@@ -71,7 +70,10 @@ const MemoEditor = observer((props: Props) => {
...
@@ -71,7 +70,10 @@ const MemoEditor = observer((props: Props) => {
isComposing
:
false
,
isComposing
:
false
,
isDraggingFile
:
false
,
isDraggingFile
:
false
,
});
});
const
[
displayTime
,
setDisplayTime
]
=
useState
<
Date
|
undefined
>
();
const
[
createTime
,
setCreateTime
]
=
useState
<
Date
|
undefined
>
();
const
[
updateTime
,
setUpdateTime
]
=
useState
<
Date
|
undefined
>
();
const
[
originalCreateTime
,
setOriginalCreateTime
]
=
useState
<
Date
|
undefined
>
();
const
[
originalUpdateTime
,
setOriginalUpdateTime
]
=
useState
<
Date
|
undefined
>
();
const
[
hasContent
,
setHasContent
]
=
useState
<
boolean
>
(
false
);
const
[
hasContent
,
setHasContent
]
=
useState
<
boolean
>
(
false
);
const
[
isVisibilitySelectorOpen
,
setIsVisibilitySelectorOpen
]
=
useState
(
false
);
const
[
isVisibilitySelectorOpen
,
setIsVisibilitySelectorOpen
]
=
useState
(
false
);
const
editorRef
=
useRef
<
EditorRefActions
>
(
null
);
const
editorRef
=
useRef
<
EditorRefActions
>
(
null
);
...
@@ -119,7 +121,10 @@ const MemoEditor = observer((props: Props) => {
...
@@ -119,7 +121,10 @@ const MemoEditor = observer((props: Props) => {
const
memo
=
await
memoStore
.
getOrFetchMemoByName
(
memoName
);
const
memo
=
await
memoStore
.
getOrFetchMemoByName
(
memoName
);
if
(
memo
)
{
if
(
memo
)
{
handleEditorFocus
();
handleEditorFocus
();
setDisplayTime
(
memo
.
displayTime
);
setCreateTime
(
memo
.
createTime
);
setUpdateTime
(
memo
.
updateTime
);
setOriginalCreateTime
(
memo
.
createTime
);
setOriginalUpdateTime
(
memo
.
updateTime
);
setState
((
prevState
)
=>
({
setState
((
prevState
)
=>
({
...
prevState
,
...
prevState
,
memoVisibility
:
memo
.
visibility
,
memoVisibility
:
memo
.
visibility
,
...
@@ -361,9 +366,13 @@ const MemoEditor = observer((props: Props) => {
...
@@ -361,9 +366,13 @@ const MemoEditor = observer((props: Props) => {
if
([
"content"
,
"resources"
,
"relations"
,
"location"
].
some
((
key
)
=>
updateMask
.
has
(
key
)))
{
if
([
"content"
,
"resources"
,
"relations"
,
"location"
].
some
((
key
)
=>
updateMask
.
has
(
key
)))
{
updateMask
.
add
(
"update_time"
);
updateMask
.
add
(
"update_time"
);
}
}
if
(
!
isEqual
(
displayTime
,
prevMemo
.
displayTime
))
{
if
(
createTime
&&
!
isEqual
(
createTime
,
prevMemo
.
createTime
))
{
updateMask
.
add
(
"display_time"
);
updateMask
.
add
(
"create_time"
);
memoPatch
.
displayTime
=
displayTime
;
memoPatch
.
createTime
=
createTime
;
}
if
(
updateTime
&&
!
isEqual
(
updateTime
,
prevMemo
.
updateTime
))
{
updateMask
.
add
(
"update_time"
);
memoPatch
.
updateTime
=
updateTime
;
}
}
if
(
updateMask
.
size
===
0
)
{
if
(
updateMask
.
size
===
0
)
{
toast
.
error
(
"No changes detected"
);
toast
.
error
(
"No changes detected"
);
...
@@ -487,19 +496,6 @@ const MemoEditor = observer((props: Props) => {
...
@@ -487,19 +496,6 @@ const MemoEditor = observer((props: Props) => {
onCompositionStart=
{
handleCompositionStart
}
onCompositionStart=
{
handleCompositionStart
}
onCompositionEnd=
{
handleCompositionEnd
}
onCompositionEnd=
{
handleCompositionEnd
}
>
>
{
memoName
&&
displayTime
&&
(
<
DatePicker
selected=
{
displayTime
}
onChange=
{
(
date
)
=>
date
&&
setDisplayTime
(
date
)
}
showTimeSelect
showMonthDropdown
showYearDropdown
yearDropdownItemNumber=
{
5
}
dateFormatCalendar=
" "
customInput=
{
<
span
className=
"cursor-pointer text-sm text-gray-400 dark:text-gray-500"
>
{
displayTime
.
toLocaleString
()
}
</
span
>
}
calendarClassName=
"ml-24 sm:ml-44"
/>
)
}
<
Editor
ref=
{
editorRef
}
{
...
editorConfig
}
/>
<
Editor
ref=
{
editorRef
}
{
...
editorConfig
}
/>
<
ResourceListView
resourceList=
{
state
.
resourceList
}
setResourceList=
{
handleSetResourceList
}
/>
<
ResourceListView
resourceList=
{
state
.
resourceList
}
setResourceList=
{
handleSetResourceList
}
/>
<
RelationListView
relationList=
{
referenceRelations
}
setRelationList=
{
handleSetRelationList
}
/>
<
RelationListView
relationList=
{
referenceRelations
}
setRelationList=
{
handleSetRelationList
}
/>
...
@@ -547,6 +543,20 @@ const MemoEditor = observer((props: Props) => {
...
@@ -547,6 +543,20 @@ const MemoEditor = observer((props: Props) => {
/>
/>
</
div
>
</
div
>
</
div
>
</
div
>
{
/* Show memo metadata if memoName is provided */
}
{
memoName
&&
(
<
div
className=
"w-full mb-4 text-xs leading-5 px-4 opacity-60 font-mono text-gray-500 dark:text-zinc-500"
>
{
!
isEqual
(
createTime
,
updateTime
)
&&
(
<
DateTimeInput
label=
"Updated"
value=
{
updateTime
}
originalValue=
{
originalUpdateTime
}
onChange=
{
setUpdateTime
}
/>
)
}
<
DateTimeInput
label=
"Created"
value=
{
createTime
}
originalValue=
{
originalCreateTime
}
onChange=
{
setCreateTime
}
/>
<
div
className=
"w-full flex items-center gap-2"
>
<
span
>
ID:
</
span
>
<
span
>
{
memoName
}
</
span
>
</
div
>
</
div
>
)
}
</
MemoEditorContext
.
Provider
>
</
MemoEditorContext
.
Provider
>
);
);
});
});
...
...
web/src/components/StatisticsView/MonthNavigator.tsx
View file @
2595e32f
import
dayjs
from
"dayjs"
;
import
dayjs
from
"dayjs"
;
import
{
ChevronLeftIcon
,
ChevronRightIcon
}
from
"lucide-react"
;
import
{
CalendarIcon
,
ChevronLeftIcon
,
ChevronRightIcon
}
from
"lucide-react"
;
import
DatePicker
from
"react-datepicker"
;
import
i18n
from
"@/i18n"
;
import
i18n
from
"@/i18n"
;
import
type
{
MonthNavigatorProps
}
from
"@/types/statistics"
;
import
type
{
MonthNavigatorProps
}
from
"@/types/statistics"
;
import
"react-datepicker/dist/react-datepicker.css"
;
export
const
MonthNavigator
=
({
visibleMonth
,
onMonthChange
}:
MonthNavigatorProps
)
=>
{
export
const
MonthNavigator
=
({
visibleMonth
,
onMonthChange
}:
MonthNavigatorProps
)
=>
{
const
currentMonth
=
dayjs
(
visibleMonth
).
toDate
();
const
currentMonth
=
dayjs
(
visibleMonth
).
toDate
();
...
@@ -18,25 +16,9 @@ export const MonthNavigator = ({ visibleMonth, onMonthChange }: MonthNavigatorPr
...
@@ -18,25 +16,9 @@ export const MonthNavigator = ({ visibleMonth, onMonthChange }: MonthNavigatorPr
return
(
return
(
<
div
className=
"w-full mb-1 flex flex-row justify-between items-center gap-1"
>
<
div
className=
"w-full mb-1 flex flex-row justify-between items-center gap-1"
>
<
div
className=
"relative text-sm font-medium inline-flex flex-row items-center w-auto dark:text-gray-400"
>
<
div
className=
"relative text-sm inline-flex flex-row items-center w-auto gap-2 dark:text-gray-400"
>
<
DatePicker
<
CalendarIcon
className=
"w-4 h-4"
/>
selected=
{
currentMonth
}
onChange=
{
(
date
)
=>
{
if
(
date
)
{
onMonthChange
(
dayjs
(
date
).
format
(
"YYYY-MM"
));
}
}
}
dateFormat=
"MMMM yyyy"
showMonthYearPicker
showFullMonthYearPicker
customInput=
{
<
span
className=
"cursor-pointer text-base hover:text-gray-600 dark:hover:text-gray-300 transition-colors"
>
{
currentMonth
.
toLocaleString
(
i18n
.
language
,
{
year
:
"numeric"
,
month
:
"long"
})
}
{
currentMonth
.
toLocaleString
(
i18n
.
language
,
{
year
:
"numeric"
,
month
:
"long"
})
}
</
span
>
}
popperPlacement=
"bottom-start"
calendarClassName=
"!bg-white !border-gray-200 !font-normal !shadow-lg"
/>
</
div
>
</
div
>
<
div
className=
"flex justify-end items-center shrink-0 gap-1"
>
<
div
className=
"flex justify-end items-center shrink-0 gap-1"
>
<
button
className=
"p-1 cursor-pointer hover:opacity-80 transition-opacity"
onClick=
{
handlePrevMonth
}
aria
-
label=
"Previous month"
>
<
button
className=
"p-1 cursor-pointer hover:opacity-80 transition-opacity"
onClick=
{
handlePrevMonth
}
aria
-
label=
"Previous month"
>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment