Skip to content

Commit

Permalink
Added routes
Browse files Browse the repository at this point in the history
  • Loading branch information
talentedunicorn committed Jan 12, 2025
1 parent f78a6fa commit 7490ee3
Show file tree
Hide file tree
Showing 13 changed files with 316 additions and 138 deletions.
5 changes: 5 additions & 0 deletions About.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# About ToDone

An offline-first note-taking app that gets you from _To Do_ to **Done**

Made by [Talentedunicorn](https://talentedunicorn.com) with 🫰 and [Svelte](https://svelte.dev)
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"marked": "^15.0.6",
"rxdb": "^15.39.0",
"rxjs": "^7.8.1",
"svelte-spa-router": "^4.0.1",
"vite-plugin-pwa": "^0.21.1",
"zod": "^3.24.1"
},
Expand Down
16 changes: 16 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

227 changes: 102 additions & 125 deletions src/App.svelte
Original file line number Diff line number Diff line change
@@ -1,37 +1,30 @@
<script lang="ts">
import './app.css';
import Logo from './components/Logo.svelte';
import Menu from './components/Menu.svelte';
import { isLoggedin, tabs, currentTab, status, user } from './stores';
import Button from './components/Button.svelte';
import { checkAuth, initAuth0Client, login, logout } from './auth';
import { onMount } from 'svelte';
import { pwaInfo } from 'virtual:pwa-info';
import Router, { link, push } from 'svelte-spa-router';
import { wrap } from 'svelte-spa-router/wrap';
import { fly } from 'svelte/transition';
import List from './List.svelte';
import type { Auth0Client } from '@auth0/auth0-spa-js';
import './app.css';
import Button from './components/Button.svelte';
import ReloadPrompt from './components/ReloadPrompt.svelte';
import { pwaInfo } from 'virtual:pwa-info';
import ExportImport from './components/ExportImport.svelte';
import Toast from './components/Toast.svelte';
import Logo from './components/Logo.svelte';
import ToggleTheme from './components/ToggleTheme.svelte';
import { toastActions, toastMessage } from './stores';
let auth0: Auth0Client;
import About from './routes/About.svelte';
import NotFound from './routes/NotFound.svelte';
import Login from './routes/Login.svelte';
import Home from './routes/Home.svelte';
import { checkAuth, initAuth0Client } from './auth';
import { toastActions, toastMessage, status, isLoggedin } from './stores';
import type { ComponentType } from 'svelte';
let auth0 = $state<Auth0Client>();
let wrapper: HTMLElement;
let menuItems = $derived(
tabs.map((item) => ({
...item,
selected: item.label === $currentTab
}))
);
let showBackToTop = $state(false);
const handleMenu = (path: string) => {
currentTab.set(path);
scrollToTop();
};
const synced = import.meta.env.VITE_SYNCED === 'true';
const scrollToTop = () => {
wrapper.scrollIntoView({
Expand All @@ -46,21 +39,58 @@
});
};
onMount(async () => {
const initializeAuth = async () => {
auth0 = await initAuth0Client();
await checkAuth(auth0);
};
$effect(() => {
handleBackToTop();
if (import.meta.env.VITE_SYNCED === 'true' && navigator.onLine) {
if (!auth0) {
auth0 = await initAuth0Client();
}
try {
await checkAuth(auth0);
if (!$isLoggedin) return;
} catch (e) {
// Log out on failure
logout(auth0);
}
}
if (synced && !auth0) initializeAuth();
});
const routes = {
'/about': About,
'/login': wrap({
component: Login as unknown as ComponentType,
props: {
auth0: () => auth0
},
conditions: [
() => {
if (!synced) {
push(`/`);
return false;
}
return true;
},
() => {
if ($isLoggedin) {
push(`/`);
return false;
}
return true;
}
]
}),
'/': wrap({
component: Home as unknown as ComponentType,
props: {
auth0: () => auth0
},
conditions: [
() => {
if (!synced) return true;
if (!$isLoggedin) {
push('/login');
return false;
}
return true;
}
]
}),
'*': NotFound
};
</script>

<svelte:head>
Expand All @@ -70,33 +100,12 @@
</svelte:head>

<main class="Wrapper" bind:this={wrapper}>
{#if import.meta.env.VITE_SYNCED === 'true' && !$isLoggedin}
<div class="Login">
<Logo />
<Button onclick={() => login(auth0)}>Log in</Button>
<ToggleTheme />
</div>
{:else}
<aside class="Menu">
<Menu {menuItems} goTo={handleMenu}>
<ExportImport />
</Menu>
</aside>
<header class="Header">
<h1 data-syncing={$status} class="Logo" title="ToDone"><Logo /></h1>

<ToggleTheme />
</header>
<section class="Content">
{#if $isLoggedin}
<div class="Profile">
<img src={$user.picture} alt={$user.nickname} />
<Button onclick={() => logout(auth0)}>Log out</Button>
</div>
{/if}
<List />
</section>
{/if}
<header class="Header">
<h1 data-syncing={$status} class="Logo" title="ToDone"><a href="/" use:link><Logo /></a></h1>

<ToggleTheme />
</header>
<Router {routes} />
{#if showBackToTop}
<footer class="Footer" transition:fly={{ y: 100, duration: 500 }}>
<Button onclick={scrollToTop}
Expand Down Expand Up @@ -137,82 +146,50 @@
{/if}

<style>
.Wrapper,
.Login {
.Wrapper {
flex-flow: column;
display: flex;
min-height: 100vh;
}
.Login {
padding: 2rem;
gap: 2rem;
align-items: flex-start;
:global(.ColorToggle) {
margin-left: auto;
.Footer {
align-self: flex-end;
position: sticky;
bottom: 2rem;
padding: 0 1rem 0 0;
display: flex;
justify-content: flex-end;
}
}
.Menu {
position: fixed;
top: 0;
z-index: 9;
}
.Header {
align-self: flex-end;
display: flex;
gap: 2rem;
flex-direction: row-reverse;
padding-top: 1rem;
.Header {
align-self: flex-end;
display: flex;
gap: 2rem;
flex-direction: row-reverse;
padding-top: 1rem;
}
}
.Logo {
margin: 1rem;
padding: 0.2em;
background: var(--white);
position: relative;
}
.Footer {
align-self: flex-end;
position: sticky;
bottom: 2rem;
padding: 0 1rem 0 0;
display: flex;
justify-content: flex-end;
}
.Profile {
display: flex;
gap: 1rem;
margin: 2rem;
justify-content: end;
align-items: center;
&[data-syncing] {
--indicator-color: var(--primary);
}
img {
inline-size: 3rem;
&[data-syncing]:not([data-syncing='NOT_SYNCED'])::after {
content: '';
width: 0.5em;
height: 0.5em;
border-radius: 100%;
background: var(--indicator-color);
position: absolute;
top: -0.2em;
left: -0.2em;
}
}
[data-syncing] {
--indicator-color: var(--primary);
}
[data-syncing]:not([data-syncing='NOT_SYNCED'])::after {
content: '';
width: 0.5em;
height: 0.5em;
border-radius: 100%;
background: var(--indicator-color);
position: absolute;
top: -0.2em;
left: -0.2em;
}
[data-syncing='ERROR'] {
--indicator-color: var(--red);
&[data-syncing='ERROR'] {
--indicator-color: var(--red);
}
}
</style>
3 changes: 0 additions & 3 deletions src/List.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -235,9 +235,6 @@
.Search {
align-self: flex-end;
position: sticky;
z-index: 1;
top: 1rem;
display: inline-flex;
gap: 1rem;
padding: 0.5rem;
Expand Down
4 changes: 4 additions & 0 deletions src/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ img {
max-width: 100%;
}

a {
color: var(--primary);
}

.visually-hidden {
position: absolute;
margin: -1px;
Expand Down
3 changes: 1 addition & 2 deletions src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export const initAuth0Client = async () => {
domain: import.meta.env.VITE_AUTH0_DOMAIN,
cacheLocation: 'localstorage',
authorizationParams: {
redirect_uri: window.location.origin
redirect_uri
}
});
};
Expand Down Expand Up @@ -60,7 +60,6 @@ export const checkAuth = async (auth0: Auth0Client) => {
token.set(id_token);
}, refreshRate);
}
// });

// clear token refresh interval on component unmount
return () => {
Expand Down
Loading

0 comments on commit 7490ee3

Please sign in to comment.