refactor: Some small visual improvements & register

main
phga 2 years ago
parent 9d4019f3e4
commit 018db91090
Signed by: phga
GPG Key ID: 5249548AA705F019

@ -1,9 +1,7 @@
import { Route, Routes } from '@solidjs/router'; import { Route, Routes } from '@solidjs/router';
import { Component, createEffect, createSignal, lazy } from 'solid-js'; import { Component, createEffect, lazy } from 'solid-js';
import { loggedInUser } from './pages/Login'; import { createStore, SetStoreFunction, Store } from 'solid-js/store';
import { createStore, Store, SetStoreFunction } from 'solid-js/store';
import Navbar from './ui/Navbar'; import Navbar from './ui/Navbar';
import { Todo } from './pages/Home';
// Only load the components if we are navigating to them // Only load the components if we are navigating to them
const Home = lazy(() => import('./pages/Home')); const Home = lazy(() => import('./pages/Home'));
const Login = lazy(() => import('./pages/Login')); const Login = lazy(() => import('./pages/Login'));
@ -15,30 +13,40 @@ export type User = {
}; };
// Helper funciton to get a global state // Helper funciton to get a global state
// https://stackoverflow.com/a/72339551 // I tried a couple other things but couldn't figure it all out in one day...
// Probably should be possible with Context.Provider etc.
// The Problem with all of them was that I could not set the User globally inside
// Login Component. At one point I gave up and took this shortcut (for now).
// Fairly modified version of: https://stackoverflow.com/a/72339551
export const createGlobalStore = <T extends object>( export const createGlobalStore = <T extends object>(
storeName: string,
init: T init: T
): [Store<T>, SetStoreFunction<T>] => { ): [Store<T>, SetStoreFunction<T>] => {
const [state, setState] = createStore(init); const [state, setState] = createStore(init);
if (localStorage.globalStore) { if (localStorage[storeName]) {
try { try {
setState(JSON.parse(localStorage.globalStore)); setState(JSON.parse(localStorage[storeName]));
} catch (err) { } catch (err) {
setState(() => init); setState(() => init);
} }
} }
createEffect(() => { // Used to listen to changes in state
localStorage.globalStore = JSON.stringify(state); // This produced a warning bc. it could create a mem leak
}); // bc. we try to create a reactive component outside of render/etc.
// I leave this here for future reference
/* createEffect(() => {
* localStorage.globalStore = JSON.stringify(state);
* }); */
return [state, setState]; return [state, setState];
}; };
const [store, setStore] = createGlobalStore({ const storeName = 'globalStore';
const [store, setStore] = createGlobalStore(storeName, {
user: { id: '', login: '' } as User, user: { id: '', login: '' } as User,
todos: [] as Todo[],
}); });
const App: Component = () => { const App: Component = () => {
createEffect(() => (localStorage[storeName] = JSON.stringify(store)));
return ( return (
<> <>
<Navbar /> <Navbar />

@ -55,10 +55,21 @@ const TodoModal: Component<TodoModalProps> = (props) => {
const selectClass = 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'; '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'; const labelClass = 'form-label inline-block mb-2 text-gray-700';
console.log(Object.is(props.todo, todo()));
return ( return (
<> <>
<Button onClick={() => setShow(true)}>🖉</Button> <Show
when={Object.is(props.todo, todo())}
fallback={
<>
<Button backgroundColor='magenta' onClick={() => setShow(true)}>
🖉
</Button>
</>
}
>
<Button onClick={() => setShow(true)}>🖉</Button>
</Show>
<Show when={show()} fallback={<></>}> <Show when={show()} fallback={<></>}>
<div class='fixed top-0 left-0 w-screen h-screen flex items-center justify-center bg-sh-bgP2 bg-opacity-50 transform transition-transform duration-300'> <div class='fixed top-0 left-0 w-screen h-screen flex items-center justify-center bg-sh-bgP2 bg-opacity-50 transform transition-transform duration-300'>
<div class='p-6 rounded-lg bg-white w-1/2'> <div class='p-6 rounded-lg bg-white w-1/2'>
@ -168,21 +179,18 @@ const TodoModal: Component<TodoModalProps> = (props) => {
}; };
const fetchTodos = async () => { const fetchTodos = async () => {
const todos = (await RestClient.GET('/todo')) as Todo[]; setTodos((await RestClient.GET('/todo')) as Todo[]);
setStore({
...store,
todos,
});
}; };
const [todos, setTodos] = createSignal<Todo[]>([]);
const Home: Component = () => { const Home: Component = () => {
onMount(fetchTodos); onMount(fetchTodos);
return ( return (
<> <>
<Show when={store.todos.length > 0} fallback={<></>}> <Show when={todos().length > 0} fallback={<></>}>
<Table <Table
data={store.todos.map((todo) => ({ data={todos().map((todo) => ({
Title: todo.title, Title: todo.title,
Description: todo.description, Description: todo.description,
Status: todo.status, Status: todo.status,

@ -1,18 +1,15 @@
import { Component, createEffect, createSignal } from 'solid-js'; import { Component, createEffect, createSignal, Show } from 'solid-js';
import RestClient from '../api/RestClient'; import RestClient from '../api/RestClient';
import { setStore, store, User } from '../App'; import { setStore, store, User } from '../App';
import Button from '../ui/Button'; import Button from '../ui/Button';
type LoginRequest = { type UserRequest = {
login: string; login: string;
password: string; password: string;
}; };
const [loggedInUser, setLoggedInUser] = createSignal();
export { loggedInUser };
const Login: Component = () => { const Login: Component = () => {
const [loginRequest, setLoginRequest] = createSignal<LoginRequest>({ const [userRequest, setUserRequest] = createSignal<UserRequest>({
login: '', login: '',
password: '', password: '',
}); });
@ -21,13 +18,17 @@ const Login: Component = () => {
// Populate the current user outside the JSX (we need createEffect for this!) // Populate the current user outside the JSX (we need createEffect for this!)
createEffect(async () => { createEffect(async () => {
if (loginRequest().login.trim() === '' || loginRequest().password.trim() === '') { if (userRequest().login.trim() === '' || userRequest().password.trim() === '') {
return; return;
} }
const user = (await RestClient.POST( if (window.location.href.includes('/register')) {
'/login', const register = await RestClient.POST('/user', JSON.stringify(userRequest()));
JSON.stringify(loginRequest()) if (register) {
)) as User; console.log('Could not create new user');
return;
}
}
const user = (await RestClient.POST('/login', JSON.stringify(userRequest()))) as User;
if (user.id === undefined) { if (user.id === undefined) {
console.log(user); console.log(user);
return; return;
@ -96,24 +97,50 @@ const Login: Component = () => {
value={password()} value={password()}
/> />
</div> </div>
<Button <Show
fullWidth when={window.location.href.includes('/register')}
onClick={() => { fallback={
console.log(login(), password()); <>
setLoginRequest({ login: login(), password: password() }); <Button
}} fullWidth
onClick={() => {
console.log(login(), password());
setUserRequest({ login: login(), password: password() });
}}
>
Sign in
</Button>
<p class='text-gray-800 mt-6 text-center'>
Want to track your todo{"'"}s?{' '}
<a
href='/register'
class='text-blue-600 hover:text-blue-700 focus:text-blue-700 transition duration-200 ease-in-out'
>
Register
</a>
</p>
</>
}
> >
Sign in <Button
</Button> fullWidth
<p class='text-gray-800 mt-6 text-center'> onClick={() => {
Want to track your todo{"'"}s?{' '} console.log(login(), password());
<a setUserRequest({ login: login(), password: password() });
href='#!' }}
class='text-blue-600 hover:text-blue-700 focus:text-blue-700 transition duration-200 ease-in-out'
> >
Register Register
</a> </Button>
</p> <p class='text-gray-800 mt-6 text-center'>
Back to login?{' '}
<a
href='/login'
class='text-blue-600 hover:text-blue-700 focus:text-blue-700 transition duration-200 ease-in-out'
>
Sign in
</a>
</p>
</Show>
</form> </form>
</div> </div>
</div> </div>

@ -1,7 +1,6 @@
import { A } from '@solidjs/router';
import { Component, Show } from 'solid-js'; import { Component, Show } from 'solid-js';
import RestClient from '../api/RestClient'; import RestClient from '../api/RestClient';
import { setStore, store, User } from '../App'; import { setStore, store } from '../App';
import Button from './Button'; import Button from './Button';
const Navbar: Component = () => { const Navbar: Component = () => {
@ -35,7 +34,7 @@ const Navbar: Component = () => {
<Button <Button
onClick={() => { onClick={() => {
RestClient.DELETE('/logout'); RestClient.DELETE('/logout');
setStore({ todos: [], user: { id: '', login: '' } }); setStore({ user: { id: '', login: '' } });
window.location.href = '/login'; window.location.href = '/login';
}} }}
backgroundColor='magenta' backgroundColor='magenta'

@ -1,8 +1,7 @@
import { Component, For, JSX } from 'solid-js'; import { Component, For, JSX } from 'solid-js';
import { Priority, Status, Todo } from '../pages/Home';
type TableProps = { type TableProps = {
data: Todo[]; data: object[];
}; };
type TableRowProps = { type TableRowProps = {
@ -19,7 +18,7 @@ type TableHeadProps = {
export const TableHead: Component<TableHeadProps> = (props) => { export const TableHead: Component<TableHeadProps> = (props) => {
return ( return (
<th scope='col' class='text-sm font-medium px-6 py-4'> <th scope='col' class='text-sm font-bold px-6 py-4'>
{props.children} {props.children}
</th> </th>
); );
@ -34,6 +33,7 @@ export const TableRow: Component<TableRowProps> = (props) => {
return <tr class={rowClass}>{props.children}</tr>; return <tr class={rowClass}>{props.children}</tr>;
}; };
// Would have been nicer with cards instead of a table...
const Table: Component<TableProps> = (props) => { const Table: Component<TableProps> = (props) => {
if (props.data.length < 1) { if (props.data.length < 1) {
return <></>; return <></>;

Loading…
Cancel
Save