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 { Component, createEffect, createSignal, lazy } from 'solid-js';
|
||||
import { loggedInUser } from './pages/Login';
|
||||
import { createStore, Store, SetStoreFunction } from 'solid-js/store';
|
||||
import { Component, createEffect, lazy } from 'solid-js';
|
||||
import { createStore, SetStoreFunction, Store } 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'));
|
||||
@ -15,30 +13,40 @@ export type User = {
|
||||
};
|
||||
|
||||
// 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>(
|
||||
storeName: string,
|
||||
init: T
|
||||
): [Store<T>, SetStoreFunction<T>] => {
|
||||
const [state, setState] = createStore(init);
|
||||
if (localStorage.globalStore) {
|
||||
if (localStorage[storeName]) {
|
||||
try {
|
||||
setState(JSON.parse(localStorage.globalStore));
|
||||
setState(JSON.parse(localStorage[storeName]));
|
||||
} catch (err) {
|
||||
setState(() => init);
|
||||
}
|
||||
}
|
||||
createEffect(() => {
|
||||
localStorage.globalStore = JSON.stringify(state);
|
||||
});
|
||||
// Used to listen to changes in 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];
|
||||
};
|
||||
|
||||
const [store, setStore] = createGlobalStore({
|
||||
const storeName = 'globalStore';
|
||||
const [store, setStore] = createGlobalStore(storeName, {
|
||||
user: { id: '', login: '' } as User,
|
||||
todos: [] as Todo[],
|
||||
});
|
||||
|
||||
const App: Component = () => {
|
||||
createEffect(() => (localStorage[storeName] = JSON.stringify(store)));
|
||||
return (
|
||||
<>
|
||||
<Navbar />
|
||||
|
@ -55,10 +55,21 @@ const TodoModal: Component<TodoModalProps> = (props) => {
|
||||
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';
|
||||
|
||||
console.log(Object.is(props.todo, todo()));
|
||||
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={<></>}>
|
||||
<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'>
|
||||
@ -168,21 +179,18 @@ const TodoModal: Component<TodoModalProps> = (props) => {
|
||||
};
|
||||
|
||||
const fetchTodos = async () => {
|
||||
const todos = (await RestClient.GET('/todo')) as Todo[];
|
||||
setStore({
|
||||
...store,
|
||||
todos,
|
||||
});
|
||||
setTodos((await RestClient.GET('/todo')) as Todo[]);
|
||||
};
|
||||
|
||||
const [todos, setTodos] = createSignal<Todo[]>([]);
|
||||
|
||||
const Home: Component = () => {
|
||||
onMount(fetchTodos);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Show when={store.todos.length > 0} fallback={<></>}>
|
||||
<Show when={todos().length > 0} fallback={<></>}>
|
||||
<Table
|
||||
data={store.todos.map((todo) => ({
|
||||
data={todos().map((todo) => ({
|
||||
Title: todo.title,
|
||||
Description: todo.description,
|
||||
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 { setStore, store, User } from '../App';
|
||||
import Button from '../ui/Button';
|
||||
|
||||
type LoginRequest = {
|
||||
type UserRequest = {
|
||||
login: string;
|
||||
password: string;
|
||||
};
|
||||
|
||||
const [loggedInUser, setLoggedInUser] = createSignal();
|
||||
export { loggedInUser };
|
||||
|
||||
const Login: Component = () => {
|
||||
const [loginRequest, setLoginRequest] = createSignal<LoginRequest>({
|
||||
const [userRequest, setUserRequest] = createSignal<UserRequest>({
|
||||
login: '',
|
||||
password: '',
|
||||
});
|
||||
@ -21,13 +18,17 @@ const Login: Component = () => {
|
||||
|
||||
// Populate the current user outside the JSX (we need createEffect for this!)
|
||||
createEffect(async () => {
|
||||
if (loginRequest().login.trim() === '' || loginRequest().password.trim() === '') {
|
||||
if (userRequest().login.trim() === '' || userRequest().password.trim() === '') {
|
||||
return;
|
||||
}
|
||||
const user = (await RestClient.POST(
|
||||
'/login',
|
||||
JSON.stringify(loginRequest())
|
||||
)) as User;
|
||||
if (window.location.href.includes('/register')) {
|
||||
const register = await RestClient.POST('/user', JSON.stringify(userRequest()));
|
||||
if (register) {
|
||||
console.log('Could not create new user');
|
||||
return;
|
||||
}
|
||||
}
|
||||
const user = (await RestClient.POST('/login', JSON.stringify(userRequest()))) as User;
|
||||
if (user.id === undefined) {
|
||||
console.log(user);
|
||||
return;
|
||||
@ -96,24 +97,50 @@ const Login: Component = () => {
|
||||
value={password()}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
console.log(login(), password());
|
||||
setLoginRequest({ login: login(), password: password() });
|
||||
}}
|
||||
<Show
|
||||
when={window.location.href.includes('/register')}
|
||||
fallback={
|
||||
<>
|
||||
<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>
|
||||
<p class='text-gray-800 mt-6 text-center'>
|
||||
Want to track your todo{"'"}s?{' '}
|
||||
<a
|
||||
href='#!'
|
||||
class='text-blue-600 hover:text-blue-700 focus:text-blue-700 transition duration-200 ease-in-out'
|
||||
<Button
|
||||
fullWidth
|
||||
onClick={() => {
|
||||
console.log(login(), password());
|
||||
setUserRequest({ login: login(), password: password() });
|
||||
}}
|
||||
>
|
||||
Register
|
||||
</a>
|
||||
</p>
|
||||
</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>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { A } from '@solidjs/router';
|
||||
import { Component, Show } from 'solid-js';
|
||||
import RestClient from '../api/RestClient';
|
||||
import { setStore, store, User } from '../App';
|
||||
import { setStore, store } from '../App';
|
||||
import Button from './Button';
|
||||
|
||||
const Navbar: Component = () => {
|
||||
@ -35,7 +34,7 @@ const Navbar: Component = () => {
|
||||
<Button
|
||||
onClick={() => {
|
||||
RestClient.DELETE('/logout');
|
||||
setStore({ todos: [], user: { id: '', login: '' } });
|
||||
setStore({ user: { id: '', login: '' } });
|
||||
window.location.href = '/login';
|
||||
}}
|
||||
backgroundColor='magenta'
|
||||
|
@ -1,8 +1,7 @@
|
||||
import { Component, For, JSX } from 'solid-js';
|
||||
import { Priority, Status, Todo } from '../pages/Home';
|
||||
|
||||
type TableProps = {
|
||||
data: Todo[];
|
||||
data: object[];
|
||||
};
|
||||
|
||||
type TableRowProps = {
|
||||
@ -19,7 +18,7 @@ type TableHeadProps = {
|
||||
|
||||
export const TableHead: Component<TableHeadProps> = (props) => {
|
||||
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}
|
||||
</th>
|
||||
);
|
||||
@ -34,6 +33,7 @@ export const TableRow: Component<TableRowProps> = (props) => {
|
||||
return <tr class={rowClass}>{props.children}</tr>;
|
||||
};
|
||||
|
||||
// Would have been nicer with cards instead of a table...
|
||||
const Table: Component<TableProps> = (props) => {
|
||||
if (props.data.length < 1) {
|
||||
return <></>;
|
||||
|
Loading…
x
Reference in New Issue
Block a user