mirror of
https://github.com/JonasunderscoreJones/dash.jonasjones.dev.git
synced 2025-10-23 07:09:19 +02:00
initial project structure
This commit is contained in:
commit
3976aa6566
24 changed files with 1941 additions and 0 deletions
57
src/routes/+layout.svelte
Normal file
57
src/routes/+layout.svelte
Normal file
|
@ -0,0 +1,57 @@
|
|||
<script>
|
||||
import Header from './Header.svelte';
|
||||
import '../app.css';
|
||||
|
||||
let { children } = $props();
|
||||
</script>
|
||||
|
||||
<div class="app">
|
||||
<Header />
|
||||
|
||||
<main>
|
||||
{@render children()}
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<p>
|
||||
visit <a href="https://svelte.dev/docs/kit">svelte.dev/docs/kit</a> to learn about SvelteKit
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.app {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
main {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 1rem;
|
||||
width: 100%;
|
||||
max-width: 64rem;
|
||||
margin: 0 auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
footer {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
footer a {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@media (min-width: 480px) {
|
||||
footer {
|
||||
padding: 12px 0;
|
||||
}
|
||||
}
|
||||
</style>
|
3
src/routes/+page.js
Normal file
3
src/routes/+page.js
Normal file
|
@ -0,0 +1,3 @@
|
|||
// since there's no dynamic data here, we can prerender
|
||||
// it so that it gets served as a static asset in production
|
||||
export const prerender = true;
|
17
src/routes/+page.svelte
Normal file
17
src/routes/+page.svelte
Normal file
|
@ -0,0 +1,17 @@
|
|||
<script>
|
||||
import { onMount } from 'svelte';
|
||||
import { ensureAuthenticated } from '../utils/session.js';
|
||||
|
||||
onMount(() => {
|
||||
ensureAuthenticated(); // This will check the session key and redirect if necessary
|
||||
});
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Home</title>
|
||||
<meta name="description" content="Svelte demo app" />
|
||||
</svelte:head>
|
||||
|
||||
<h2>Welcome to the Dashboard</h2>
|
||||
|
||||
<p>You are logged in and have access to this page.</p>
|
129
src/routes/Header.svelte
Normal file
129
src/routes/Header.svelte
Normal file
|
@ -0,0 +1,129 @@
|
|||
<script>
|
||||
import { page } from '$app/state';
|
||||
import logo from '$lib/images/svelte-logo.svg';
|
||||
import github from '$lib/images/github.svg';
|
||||
</script>
|
||||
|
||||
<header>
|
||||
<div class="corner">
|
||||
<a href="https://svelte.dev/docs/kit">
|
||||
<img src={logo} alt="SvelteKit" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<nav>
|
||||
<svg viewBox="0 0 2 3" aria-hidden="true">
|
||||
<path d="M0,0 L1,2 C1.5,3 1.5,3 2,3 L2,0 Z" />
|
||||
</svg>
|
||||
<ul>
|
||||
<li aria-current={page.url.pathname === '/' ? 'page' : undefined}>
|
||||
<a href="/">Home</a>
|
||||
</li>
|
||||
<li aria-current={page.url.pathname === '/about' ? 'page' : undefined}>
|
||||
<a href="/about">About</a>
|
||||
</li>
|
||||
<li aria-current={page.url.pathname.startsWith('/sverdle') ? 'page' : undefined}>
|
||||
<a href="/sverdle">Sverdle</a>
|
||||
</li>
|
||||
</ul>
|
||||
<svg viewBox="0 0 2 3" aria-hidden="true">
|
||||
<path d="M0,0 L0,3 C0.5,3 0.5,3 1,2 L2,0 Z" />
|
||||
</svg>
|
||||
</nav>
|
||||
|
||||
<div class="corner">
|
||||
<a href="https://github.com/sveltejs/kit">
|
||||
<img src={github} alt="GitHub" />
|
||||
</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<style>
|
||||
header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.corner {
|
||||
width: 3em;
|
||||
height: 3em;
|
||||
}
|
||||
|
||||
.corner a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.corner img {
|
||||
width: 2em;
|
||||
height: 2em;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
--background: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 2em;
|
||||
height: 3em;
|
||||
display: block;
|
||||
}
|
||||
|
||||
path {
|
||||
fill: var(--background);
|
||||
}
|
||||
|
||||
ul {
|
||||
position: relative;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
height: 3em;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
list-style: none;
|
||||
background: var(--background);
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
li[aria-current='page']::before {
|
||||
--size: 6px;
|
||||
content: '';
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: calc(50% - var(--size));
|
||||
border: var(--size) solid transparent;
|
||||
border-top: var(--size) solid var(--color-theme-1);
|
||||
}
|
||||
|
||||
nav a {
|
||||
display: flex;
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
padding: 0 0.5rem;
|
||||
color: var(--color-text);
|
||||
font-weight: 700;
|
||||
font-size: 0.8rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.1em;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s linear;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
color: var(--color-theme-1);
|
||||
}
|
||||
</style>
|
9
src/routes/about/+page.js
Normal file
9
src/routes/about/+page.js
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { dev } from '$app/environment';
|
||||
|
||||
// we don't need any JS on this page, though we'll load
|
||||
// it in dev so that we get hot module replacement
|
||||
export const csr = dev;
|
||||
|
||||
// since there's no dynamic data here, we can prerender
|
||||
// it so that it gets served as a static asset in production
|
||||
export const prerender = true;
|
26
src/routes/about/+page.svelte
Normal file
26
src/routes/about/+page.svelte
Normal file
|
@ -0,0 +1,26 @@
|
|||
<svelte:head>
|
||||
<title>About</title>
|
||||
<meta name="description" content="About this app" />
|
||||
</svelte:head>
|
||||
|
||||
<div class="text-column">
|
||||
<h1>About this app</h1>
|
||||
|
||||
<p>
|
||||
This is a <a href="https://svelte.dev/docs/kit">SvelteKit</a> app. You can make your own by typing
|
||||
the following into your command line and following the prompts:
|
||||
</p>
|
||||
|
||||
<pre>npx sv create</pre>
|
||||
|
||||
<p>
|
||||
The page you're looking at is purely static HTML, with no client-side interactivity needed.
|
||||
Because of that, we don't need to load any JavaScript. Try viewing the page's source, or opening
|
||||
the devtools network panel and reloading.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="/sverdle">Sverdle</a> page illustrates SvelteKit's data loading and form handling. Try
|
||||
using it with JavaScript disabled!
|
||||
</p>
|
||||
</div>
|
47
src/routes/login/+page.svelte
Normal file
47
src/routes/login/+page.svelte
Normal file
|
@ -0,0 +1,47 @@
|
|||
<script>
|
||||
import { navigate } from 'svelte-routing';
|
||||
import { setSessionKey } from '../../utils/session.js';
|
||||
let username = '';
|
||||
let password = '';
|
||||
let errorMessage = '';
|
||||
|
||||
const handleLogin = async () => {
|
||||
try {
|
||||
const response = await fetch('https://your-backend-api/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ username, password }),
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.sessionKey) {
|
||||
// Set session key as a cookie
|
||||
setSessionKey(data.sessionKey);
|
||||
// Get the return URL from query parameters
|
||||
const returnUrl = new URLSearchParams(window.location.search).get('returnUrl') || '/';
|
||||
navigate(returnUrl); // Redirect back to the requested path
|
||||
} else {
|
||||
errorMessage = 'Invalid login credentials';
|
||||
}
|
||||
} catch (error) {
|
||||
errorMessage = 'Error logging in. Please try again later.';
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<h2>Login</h2>
|
||||
|
||||
{#if errorMessage}
|
||||
<p style="color: red;">{errorMessage}</p>
|
||||
{/if}
|
||||
|
||||
<form on:submit|preventDefault={handleLogin}>
|
||||
<label for="username">Username:</label>
|
||||
<input id="username" bind:value={username} required />
|
||||
|
||||
<label for="password">Password:</label>
|
||||
<input type="password" id="password" bind:value={password} required />
|
||||
|
||||
<button type="submit">Login</button>
|
||||
</form>
|
Loading…
Add table
Add a link
Reference in a new issue