1
Fork 0
mirror of https://github.com/Steffo99/todocolors.git synced 2024-11-25 09:44:18 +00:00

Complete functionality i guess

This commit is contained in:
Steffo 2023-08-04 16:41:33 +02:00
parent b73dc41b70
commit 0b0999d338
Signed by: steffo
GPG key ID: 2A24051445686895
15 changed files with 217 additions and 47 deletions

View file

@ -0,0 +1,7 @@
.appBody {
min-width: 100svw;
min-height: 100svh;
width: 100svw;
height: 100svh;
}

View file

@ -0,0 +1,11 @@
import {ReactNode} from "react"
import style from "./AppBody.module.css"
export function AppBody({children}: {children: ReactNode}) {
return (
<body className={style.appBody}>
{children}
</body>
)
}

View file

@ -9,7 +9,9 @@ export function BoardColumn({taskGroup}: {taskGroup: TaskGroup}) {
<h3> <h3>
{taskGroup.name} {taskGroup.name}
</h3> </h3>
{taskGroup.tasks.map(task => <TaskDisplay task={task}/>)} <div>
{taskGroup.tasks.map(task => <TaskDisplay task={task}/>)}
</div>
</div> </div>
) )
} }

View file

@ -7,11 +7,11 @@ import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
import cn from "classnames" import cn from "classnames"
export function BoardHeader() { export function BoardHeader({className}: {className?: string}) {
const {isEditingTitle} = useManagedBoard(); const {isEditingTitle} = useManagedBoard();
return ( return (
<header className={style.boardHeader}> <header className={cn(style.boardHeader, className)}>
<TitleArea> <TitleArea>
{isEditingTitle ? <TitleInput/> : <TitleDisplay/>} {isEditingTitle ? <TitleInput/> : <TitleDisplay/>}
</TitleArea> </TitleArea>
@ -36,16 +36,18 @@ function TitleArea({children}: {children: ReactNode}) {
} }
function TitleInput() { function TitleInput() {
const {editTitle, setEditTitle} = useManagedBoard() const {editTitle, setEditTitle, stopEditingTitle} = useManagedBoard()
return ( return (
<input <form onSubmit={stopEditingTitle}>
className={style.titleInput} <input
type={"text"} className={style.titleInput}
placeholder={"Titolo"} type={"text"}
onChange={(e) => setEditTitle(e.target.value)} placeholder={"Titolo"}
value={editTitle} onChange={(e) => setEditTitle(e.target.value)}
/> value={editTitle}
/>
</form>
) )
} }

View file

@ -1,22 +1,23 @@
import {BoardMainTaskGroups} from "@/app/board/[board]/BoardMainTaskGroups"
import {BoardMainIcon} from "@/app/board/[board]/BoardMainIcon" import {BoardMainIcon} from "@/app/board/[board]/BoardMainIcon"
import {BoardMainTaskGroups} from "@/app/board/[board]/BoardMainTaskGroups"
import {useManagedBoard} from "@/app/board/[board]/BoardManager" import {useManagedBoard} from "@/app/board/[board]/BoardManager"
import {faArrowsSpin, faExclamationCircle, faGear} from "@fortawesome/free-solid-svg-icons"
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome" import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
import {faGear, faArrowsSpin, faExclamationCircle} from "@fortawesome/free-solid-svg-icons" import cn from "classnames"
export function BoardMain() { export function BoardMain({className}: {className?: string}) {
const {websocketState} = useManagedBoard() const {websocketState} = useManagedBoard()
switch(websocketState) { switch(websocketState) {
case undefined: case undefined:
return <BoardMainIcon icon={<FontAwesomeIcon size={"4x"} icon={faGear} spin/>} text={"Caricamento..."}/> return <BoardMainIcon icon={<FontAwesomeIcon size={"4x"} icon={faGear} spin/>} text={"Caricamento..."} className={className}/>
case WebSocket.CONNECTING: case WebSocket.CONNECTING:
return <BoardMainIcon icon={<FontAwesomeIcon size={"4x"} icon={faArrowsSpin} spin/>} text={"Connessione..."}/> return <BoardMainIcon icon={<FontAwesomeIcon size={"4x"} icon={faArrowsSpin} spin/>} text={"Connessione..."} className={className}/>
case WebSocket.OPEN: case WebSocket.OPEN:
return <BoardMainTaskGroups/> return <BoardMainTaskGroups className={className}/>
case WebSocket.CLOSING: case WebSocket.CLOSING:
case WebSocket.CLOSED: case WebSocket.CLOSED:
return <BoardMainIcon icon={<FontAwesomeIcon size={"4x"} icon={faExclamationCircle}/>} text={"Errore"} className={"red"}/> return <BoardMainIcon icon={<FontAwesomeIcon size={"4x"} icon={faExclamationCircle}/>} text={"Errore"} className={cn("red", className)}/>
} }
} }

View file

@ -1,11 +1,21 @@
.boardMainTaskGroups { .boardMainTaskGroups {
display: flex; display: flex;
gap: 8px; gap: 8px;
justify-content: center; justify-content: start;
flex-wrap: wrap; flex-wrap: nowrap;
overflow-x: scroll;
overflow-y: hidden;
} }
.boardMainTaskGroups > div { .boardMainTaskGroups > div {
flex-basis: 240px; flex-basis: 240px;
flex-shrink: 0; flex-shrink: 0;
} }
.boardMainTaskGroups > div > div {
display: flex;
flex-direction: column;
gap: 8px;
overflow-y: scroll;
}

View file

@ -1,13 +1,14 @@
import {BoardColumn} from "@/app/board/[board]/BoardColumn" import {BoardColumn} from "@/app/board/[board]/BoardColumn"
import {useManagedBoard} from "@/app/board/[board]/BoardManager" import {useManagedBoard} from "@/app/board/[board]/BoardManager"
import cn from "classnames"
import style from "./BoardMainTaskGroups.module.css" import style from "./BoardMainTaskGroups.module.css"
export function BoardMainTaskGroups() { export function BoardMainTaskGroups({className}: {className?: string}) {
const {taskGroups} = useManagedBoard() const {taskGroups} = useManagedBoard()
return ( return (
<main className={style.boardMainTaskGroups}> <main className={cn(style.boardMainTaskGroups, className)}>
{taskGroups.map((tg) => <BoardColumn taskGroup={tg}/>)} {taskGroups.map((tg) => <BoardColumn taskGroup={tg}/>)}
</main> </main>
) )

View file

@ -0,0 +1,14 @@
.editorForm {
display: flex;
flex-direction: row;
}
.editorTextInput {
width: 100%;
height: 100%;
}
.editorSubmitButton {
width: 44px;
height: 44px;
}

View file

@ -0,0 +1,46 @@
import {useManagedBoard} from "@/app/board/[board]/BoardManager"
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
import cn from "classnames"
import {FormEvent, useCallback} from "react"
import style from "./BoardTaskEditor.module.css"
import {faAdd} from "@fortawesome/free-solid-svg-icons"
export function BoardTaskEditor({className}: {className?: string}) {
const {editedTask, send, setEditedTaskText} = useManagedBoard()
const submitTask = useCallback((e: FormEvent) => {
e.preventDefault();
send({"Task": [null, editedTask]});
setEditedTaskText("")
}, [send, editedTask])
return (
<form onSubmit={submitTask} className={cn(style.editorForm, className)}>
<EditorTextInput/>
<EditorSubmitButton/>
</form>
)
}
function EditorTextInput() {
const {editedTaskText, setEditedTaskText} = useManagedBoard();
return (
<input
type={"text"}
placeholder={"What to do...?"}
value={editedTaskText}
onChange={(e) => setEditedTaskText(e.target.value)}
className={style.editorTextInput}
/>
)
}
function EditorSubmitButton() {
return (
<button className={style.editorSubmitButton} title={"Crea"}>
<FontAwesomeIcon icon={faAdd}/>
</button>
)
}

View file

@ -0,0 +1,35 @@
.pageRoot {
display: grid;
grid-template-areas:
"header"
"main"
"editor"
;
grid-template-rows: auto 1fr 44px;
grid-row-gap: 8px;
justify-content: stretch;
align-items: stretch;
width: 100%;
height: 100%;
padding: 8px;
}
.pageHeader {
grid-area: header;
}
.pageMain {
grid-area: main;
overflow-x: scroll;
}
.pageEditor {
grid-area: editor;
min-height: 44px;
}

View file

@ -3,15 +3,18 @@
import {BoardMain} from "@/app/board/[board]/BoardMain" import {BoardMain} from "@/app/board/[board]/BoardMain"
import {BoardManager} from "@/app/board/[board]/BoardManager" import {BoardManager} from "@/app/board/[board]/BoardManager"
import {BoardHeader} from "@/app/board/[board]/BoardHeader" import {BoardHeader} from "@/app/board/[board]/BoardHeader"
import {BoardTaskEditForm} from "@/app/board/[board]/BoardTaskEditForm" import {BoardTaskEditor} from "@/app/board/[board]/BoardTaskEditor"
import style from "./page.module.css"
export default function Page({params: {board}}: {params: {board: string}}) { export default function Page({params: {board}}: {params: {board: string}}) {
return ( return (
<BoardManager name={board}> <BoardManager name={board}>
<BoardHeader/> <div className={style.pageRoot}>
<BoardMain/> <BoardHeader className={style.pageHeader}/>
<BoardTaskEditForm/> <BoardMain className={style.pageMain}/>
<BoardTaskEditor className={style.pageEditor}/>
</div>
</BoardManager> </BoardManager>
) )
} }

View file

@ -0,0 +1,6 @@
@import "@steffo/bluelib/dist/base.root.css";
@import "@steffo/bluelib/dist/classic.root.css";
@import "@steffo/bluelib/dist/glass.root.css";
@import "@steffo/bluelib/dist/colors-royalblue.root.css";
@import "@steffo/bluelib/dist/fonts-fira-ghpages.root.css";
@import '@fortawesome/fontawesome-svg-core/styles.css';

View file

@ -1,12 +1,7 @@
// noinspection JSUnusedGlobalSymbols // noinspection JSUnusedGlobalSymbols
import "@steffo/bluelib/dist/base.root.css" import "./layout.css";
import "@steffo/bluelib/dist/classic.root.css" import {AppBody} from "@/app/AppBody"
import "@steffo/bluelib/dist/glass.root.css"
import "@steffo/bluelib/dist/layouts-center.root.css"
import "@steffo/bluelib/dist/colors-royalblue.root.css"
import "@steffo/bluelib/dist/fonts-fira-ghpages.root.css"
import '@fortawesome/fontawesome-svg-core/styles.css';
import { config } from '@fortawesome/fontawesome-svg-core'; import { config } from '@fortawesome/fontawesome-svg-core';
config.autoAddCss = false; /* eslint-disable import/first */ config.autoAddCss = false; /* eslint-disable import/first */
@ -23,17 +18,9 @@ export const metadata: NextMetadata = {
export default function RootLayout({children}: { children: ReactNode }) { export default function RootLayout({children}: { children: ReactNode }) {
return ( return (
<html lang="en"> <html lang="en">
<body className={"theme-bluelib layout-center"}> <AppBody>
{children} {children}
<footer> </AppBody>
<p>
© <a href="https://steffo.eu">Stefano Pigozzi</a> -
<a href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPL 3.0</a> -
<a href="https://github.com/Steffo99/todocolors">GitHub</a> -
Using {process.env.NEXT_PUBLIC_API_BASE_URL}
</p>
</footer>
</body>
</html> </html>
) )
} }

View file

@ -0,0 +1,19 @@
.pageRoot {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-between;
align-items: center;
padding: 8px;
}
.pageMain h2 {
margin-top: 0;
}
.pageMain div {
max-width: 960px;
}

View file

@ -1,15 +1,29 @@
import {CreatePrivateBoardPanel} from "@/app/CreatePrivateBoardPanel" import {CreatePrivateBoardPanel} from "@/app/CreatePrivateBoardPanel"
import {CreatePublicBoardPanel} from "@/app/CreatePublicBoardPanel" import {CreatePublicBoardPanel} from "@/app/CreatePublicBoardPanel"
import {default as React} from "react"; import {default as React} from "react";
import style from "./page.module.css"
export default function Page() { export default function Page() {
return <> return <div className={style.pageRoot}>
<header> <PageHeader/>
<PageMain/>
<PageFooter/>
</div>
}
function PageHeader() {
return (
<header className={style.pageHeader}>
<h1> <h1>
{process.env.NEXT_PUBLIC_SITE_NAME ?? "Todoblue"} {process.env.NEXT_PUBLIC_SITE_NAME ?? "Todoblue"}
</h1> </h1>
</header> </header>
<main> )
}
function PageMain() {
return (
<main className={style.pageMain}>
<div className={"chapter-2"}> <div className={"chapter-2"}>
<h2> <h2>
Crea un nuovo tabellone Crea un nuovo tabellone
@ -18,5 +32,17 @@ export default function Page() {
<CreatePrivateBoardPanel/> <CreatePrivateBoardPanel/>
</div> </div>
</main> </main>
</> )
}
function PageFooter() {
return (
<footer className={style.pageFooter}>
<p>
© <a href="https://steffo.eu">Stefano Pigozzi</a> -
<a href="https://www.gnu.org/licenses/agpl-3.0.en.html">AGPL 3.0</a> -
<a href="https://github.com/Steffo99/todocolors">GitHub</a>
</p>
</footer>
)
} }