-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e1361de
commit a0afc6a
Showing
4 changed files
with
278 additions
and
101 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
import { | ||
IonButton, | ||
IonButtons, | ||
IonContent, | ||
IonHeader, | ||
IonIcon, | ||
IonInput, | ||
IonPage, | ||
IonTextarea, | ||
IonTitle, | ||
IonToolbar, | ||
useIonModal, | ||
} from '@ionic/react' | ||
import { openOutline } from 'ionicons/icons' | ||
import { useCallback, useEffect, useRef, useState } from 'react' | ||
import useNoteProvider from '../notes/useNoteProvider' | ||
import { CreatedTodo, db } from '../db' | ||
import useSelectedTodo from './SelectedTodo' | ||
|
||
export function EditTodoModal({ | ||
dismiss, | ||
todo, | ||
}: { | ||
dismiss: (data?: any, role?: string) => void | ||
todo: CreatedTodo | ||
}) { | ||
const page = useRef<HTMLIonModalElement>(null) | ||
const input = useRef<HTMLIonInputElement>(null) | ||
const noteInput = useRef<HTMLIonTextareaElement>(null) | ||
|
||
useEffect(() => { | ||
input.current?.setFocus() | ||
}, []) | ||
|
||
const noteProvider = useNoteProvider() | ||
|
||
useEffect(() => { | ||
const handleKeyDown = (event: KeyboardEvent) => { | ||
if (event.key === 'Enter') { | ||
event.preventDefault() | ||
dismiss( | ||
{ | ||
title: input.current?.value, | ||
note: noteInput.current?.value, | ||
}, | ||
'confirm', | ||
) | ||
} | ||
} | ||
page.current?.addEventListener('keydown', handleKeyDown) | ||
return () => { | ||
page.current?.removeEventListener('keydown', handleKeyDown) | ||
} | ||
}, [dismiss]) | ||
|
||
return ( | ||
<IonPage ref={page}> | ||
<IonHeader> | ||
<IonToolbar> | ||
<IonTitle>Edit todo</IonTitle> | ||
<IonButtons slot="secondary"> | ||
<IonButton | ||
role="cancel" | ||
onClick={() => dismiss(null, 'cancel')} | ||
> | ||
Cancel | ||
</IonButton> | ||
</IonButtons> | ||
<IonButtons slot="primary"> | ||
<IonButton | ||
onClick={() => { | ||
dismiss( | ||
{ | ||
...todo, | ||
title: input.current?.value, | ||
note: noteInput.current?.value, | ||
}, | ||
'confirm', | ||
) | ||
}} | ||
strong={true} | ||
> | ||
Confirm | ||
</IonButton> | ||
</IonButtons> | ||
</IonToolbar> | ||
</IonHeader> | ||
<IonContent className="space-y-4 ion-padding"> | ||
<IonInput | ||
fill="outline" | ||
ref={input} | ||
type="text" | ||
label="Title" | ||
labelPlacement="floating" | ||
value={todo?.title} | ||
/> | ||
{!noteProvider && ( | ||
<p>Set a note provider in settings to enable this feature.</p> | ||
)} | ||
{todo?.note ? ( | ||
<div> | ||
<a | ||
className="space-x-1" | ||
href={todo?.note?.uri} | ||
target="_blank" | ||
rel="noreferrer" | ||
> | ||
<span>Open note</span> | ||
<IonIcon icon={openOutline} /> | ||
</a> | ||
</div> | ||
) : ( | ||
<IonTextarea | ||
className="h-48" | ||
disabled={!noteProvider} | ||
helperText="A note with this initial content will be created with your note provider and linked to this todo." | ||
fill="outline" | ||
label="Note" | ||
labelPlacement="floating" | ||
placeholder="Write markdown here..." | ||
ref={noteInput} | ||
/> | ||
)} | ||
</IonContent> | ||
</IonPage> | ||
) | ||
} | ||
|
||
export function useEditTodoModal() { | ||
const [todo, setTodo] = useSelectedTodo() | ||
const [present, dismiss] = useIonModal(EditTodoModal, { | ||
dismiss: (data: string, role: string) => dismiss(data, role), | ||
todo, | ||
}) | ||
const noteProvider = useNoteProvider() | ||
const editTodo = useCallback( | ||
async (updatedTodo: CreatedTodo) => { | ||
let uri | ||
if (updatedTodo.note && noteProvider) { | ||
uri = await noteProvider.create({ content: updatedTodo.note }) | ||
} | ||
await db.todos.update(updatedTodo.id, { | ||
createdAt: new Date(), | ||
title: updatedTodo.title, | ||
...(uri && { note: { uri } }), | ||
}) | ||
}, | ||
[noteProvider], | ||
) | ||
|
||
return [ | ||
(todo: CreatedTodo) => { | ||
present({ | ||
onWillPresent: () => { | ||
setTodo(todo) | ||
}, | ||
onWillDismiss: event => { | ||
const todo = event.detail.data | ||
if (event.detail.role === 'confirm') editTodo(todo) | ||
setTodo(null) | ||
}, | ||
}) | ||
}, | ||
dismiss, | ||
] | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { | ||
createContext, | ||
Dispatch, | ||
SetStateAction, | ||
useContext, | ||
useState, | ||
} from 'react' | ||
import { CreatedTodo } from '../db' | ||
|
||
export const SelecteTodoContext = createContext< | ||
[ | ||
todo: CreatedTodo | null, | ||
setTodo: Dispatch<SetStateAction<CreatedTodo | null>>, | ||
] | ||
>([null, () => null]) | ||
|
||
export function SelectedTodoProvider({ | ||
children, | ||
}: { | ||
children: React.ReactNode | ||
}) { | ||
const [todo, setTodo] = useState<CreatedTodo | null>(null) | ||
|
||
return ( | ||
<SelecteTodoContext.Provider value={[todo, setTodo]}> | ||
{children} | ||
</SelecteTodoContext.Provider> | ||
) | ||
} | ||
|
||
export default function useSelectedTodo() { | ||
return useContext(SelecteTodoContext) | ||
} |
Oops, something went wrong.