Added pocket base.
This commit is contained in:
parent
4dd4c22db6
commit
402c65fc90
11
package-lock.json
generated
11
package-lock.json
generated
@ -14,6 +14,7 @@
|
|||||||
"bulmaswatch": "^0.8.1",
|
"bulmaswatch": "^0.8.1",
|
||||||
"material-dynamic-colors": "^0.0.10",
|
"material-dynamic-colors": "^0.0.10",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
|
"pocketbase": "^0.7.3",
|
||||||
"svelte-spa-router": "^3.3.0"
|
"svelte-spa-router": "^3.3.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -885,6 +886,11 @@
|
|||||||
"url": "https://github.com/sponsors/jonschlinkert"
|
"url": "https://github.com/sponsors/jonschlinkert"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/pocketbase": {
|
||||||
|
"version": "0.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.7.3.tgz",
|
||||||
|
"integrity": "sha512-sMbj6uw0f/u9xALsow9b2xlA/6vCB+R0DVswldTxxSBY+HQNz2EyLW2jQu8sMYwo7W0OF2VPyV2Aa+RlhyPoLQ=="
|
||||||
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.4.17",
|
"version": "8.4.17",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz",
|
||||||
@ -1668,6 +1674,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
|
||||||
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="
|
||||||
},
|
},
|
||||||
|
"pocketbase": {
|
||||||
|
"version": "0.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/pocketbase/-/pocketbase-0.7.3.tgz",
|
||||||
|
"integrity": "sha512-sMbj6uw0f/u9xALsow9b2xlA/6vCB+R0DVswldTxxSBY+HQNz2EyLW2jQu8sMYwo7W0OF2VPyV2Aa+RlhyPoLQ=="
|
||||||
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "8.4.17",
|
"version": "8.4.17",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.17.tgz",
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"bulmaswatch": "^0.8.1",
|
"bulmaswatch": "^0.8.1",
|
||||||
"material-dynamic-colors": "^0.0.10",
|
"material-dynamic-colors": "^0.0.10",
|
||||||
"normalize.css": "^8.0.1",
|
"normalize.css": "^8.0.1",
|
||||||
|
"pocketbase": "^0.7.3",
|
||||||
"svelte-spa-router": "^3.3.0"
|
"svelte-spa-router": "^3.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,60 @@
|
|||||||
<script>
|
<script>
|
||||||
import Router from 'svelte-spa-router';
|
import Router from "svelte-spa-router";
|
||||||
import { replace } from 'svelte-spa-router';
|
import { replace, location } from "svelte-spa-router";
|
||||||
|
|
||||||
import { isAuthed } from './store';
|
import { pbClient, activeNav } from "./store";
|
||||||
|
|
||||||
import Home from './routes/Home.svelte';
|
import Home from "./routes/Home.svelte";
|
||||||
import NotFound from './routes/NotFound.svelte';
|
import NotFound from "./routes/NotFound.svelte";
|
||||||
import Budgets from './routes/Budgets.svelte';
|
import Budgets from "./routes/Budgets.svelte";
|
||||||
import Settings from './routes/Settings.svelte';
|
import Settings from "./routes/Settings.svelte";
|
||||||
import Timeline from './routes/Timeline.svelte'
|
import Timeline from "./routes/Timeline.svelte";
|
||||||
import Login from './routes/Login.svelte';
|
import Login from "./routes/Login.svelte";
|
||||||
import Logout from './routes/Logout.svelte';
|
import Logout from "./routes/Logout.svelte";
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from "svelte";
|
||||||
|
import { authUserID } from "./store";
|
||||||
|
|
||||||
const routes = {
|
const routes = {
|
||||||
'/': Home,
|
"/": Home,
|
||||||
'/timeline': Timeline,
|
"/timeline": Timeline,
|
||||||
"/budgets": Budgets,
|
"/budgets": Budgets,
|
||||||
'/settings': Settings,
|
"/settings": Settings,
|
||||||
'/login': Login,
|
"/login": Login,
|
||||||
'/logout': Logout,
|
"/logout": Logout,
|
||||||
'*': NotFound,
|
"*": NotFound,
|
||||||
|
};
|
||||||
|
|
||||||
|
location.subscribe((value) => {
|
||||||
|
switch (value) {
|
||||||
|
case "/":
|
||||||
|
activeNav.set(0);
|
||||||
|
break;
|
||||||
|
case "/budgets":
|
||||||
|
activeNav.set(1);
|
||||||
|
break;
|
||||||
|
case "/timeline":
|
||||||
|
activeNav.set(2);
|
||||||
|
break;
|
||||||
|
case "/settings":
|
||||||
|
activeNav.set(3);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
console.log($isAuthed)
|
if (
|
||||||
if(!$isAuthed){
|
!pbClient.authStore.isValid ||
|
||||||
replace('/login')
|
localStorage.getItem("pocketbase_auth") == null
|
||||||
|
) {
|
||||||
|
replace("/login");
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
|
authUserID.set(
|
||||||
|
JSON.parse(localStorage.getItem("pocketbase_auth")).model.id
|
||||||
|
);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Router {routes} />
|
<Router {routes} />
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ export const FAKE_BUDGET_ITEMS = [
|
|||||||
"isEnabled": true,
|
"isEnabled": true,
|
||||||
"entries":[
|
"entries":[
|
||||||
{
|
{
|
||||||
|
"budget_item_id": "",
|
||||||
"name": "Test Entry",
|
"name": "Test Entry",
|
||||||
"amount": 20,
|
"amount": 20,
|
||||||
"description": "Extra info if wanted",
|
"description": "Extra info if wanted",
|
||||||
|
@ -1,46 +1,29 @@
|
|||||||
<script>
|
<script>
|
||||||
import {link} from 'svelte-spa-router'
|
import { link } from "svelte-spa-router";
|
||||||
import { activeNav } from '../store';
|
import { activeNav } from "../store";
|
||||||
|
|
||||||
let activeitem = $activeNav;
|
let activeitem = $activeNav;
|
||||||
|
|
||||||
function updateActiveItem(num){
|
|
||||||
activeNav.set(num)
|
|
||||||
}
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
|
||||||
@media only screen and (max-width: 600px){
|
|
||||||
.m:not(.s), .l:not(.s), .m.l:not(.s) {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<nav class="m l left">
|
<nav class="m l left">
|
||||||
|
<img class="circle" src="/vite.svg" alt="Favicon" />
|
||||||
<img class="circle" src="/vite.svg" alt="Favicon">
|
<a href="/" class:active={activeitem === 0} use:link>
|
||||||
<a href="/" class:active="{activeitem === 0}" on:click={()=>updateActiveItem(0)} use:link>
|
|
||||||
<i>home</i>
|
<i>home</i>
|
||||||
<span>Home</span>
|
<span>Home</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="/budgets" class:active="{activeitem === 1}" on:click={()=>updateActiveItem(1)} use:link>
|
<a href="/budgets" class:active={activeitem === 1} use:link>
|
||||||
<i>payments</i>
|
<i>payments</i>
|
||||||
<span>Budgets</span>
|
<span>Budgets</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="/timeline" class:active="{activeitem === 2}" on:click={()=>updateActiveItem(2)} use:link>
|
<a href="/timeline" class:active={activeitem === 2} use:link>
|
||||||
<i>timeline</i>
|
<i>timeline</i>
|
||||||
<span>Spending</span>
|
<span>Spending</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="/settings" class:active="{activeitem === 3}" on:click={()=>updateActiveItem(3)} use:link>
|
<a href="/settings" class:active={activeitem === 3} use:link>
|
||||||
<i>settings</i>
|
<i>settings</i>
|
||||||
<span>Settings</span>
|
<span>Settings</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="max">
|
<div class="max" />
|
||||||
|
|
||||||
</div>
|
|
||||||
<a href="/logout" use:link>
|
<a href="/logout" use:link>
|
||||||
<i>logout</i>
|
<i>logout</i>
|
||||||
<span>Logout</span>
|
<span>Logout</span>
|
||||||
@ -48,20 +31,19 @@
|
|||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<nav class="s bottom">
|
<nav class="s bottom">
|
||||||
|
<a href="/" class:active={activeitem === 0} use:link>
|
||||||
<a href="/" class:active="{activeitem === 0}" on:click={()=>updateActiveItem(0)} use:link>
|
|
||||||
<i>home</i>
|
<i>home</i>
|
||||||
<span>Home</span>
|
<span>Home</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="/budgets" class:active="{activeitem === 1}" on:click={()=>updateActiveItem(1)} use:link>
|
<a href="/budgets" class:active={activeitem === 1} use:link>
|
||||||
<i>payments</i>
|
<i>payments</i>
|
||||||
<span>Budgets</span>
|
<span>Budgets</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="/timeline" class:active="{activeitem === 2}" on:click={()=>updateActiveItem(2)} use:link>
|
<a href="/timeline" class:active={activeitem === 2} use:link>
|
||||||
<i>timeline</i>
|
<i>timeline</i>
|
||||||
<span>Spending</span>
|
<span>Spending</span>
|
||||||
</a>
|
</a>
|
||||||
<a href="/settings" class:active="{activeitem === 3}" on:click={()=>updateActiveItem(3)} use:link>
|
<a href="/settings" class:active={activeitem === 3} use:link>
|
||||||
<i>settings</i>
|
<i>settings</i>
|
||||||
<span>Settings</span>
|
<span>Settings</span>
|
||||||
</a>
|
</a>
|
||||||
@ -70,3 +52,13 @@
|
|||||||
<span>Logout</span>
|
<span>Logout</span>
|
||||||
</a>
|
</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@media only screen and (max-width: 600px) {
|
||||||
|
.m:not(.s),
|
||||||
|
.l:not(.s),
|
||||||
|
.m.l:not(.s) {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
@ -1,6 +1,33 @@
|
|||||||
<script>
|
<script>
|
||||||
import BaseLayout from "../layouts/BaseLayout.svelte";
|
import BaseLayout from "../layouts/BaseLayout.svelte";
|
||||||
import { FAKE_BUDGET_ITEMS } from "../fakeData";
|
import { onMount } from "svelte";
|
||||||
|
|
||||||
|
import { pbClient, authUserID } from "../store";
|
||||||
|
|
||||||
|
let budgetItems = [];
|
||||||
|
|
||||||
|
async function disableBudgetItem(recordID) {
|
||||||
|
await pbClient.records.update("eo2i6pm5ldu4tsm_budget_items", recordID, {
|
||||||
|
isEnabled: false,
|
||||||
|
});
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function enableBudgetItem(recordID) {
|
||||||
|
await pbClient.records.update("eo2i6pm5ldu4tsm_budget_items", recordID, {
|
||||||
|
isEnabled: true,
|
||||||
|
});
|
||||||
|
fetchData();
|
||||||
|
}
|
||||||
|
|
||||||
|
async function fetchData() {
|
||||||
|
const items = await pbClient.records.getList($authUserID + "_budget_items");
|
||||||
|
budgetItems = items.items;
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
fetchData();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<BaseLayout>
|
<BaseLayout>
|
||||||
@ -9,33 +36,60 @@
|
|||||||
</nav>
|
</nav>
|
||||||
<div class="space" />
|
<div class="space" />
|
||||||
<hr />
|
<hr />
|
||||||
|
{#if budgetItems.length == 0}
|
||||||
|
<div class="padding absolute center middle">
|
||||||
|
<!-- svelte-ignore a11y-missing-attribute -->
|
||||||
|
<!-- svelte-ignore a11y-missing-content -->
|
||||||
|
<a class="loader" />
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
<article class="responsive">
|
<article class="responsive">
|
||||||
<table class="border medium-space">
|
<table class="border medium-space">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
<th>Enabled</th>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Amount</th>
|
<th>Amount</th>
|
||||||
<th />
|
<th />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{#each FAKE_BUDGET_ITEMS as ITEM}
|
{#each budgetItems as ITEM}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{ITEM.key}</td>
|
<td>
|
||||||
<td>{ITEM.amount}</td>
|
<label class="switch">
|
||||||
|
{#if ITEM.isEnabled}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked
|
||||||
|
on:change={() => disableBudgetItem(ITEM.id)}
|
||||||
|
/>
|
||||||
|
{:else}
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
on:change={() => enableBudgetItem(ITEM.id)}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
<span />
|
||||||
|
</label>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>{ITEM.name}</p>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<p>{ITEM.amount}</p>
|
||||||
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<nav class="right-align">
|
<nav class="right-align">
|
||||||
<button class="none">
|
|
||||||
<i>more_vert</i>
|
|
||||||
<div class="dropdown left no-wrap">
|
|
||||||
<!-- svelte-ignore a11y-missing-attribute -->
|
<!-- svelte-ignore a11y-missing-attribute -->
|
||||||
<a>Edit</a>
|
<a>
|
||||||
|
<i>edit</i>
|
||||||
|
</a>
|
||||||
<!-- svelte-ignore a11y-missing-attribute -->
|
<!-- svelte-ignore a11y-missing-attribute -->
|
||||||
<a>Disable</a>
|
<a>
|
||||||
<!-- svelte-ignore a11y-missing-attribute -->
|
<i>delete</i>
|
||||||
<a>Delete</a>
|
</a>
|
||||||
</div>
|
|
||||||
</button>
|
|
||||||
</nav>
|
</nav>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -43,4 +97,5 @@
|
|||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</article>
|
</article>
|
||||||
|
{/if}
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { onMount } from "svelte";
|
||||||
import BaseLayout from "../layouts/BaseLayout.svelte";
|
import BaseLayout from "../layouts/BaseLayout.svelte";
|
||||||
|
import { pbClient, authUserID } from '../store'
|
||||||
|
|
||||||
|
let userName = "";
|
||||||
|
|
||||||
|
onMount(async ()=>{
|
||||||
|
const user = await pbClient.users.getOne($authUserID);
|
||||||
|
userName = user.profile.name;
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<BaseLayout>
|
<BaseLayout>
|
||||||
<div>
|
<div>
|
||||||
Home
|
Welcome: {userName}
|
||||||
</div>
|
</div>
|
||||||
</BaseLayout>
|
</BaseLayout>
|
||||||
|
|
||||||
|
@ -1,11 +1,14 @@
|
|||||||
<script>
|
<script>
|
||||||
import { replace } from 'svelte-spa-router';
|
import { replace } from 'svelte-spa-router';
|
||||||
import { isAuthed } from '../store';
|
|
||||||
import NoNavLayout from '../layouts/NoNavLayout.svelte';
|
import NoNavLayout from '../layouts/NoNavLayout.svelte';
|
||||||
|
import { pbClient, authUserID } from '../store';
|
||||||
|
|
||||||
function doLogin(){
|
let userName = "";
|
||||||
|
let userPassword = "";
|
||||||
|
|
||||||
|
async function doLogin(){
|
||||||
|
const userAuthData = await pbClient.users.authViaEmail(userName, userPassword);
|
||||||
replace("/");
|
replace("/");
|
||||||
isAuthed.set(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@ -17,12 +20,12 @@
|
|||||||
|
|
||||||
<p>Username:</p>
|
<p>Username:</p>
|
||||||
<div class="field border">
|
<div class="field border">
|
||||||
<input type="text">
|
<input bind:value={userName} type="text">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Password:</p>
|
<p>Password:</p>
|
||||||
<div class="field border">
|
<div class="field border">
|
||||||
<input type="text">
|
<input bind:value={userPassword} type="password">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="responsive" on:click={doLogin}>
|
<button class="responsive" on:click={doLogin}>
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
import { writable } from 'svelte/store';
|
import { writable } from 'svelte/store';
|
||||||
|
import PocketBase from 'pocketbase';
|
||||||
|
export const pbClient = new PocketBase('https://pb.thomaspcole.com');
|
||||||
|
|
||||||
export const isAuthed = writable(false);
|
|
||||||
export const activeNav = writable(0);
|
export const activeNav = writable(0);
|
||||||
|
export const authUserID = writable("");
|
||||||
|
|
||||||
|
|
||||||
export function resetStore() {
|
export function resetStore() {
|
||||||
isAuthed.set(false);
|
pbClient.authStore.clear();
|
||||||
activeNav.set(0);
|
activeNav.set(0);
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user