refactor: Some small visual improvements & register
This commit is contained in:
parent
9d4019f3e4
commit
018db91090
@ -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 (
|
||||||
<>
|
<>
|
||||||
|
<Show
|
||||||
|
when={Object.is(props.todo, todo())}
|
||||||
|
fallback={
|
||||||
|
<>
|
||||||
|
<Button backgroundColor='magenta' onClick={() => setShow(true)}>
|
||||||
|
🖉
|
||||||
|
</Button>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Button 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,11 +97,15 @@ const Login: Component = () => {
|
|||||||
value={password()}
|
value={password()}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
<Show
|
||||||
|
when={window.location.href.includes('/register')}
|
||||||
|
fallback={
|
||||||
|
<>
|
||||||
<Button
|
<Button
|
||||||
fullWidth
|
fullWidth
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
console.log(login(), password());
|
console.log(login(), password());
|
||||||
setLoginRequest({ login: login(), password: password() });
|
setUserRequest({ login: login(), password: password() });
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Sign in
|
Sign in
|
||||||
@ -108,12 +113,34 @@ const Login: Component = () => {
|
|||||||
<p class='text-gray-800 mt-6 text-center'>
|
<p class='text-gray-800 mt-6 text-center'>
|
||||||
Want to track your todo{"'"}s?{' '}
|
Want to track your todo{"'"}s?{' '}
|
||||||
<a
|
<a
|
||||||
href='#!'
|
href='/register'
|
||||||
class='text-blue-600 hover:text-blue-700 focus:text-blue-700 transition duration-200 ease-in-out'
|
class='text-blue-600 hover:text-blue-700 focus:text-blue-700 transition duration-200 ease-in-out'
|
||||||
>
|
>
|
||||||
Register
|
Register
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
fullWidth
|
||||||
|
onClick={() => {
|
||||||
|
console.log(login(), password());
|
||||||
|
setUserRequest({ login: login(), password: password() });
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Register
|
||||||
|
</Button>
|
||||||
|
<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…
x
Reference in New Issue
Block a user