1
Fork 0
mirror of https://github.com/Steffo99/todocolors.git synced 2024-10-16 07:17:28 +00:00

Various fixes

This commit is contained in:
Steffo 2023-08-11 19:31:33 +02:00
parent 0c3b44a505
commit ced9053789
Signed by: steffo
GPG key ID: 2A24051445686895
10 changed files with 91 additions and 43 deletions

View file

@ -1,8 +1,10 @@
{
"name": "Todocolors",
"short_name": "Todocolors",
"short_name": "Todo",
"start_url": ".",
"scope": "/",
"display": "standalone",
"theme_color": "#0d193b",
"background_color": "#0c193b",
"description": "Self-hostable multiplayer todo app",
"categories": ["productivity"],

View file

@ -1,5 +1,6 @@
.taskEditorContainer {
display: flex;
flex-direction: column;
justify-content: center;
}
@ -8,8 +9,6 @@
align-items: center;
border-style: dashed;
width: 100%;
max-width: 480px;
height: 100%;
}

View file

@ -36,6 +36,7 @@
.titleArea {
grid-area: title;
height: 72px;
}
.titleDisplay {

View file

@ -22,12 +22,12 @@ interface BoardHeaderProps {
export function BoardHeader({lang, className, metadataHook, layoutHook: {columningHook, groupingHook, sortingHook}}: BoardHeaderProps) {
return (
<header className={cn(style.boardHeader, className)}>
<BoardHeaderTitle className={style.titleArea} editorHook={metadataHook}/>
<div className={cn(style.buttonsArea, style.leftButtonsArea)}>
<NavigateHomeButton lang={lang}/>
<ToggleStarredButton lang={lang}/>
<ToggleEditingButton lang={lang} metadataHook={metadataHook}/>
</div>
<BoardHeaderTitle className={style.titleArea} editorHook={metadataHook}/>
<div className={cn(style.buttonsArea, style.rightButtonsArea)}>
<CycleColumningButton lang={lang} value={columningHook.value} next={columningHook.next}/>
<CycleGroupingButton lang={lang} next={groupingHook.next}/>

View file

@ -18,5 +18,9 @@
}
.taskViewerBack {
flex-direction: row-reverse;
justify-content: end;
}
.taskViewerDebug {
font-size: xx-small;
}

View file

@ -9,12 +9,23 @@ import {TaskWithId} from "@/app/[lang]/board/[board]/(page)/(view)/(task)/TaskWi
import {faTrashArrowUp} from "@fortawesome/free-solid-svg-icons"
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
import cn from "classnames"
import {Dispatch, MouseEvent, SetStateAction, useCallback, useState} from "react"
import {Dispatch, SyntheticEvent, SetStateAction, useCallback, useState} from "react"
export function TaskViewer({lang, task, setEditorInput}: {lang: string, task: TaskWithId, setEditorInput: Dispatch<SetStateAction<string>>}) {
const [isFlipped, setFlipped] = useState<boolean>(false)
const toggleFlipped = useCallback((e: SyntheticEvent<HTMLElement>) => {
if("key" in e && typeof e["key"] === "string") {
if(!["Enter", " "].includes(e.key)) {
return;
}
}
e.preventDefault()
e.stopPropagation()
setFlipped(prev => !prev)
}, [])
return (
<div
className={cn({
@ -23,17 +34,23 @@ export function TaskViewer({lang, task, setEditorInput}: {lang: string, task: Ta
[style.taskViewerFront]: !isFlipped,
[style.taskViewerBack]: isFlipped,
}, taskClassNames(task[1]))}
onClick={() => setFlipped(prev => !prev)}
onClick={toggleFlipped}
onKeyDownCapture={toggleFlipped}
>
{isFlipped ? <TaskViewerBack lang={lang} task={task} setEditorInput={setEditorInput}/> : <TaskViewerFront lang={lang} task={task}/>}
</div>
)
}
function TaskViewerFront({lang, task}: {lang: string, task: TaskWithId}) {
function TaskViewerFront({task}: {lang: string, task: TaskWithId}) {
const {sendRequest} = useBoardConsumer()
const toggleStatus = useCallback((e: MouseEvent<HTMLDivElement>) => {
const toggleStatus = useCallback((e: SyntheticEvent<HTMLDivElement>) => {
if("key" in e && typeof e["key"] === "string") {
if(!["Enter", " "].includes(e.key)) {
return;
}
}
e.preventDefault()
e.stopPropagation()
let request: ModifyTaskBoardRequest
@ -52,7 +69,7 @@ function TaskViewerFront({lang, task}: {lang: string, task: TaskWithId}) {
}, [task, sendRequest])
return <>
<div className={style.taskIcon} onClick={toggleStatus} tabIndex={0}>
<div className={style.taskIcon} onClick={toggleStatus} onKeyDown={toggleStatus} tabIndex={0}>
<FontAwesomeIcon
size={"lg"}
icon={task[1].status === TaskStatus.Complete ? TASK_ICON_TO_FONTAWESOME_SOLID[task[1].icon] : TASK_ICON_TO_FONTAWESOME_REGULAR[task[1].icon]}
@ -69,7 +86,12 @@ function TaskViewerBack({lang, task, setEditorInput}: {lang: string, task: TaskW
const {t} = useClientTranslation(lang, "board")
const {sendRequest} = useBoardConsumer()
const recreateTask = useCallback((e: MouseEvent<HTMLButtonElement>) => {
const recreateTask = useCallback((e: SyntheticEvent<HTMLButtonElement>) => {
if("key" in e && typeof e["key"] === "string") {
if(!["Enter", " "].includes(e.key)) {
return;
}
}
e.preventDefault()
e.stopPropagation()
setEditorInput(taskToString(task[1]))
@ -78,8 +100,11 @@ function TaskViewerBack({lang, task, setEditorInput}: {lang: string, task: TaskW
}, [task, setEditorInput, sendRequest])
return <>
<div className={style.taskButtons}>
<button title={t("taskButtonRecreate")} onClick={recreateTask}>
<div className={style.taskViewerDebug}>
{task[0]}
</div>
<div className={style.taskViewerButtons}>
<button title={t("taskButtonRecreate")} onClick={recreateTask} onKeyDown={recreateTask} tabIndex={0}>
<FontAwesomeIcon size={"sm"} icon={faTrashArrowUp}/>
</button>
</div>

View file

@ -0,0 +1,40 @@
"use client";
import {TaskEditor} from "@/app/[lang]/board/[board]/(page)/(edit)/TaskEditor"
import {BoardHeader} from "@/app/[lang]/board/[board]/(page)/(header)/BoardHeader"
import {BoardMain} from "@/app/[lang]/board/[board]/(page)/(view)/BoardMain"
import {useBoardLayoutEditor} from "@/app/[lang]/board/[board]/(page)/useBoardLayoutEditor"
import {useBoardMetadataEditor} from "@/app/[lang]/board/[board]/(page)/useBoardMetadataEditor"
import {useTaskEditor} from "@/app/[lang]/board/[board]/(page)/useTaskEditor"
import style from "@/app/[lang]/board/[board]/page.module.css"
export function BoardPage({lang}: {lang: string}) {
const metadataHook = useBoardMetadataEditor()
const layoutHook = useBoardLayoutEditor()
const editorHook = useTaskEditor()
return (
<div className={style.pageRoot}>
<BoardHeader
lang={lang}
className={style.pageHeader}
metadataHook={metadataHook}
layoutHook={layoutHook}
/>
<BoardMain
lang={lang}
className={style.pageMain}
columning={layoutHook.columningHook.value}
grouping={layoutHook.groupingHook.value}
sorting={layoutHook.sortingHook.value}
setEditorInput={editorHook.setInput}
/>
<TaskEditor
lang={lang}
className={style.pageEditor}
editorHook={editorHook}
/>
</div>
)
}

View file

@ -6,7 +6,8 @@
"main"
"editor"
;
grid-template-rows: 72px 1fr 48px;
grid-template-columns: 1fr;
grid-template-rows: auto 1fr 48px;
grid-row-gap: 8px;
justify-content: stretch;
@ -30,6 +31,4 @@
.pageEditor {
grid-area: editor;
min-height: 44px;
}

View file

@ -1,39 +1,16 @@
"use client";
import {TaskEditor} from "@/app/[lang]/board/[board]/(page)/(edit)/TaskEditor"
import {BoardPage} from "@/app/[lang]/board/[board]/(page)/BoardPage"
import {useBoardLayoutEditor} from "@/app/[lang]/board/[board]/(page)/useBoardLayoutEditor"
import {useBoardMetadataEditor} from "@/app/[lang]/board/[board]/(page)/useBoardMetadataEditor"
import {BoardMain} from "@/app/[lang]/board/[board]/(page)/(view)/BoardMain"
import {BoardHeader} from "@/app/[lang]/board/[board]/(page)/(header)/BoardHeader"
import {useTaskEditor} from "@/app/[lang]/board/[board]/(page)/useTaskEditor"
import {Metadata} from "next"
import style from "./page.module.css"
export default function page({params: {lang}}: {params: {lang: string}}) {
const metadataHook = useBoardMetadataEditor()
const layoutHook = useBoardLayoutEditor()
const editorHook = useTaskEditor()
return (
<div className={style.pageRoot}>
<BoardHeader
lang={lang}
className={style.pageHeader}
metadataHook={metadataHook}
layoutHook={layoutHook}
/>
<BoardMain
lang={lang}
className={style.pageMain}
columning={layoutHook.columningHook.value}
grouping={layoutHook.groupingHook.value}
sorting={layoutHook.sortingHook.value}
setEditorInput={editorHook.setInput}
/>
<TaskEditor
lang={lang}
className={style.pageEditor}
editorHook={editorHook}
/>
</div>
<BoardPage lang={lang}/>
)
}

View file

@ -18,7 +18,8 @@ export const metadata: NextMetadata = {
creator: "Steffo",
robots: "noindex, nofollow",
manifest: "manifest.json",
icons: "favicon-wbg.ico"
icons: "favicon-wbg.ico",
themeColor: "#0d193b"
}
export default function layout({children}: { children: ReactNode }) {