From 9d4019f3e4ded75928146470a5397028e2c2e8be Mon Sep 17 00:00:00 2001 From: phga Date: Fri, 25 Nov 2022 03:48:24 +0100 Subject: [PATCH] feat: Usable todolist app (not the prettiest yet but...) --- .../frontend/package-lock.json | 16 +- rust_solid_cassandra/frontend/package.json | 3 +- rust_solid_cassandra/frontend/src/App.tsx | 37 ++- .../frontend/src/pages/Home.tsx | 215 +++++++++++++++++- .../frontend/src/pages/Login.tsx | 120 +++++++++- .../frontend/src/pages/Test.tsx | 22 +- .../frontend/src/ui/Button.tsx | 53 +++++ .../frontend/src/ui/Navbar.tsx | 51 +++++ .../frontend/src/ui/Table.tsx | 65 ++++++ .../frontend/tailwind.config.js | 44 +++- 10 files changed, 602 insertions(+), 24 deletions(-) create mode 100644 rust_solid_cassandra/frontend/src/ui/Button.tsx create mode 100644 rust_solid_cassandra/frontend/src/ui/Navbar.tsx create mode 100644 rust_solid_cassandra/frontend/src/ui/Table.tsx diff --git a/rust_solid_cassandra/frontend/package-lock.json b/rust_solid_cassandra/frontend/package-lock.json index ba2f00f..8b9a91e 100644 --- a/rust_solid_cassandra/frontend/package-lock.json +++ b/rust_solid_cassandra/frontend/package-lock.json @@ -10,7 +10,8 @@ "license": "MIT", "dependencies": { "@solidjs/router": "^0.5.1", - "solid-js": "^1.5.1" + "solid-js": "^1.5.1", + "uuid": "^9.0.0" }, "devDependencies": { "autoprefixer": "^10.4.13", @@ -2136,6 +2137,14 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "node_modules/uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, "node_modules/vite": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.4.tgz", @@ -3605,6 +3614,11 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, + "uuid": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", + "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==" + }, "vite": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/vite/-/vite-3.2.4.tgz", diff --git a/rust_solid_cassandra/frontend/package.json b/rust_solid_cassandra/frontend/package.json index af5d6fb..dd521be 100644 --- a/rust_solid_cassandra/frontend/package.json +++ b/rust_solid_cassandra/frontend/package.json @@ -19,6 +19,7 @@ }, "dependencies": { "@solidjs/router": "^0.5.1", - "solid-js": "^1.5.1" + "solid-js": "^1.5.1", + "uuid": "^9.0.0" } } diff --git a/rust_solid_cassandra/frontend/src/App.tsx b/rust_solid_cassandra/frontend/src/App.tsx index bc1e4be..df3a003 100644 --- a/rust_solid_cassandra/frontend/src/App.tsx +++ b/rust_solid_cassandra/frontend/src/App.tsx @@ -1,13 +1,47 @@ import { Route, Routes } from '@solidjs/router'; -import { Component, lazy } from 'solid-js'; +import { Component, createEffect, createSignal, lazy } from 'solid-js'; +import { loggedInUser } from './pages/Login'; +import { createStore, Store, SetStoreFunction } from 'solid-js/store'; +import Navbar from './ui/Navbar'; +import { Todo } from './pages/Home'; // Only load the components if we are navigating to them const Home = lazy(() => import('./pages/Home')); const Login = lazy(() => import('./pages/Login')); const Test = lazy(() => import('./pages/Test')); +export type User = { + id: string; + login: string; +}; + +// Helper funciton to get a global state +// https://stackoverflow.com/a/72339551 +export const createGlobalStore = ( + init: T +): [Store, SetStoreFunction] => { + const [state, setState] = createStore(init); + if (localStorage.globalStore) { + try { + setState(JSON.parse(localStorage.globalStore)); + } catch (err) { + setState(() => init); + } + } + createEffect(() => { + localStorage.globalStore = JSON.stringify(state); + }); + return [state, setState]; +}; + +const [store, setStore] = createGlobalStore({ + user: { id: '', login: '' } as User, + todos: [] as Todo[], +}); + const App: Component = () => { return ( <> + @@ -17,4 +51,5 @@ const App: Component = () => { ); }; +export { store, setStore }; export default App; diff --git a/rust_solid_cassandra/frontend/src/pages/Home.tsx b/rust_solid_cassandra/frontend/src/pages/Home.tsx index 3e71088..27e771a 100644 --- a/rust_solid_cassandra/frontend/src/pages/Home.tsx +++ b/rust_solid_cassandra/frontend/src/pages/Home.tsx @@ -1,9 +1,220 @@ -import { Component } from "solid-js"; +import { + Component, + createEffect, + createResource, + createSignal, + For, + onMount, + Show, +} from 'solid-js'; +import RestClient from '../api/RestClient'; +import { store, setStore } from '../App'; +import Button from '../ui/Button'; +import Table, { TableData, TableRow } from '../ui/Table'; +import { v4 as uuidv4 } from 'uuid'; + +export type Todo = { + id: string; + user_id: string; + title: string; + priority: Priority; + status: Status; + description: string; +}; + +type TodoModalProps = { + todo: Todo; +}; + +export enum Status { + Todo = 'Todo', + Doing = 'Doing', + Done = 'Done', +} + +export enum Priority { + High = 'High', + Normal = 'Normal', + Low = 'Low', +} + +const createNewTodo = (): Todo => ({ + id: uuidv4(), + user_id: store.user.id, + title: 'New Title', + description: 'Some description.', + status: Status.Todo, + priority: Priority.Normal, +}); + +const TodoModal: Component = (props) => { + const [show, setShow] = createSignal(false); + const [todo, setTodo] = createSignal(props.todo); + const inputClass = + 'form-control block w-full px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding border border-solid border-gray-300 rounded transition ease-in-out m-0 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none'; + const selectClass = + 'form-select block w-full px-3 py-1.5 text-base font-normal text-gray-700 bg-white bg-clip-padding bg-no-repeat border border-solid border-gray-300 rounded transition ease-in-out m-0 focus:text-gray-700 focus:bg-white focus:border-blue-600 focus:outline-none'; + const labelClass = 'form-label inline-block mb-2 text-gray-700'; + + return ( + <> + + }> +
+
+
+
+ + + setTodo((t) => ({ ...t, title: e.currentTarget.value } as Todo)) + } + value={todo()?.title} + /> +
+
+ +