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:
parent
b73dc41b70
commit
0b0999d338
15 changed files with 217 additions and 47 deletions
7
todoblue/src/app/AppBody.module.css
Normal file
7
todoblue/src/app/AppBody.module.css
Normal file
|
@ -0,0 +1,7 @@
|
|||
.appBody {
|
||||
min-width: 100svw;
|
||||
min-height: 100svh;
|
||||
|
||||
width: 100svw;
|
||||
height: 100svh;
|
||||
}
|
11
todoblue/src/app/AppBody.tsx
Normal file
11
todoblue/src/app/AppBody.tsx
Normal 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>
|
||||
)
|
||||
}
|
|
@ -9,7 +9,9 @@ export function BoardColumn({taskGroup}: {taskGroup: TaskGroup}) {
|
|||
<h3>
|
||||
{taskGroup.name}
|
||||
</h3>
|
||||
<div>
|
||||
{taskGroup.tasks.map(task => <TaskDisplay task={task}/>)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,11 +7,11 @@ import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
|
|||
import cn from "classnames"
|
||||
|
||||
|
||||
export function BoardHeader() {
|
||||
export function BoardHeader({className}: {className?: string}) {
|
||||
const {isEditingTitle} = useManagedBoard();
|
||||
|
||||
return (
|
||||
<header className={style.boardHeader}>
|
||||
<header className={cn(style.boardHeader, className)}>
|
||||
<TitleArea>
|
||||
{isEditingTitle ? <TitleInput/> : <TitleDisplay/>}
|
||||
</TitleArea>
|
||||
|
@ -36,9 +36,10 @@ function TitleArea({children}: {children: ReactNode}) {
|
|||
}
|
||||
|
||||
function TitleInput() {
|
||||
const {editTitle, setEditTitle} = useManagedBoard()
|
||||
const {editTitle, setEditTitle, stopEditingTitle} = useManagedBoard()
|
||||
|
||||
return (
|
||||
<form onSubmit={stopEditingTitle}>
|
||||
<input
|
||||
className={style.titleInput}
|
||||
type={"text"}
|
||||
|
@ -46,6 +47,7 @@ function TitleInput() {
|
|||
onChange={(e) => setEditTitle(e.target.value)}
|
||||
value={editTitle}
|
||||
/>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
import {BoardMainTaskGroups} from "@/app/board/[board]/BoardMainTaskGroups"
|
||||
import {BoardMainIcon} from "@/app/board/[board]/BoardMainIcon"
|
||||
import {BoardMainTaskGroups} from "@/app/board/[board]/BoardMainTaskGroups"
|
||||
import {useManagedBoard} from "@/app/board/[board]/BoardManager"
|
||||
import {faArrowsSpin, faExclamationCircle, faGear} from "@fortawesome/free-solid-svg-icons"
|
||||
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()
|
||||
|
||||
switch(websocketState) {
|
||||
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:
|
||||
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:
|
||||
return <BoardMainTaskGroups/>
|
||||
return <BoardMainTaskGroups className={className}/>
|
||||
case WebSocket.CLOSING:
|
||||
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)}/>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,21 @@
|
|||
.boardMainTaskGroups {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
justify-content: start;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
overflow-x: scroll;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.boardMainTaskGroups > div {
|
||||
flex-basis: 240px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.boardMainTaskGroups > div > div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
import {BoardColumn} from "@/app/board/[board]/BoardColumn"
|
||||
import {useManagedBoard} from "@/app/board/[board]/BoardManager"
|
||||
import cn from "classnames"
|
||||
import style from "./BoardMainTaskGroups.module.css"
|
||||
|
||||
|
||||
export function BoardMainTaskGroups() {
|
||||
export function BoardMainTaskGroups({className}: {className?: string}) {
|
||||
const {taskGroups} = useManagedBoard()
|
||||
|
||||
return (
|
||||
<main className={style.boardMainTaskGroups}>
|
||||
<main className={cn(style.boardMainTaskGroups, className)}>
|
||||
{taskGroups.map((tg) => <BoardColumn taskGroup={tg}/>)}
|
||||
</main>
|
||||
)
|
||||
|
|
14
todoblue/src/app/board/[board]/BoardTaskEditor.module.css
Normal file
14
todoblue/src/app/board/[board]/BoardTaskEditor.module.css
Normal file
|
@ -0,0 +1,14 @@
|
|||
.editorForm {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.editorTextInput {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.editorSubmitButton {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
46
todoblue/src/app/board/[board]/BoardTaskEditor.tsx
Normal file
46
todoblue/src/app/board/[board]/BoardTaskEditor.tsx
Normal 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>
|
||||
)
|
||||
}
|
35
todoblue/src/app/board/[board]/page.module.css
Normal file
35
todoblue/src/app/board/[board]/page.module.css
Normal 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;
|
||||
}
|
|
@ -3,15 +3,18 @@
|
|||
import {BoardMain} from "@/app/board/[board]/BoardMain"
|
||||
import {BoardManager} from "@/app/board/[board]/BoardManager"
|
||||
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}}) {
|
||||
return (
|
||||
<BoardManager name={board}>
|
||||
<BoardHeader/>
|
||||
<BoardMain/>
|
||||
<BoardTaskEditForm/>
|
||||
<div className={style.pageRoot}>
|
||||
<BoardHeader className={style.pageHeader}/>
|
||||
<BoardMain className={style.pageMain}/>
|
||||
<BoardTaskEditor className={style.pageEditor}/>
|
||||
</div>
|
||||
</BoardManager>
|
||||
)
|
||||
}
|
||||
|
|
6
todoblue/src/app/layout.css
Normal file
6
todoblue/src/app/layout.css
Normal 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';
|
|
@ -1,12 +1,7 @@
|
|||
// noinspection JSUnusedGlobalSymbols
|
||||
|
||||
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/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 "./layout.css";
|
||||
import {AppBody} from "@/app/AppBody"
|
||||
|
||||
import { config } from '@fortawesome/fontawesome-svg-core';
|
||||
config.autoAddCss = false; /* eslint-disable import/first */
|
||||
|
@ -23,17 +18,9 @@ export const metadata: NextMetadata = {
|
|||
export default function RootLayout({children}: { children: ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={"theme-bluelib layout-center"}>
|
||||
<AppBody>
|
||||
{children}
|
||||
<footer>
|
||||
<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>
|
||||
</AppBody>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
|
|
19
todoblue/src/app/page.module.css
Normal file
19
todoblue/src/app/page.module.css
Normal 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;
|
||||
}
|
|
@ -1,15 +1,29 @@
|
|||
import {CreatePrivateBoardPanel} from "@/app/CreatePrivateBoardPanel"
|
||||
import {CreatePublicBoardPanel} from "@/app/CreatePublicBoardPanel"
|
||||
import {default as React} from "react";
|
||||
import style from "./page.module.css"
|
||||
|
||||
export default function Page() {
|
||||
return <>
|
||||
<header>
|
||||
return <div className={style.pageRoot}>
|
||||
<PageHeader/>
|
||||
<PageMain/>
|
||||
<PageFooter/>
|
||||
</div>
|
||||
}
|
||||
|
||||
function PageHeader() {
|
||||
return (
|
||||
<header className={style.pageHeader}>
|
||||
<h1>
|
||||
{process.env.NEXT_PUBLIC_SITE_NAME ?? "Todoblue"}
|
||||
</h1>
|
||||
</header>
|
||||
<main>
|
||||
)
|
||||
}
|
||||
|
||||
function PageMain() {
|
||||
return (
|
||||
<main className={style.pageMain}>
|
||||
<div className={"chapter-2"}>
|
||||
<h2>
|
||||
Crea un nuovo tabellone
|
||||
|
@ -18,5 +32,17 @@ export default function Page() {
|
|||
<CreatePrivateBoardPanel/>
|
||||
</div>
|
||||
</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>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue