mirror of
https://github.com/BradNut/svelteKitForBeginners
synced 2025-09-08 17:40:24 +00:00
Adding settings pages with default text, about page that is static, and a form action fully typed used in all form elements. If JS exists then use fetch otherwise default to regular HTML form ways.
This commit is contained in:
parent
9d13216fea
commit
4324a70a7a
10 changed files with 253 additions and 3 deletions
|
|
@ -1,4 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { enhance } from '$root/lib/form'
|
||||
|
||||
let tweet = ''
|
||||
let maxCharacters = 140
|
||||
|
||||
|
|
@ -8,7 +10,14 @@
|
|||
<div class="compose">
|
||||
<img src="/profile/matia/avatar.webp" alt="Avatar">
|
||||
|
||||
<form action="/home" method="post" autocomplete="off">
|
||||
<form
|
||||
action="/home"
|
||||
method="post"
|
||||
autocomplete="off"
|
||||
use:enhance={{
|
||||
result: ({ form }) => form.reset()
|
||||
}}
|
||||
>
|
||||
<input
|
||||
aria-label="Enter your tweet"
|
||||
bind:value={tweet}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<script lang="ts">
|
||||
import { fade, fly } from 'svelte/transition'
|
||||
|
||||
import { enhance } from '$root/lib/form'
|
||||
import Icon from '$root/components/icon.svelte'
|
||||
import type { TweetType } from '$root/types'
|
||||
|
||||
|
|
@ -32,7 +33,11 @@
|
|||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<form action="/home/like" method="post">
|
||||
<form
|
||||
action="/home/like"
|
||||
method="post"
|
||||
use:enhance
|
||||
>
|
||||
<input type="hidden" name="id" value={tweet.id} />
|
||||
<button
|
||||
class="btn like"
|
||||
|
|
@ -72,7 +77,11 @@
|
|||
</div>
|
||||
</a>
|
||||
|
||||
<form action="/home?_method=delete" method="post">
|
||||
<form
|
||||
action="/home?_method=delete"
|
||||
method="post"
|
||||
use:enhance
|
||||
>
|
||||
<input type="hidden" name="id" value={tweet.id} />
|
||||
<button
|
||||
aria-label="Remove tweet"
|
||||
|
|
|
|||
48
src/lib/form.ts
Normal file
48
src/lib/form.ts
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
import { invalidate } from "$app/navigation"
|
||||
import { page } from "$app/stores"
|
||||
|
||||
type Parameters = {
|
||||
result?: ({ form }: { form: HTMLFormElement }) => void
|
||||
}
|
||||
type Destroy = { destroy: () => void }
|
||||
type Enhance = (
|
||||
form?: HTMLFormElement,
|
||||
{ result }?: Parameters
|
||||
) => Destroy
|
||||
|
||||
export const enhance: Enhance = (form, { result } = {}) => {
|
||||
let invalidatePath: URL
|
||||
|
||||
page.subscribe((path) => {
|
||||
invalidatePath = path.url
|
||||
})
|
||||
|
||||
async function handleSubmit(event: Event) {
|
||||
event.preventDefault()
|
||||
const response = await fetch(form.action, {
|
||||
method: form.method,
|
||||
headers: { accept: 'application/json' },
|
||||
body: new FormData(form)
|
||||
})
|
||||
|
||||
if (!response.ok) {
|
||||
console.error(await response.text());
|
||||
}
|
||||
|
||||
const url = new URL(invalidatePath)
|
||||
url.search = ''
|
||||
url.hash = ''
|
||||
invalidate(url.href)
|
||||
|
||||
if (result) {
|
||||
result({ form })
|
||||
}
|
||||
}
|
||||
form.addEventListener('submit', handleSubmit)
|
||||
|
||||
return {
|
||||
destroy() {
|
||||
form.removeEventListener('submit', handleSubmit)
|
||||
}
|
||||
}
|
||||
}
|
||||
38
src/routes/home/about/index.svelte
Normal file
38
src/routes/home/about/index.svelte
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
<script context="module" lang="ts">
|
||||
import { dev } from '$app/env'
|
||||
|
||||
export const hydrate = dev
|
||||
export const prerender = true
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>About</title>
|
||||
</svelte:head>
|
||||
|
||||
<div class="container">
|
||||
<h1>About</h1>
|
||||
<div class="content">
|
||||
<p>Lorem ipsum dolor sit amet consectetur adipisicing elit. Molestiae mollitia, dolores consequatur quos hic commodi eum eius ex et laudantium quia dolore quidem aliquid tempore sit. A natus dolor sed!</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
h1 {
|
||||
font-size: var(--font-24);
|
||||
}
|
||||
|
||||
p {
|
||||
color: var(--color-text-muted);
|
||||
}
|
||||
|
||||
.container {
|
||||
display: grid;
|
||||
gap: var(--spacing-8);
|
||||
padding: var(--spacing-16);
|
||||
}
|
||||
|
||||
.content {
|
||||
display: grid;
|
||||
gap: var(--spacing-16);
|
||||
}
|
||||
</style>
|
||||
123
src/routes/home/settings/__layout.reset.svelte
Normal file
123
src/routes/home/settings/__layout.reset.svelte
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import Navigation from '$root/components/navigation.svelte';
|
||||
|
||||
$: path = $page.url.pathname
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<Navigation />
|
||||
|
||||
<main class="settings">
|
||||
<h1 class="title">Settings</h1>
|
||||
|
||||
<section class="privacy">
|
||||
<h2>Privacy</h2>
|
||||
<a
|
||||
class:active={
|
||||
path === '/home/settings/personalization'
|
||||
}
|
||||
href="/home/settings/personalization"
|
||||
>
|
||||
Personalization and data
|
||||
</a>
|
||||
<a
|
||||
class:active={
|
||||
path === '/home/settings/data'
|
||||
}
|
||||
href="/home/settings/data"
|
||||
>
|
||||
Your Twitttr data
|
||||
</a>
|
||||
<a
|
||||
class:active={
|
||||
path === '/home/settings/cookies'
|
||||
}
|
||||
href="/home/settings/cookies"
|
||||
>
|
||||
Cookie preferences
|
||||
</a>
|
||||
</section>
|
||||
|
||||
<section class="general">
|
||||
<h2>General</h2>
|
||||
<a
|
||||
class:active={
|
||||
path === '/home/settings/resources'
|
||||
}
|
||||
href="/home/settings/resources"
|
||||
>
|
||||
Additional resources
|
||||
</a>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<aside>
|
||||
<slot />
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.container {
|
||||
height: 100vh;
|
||||
max-width: min-content;
|
||||
margin: 0 auto;
|
||||
display: grid;
|
||||
grid-template-columns: min-content 50ch;
|
||||
}
|
||||
|
||||
.settings {
|
||||
display: grid;
|
||||
grid-auto-rows: min-content;
|
||||
gap: var(--spacing-24);
|
||||
border: 1px solid var(--color-border-primary);
|
||||
border-top: none;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.privacy,
|
||||
.general {
|
||||
display: grid;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: var(--font-18);
|
||||
margin-top: var(--spacing-24);
|
||||
padding: 0 var(--spacing-16);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: var(--font-24);
|
||||
padding: 0 var(--spacing-16);
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-bottom: var(--spacing-16);
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 1.4rem var(--spacing-16);
|
||||
}
|
||||
|
||||
.active {
|
||||
background: var(--color-link-hover);
|
||||
}
|
||||
|
||||
aside {
|
||||
display: none;
|
||||
padding: var(--spacing-16);
|
||||
}
|
||||
|
||||
@media (min-width: 1024px) {
|
||||
.container {
|
||||
max-width: 1240px;
|
||||
margin: 0 auto;
|
||||
grid-template-columns: 1fr 50ch 1fr;
|
||||
}
|
||||
|
||||
aside {
|
||||
width: 400px;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
5
src/routes/home/settings/cookies.svelte
Normal file
5
src/routes/home/settings/cookies.svelte
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svelte:head>
|
||||
<title>Settings | Cookies</title>
|
||||
</svelte:head>
|
||||
|
||||
<h3>Cookie preferences</h3>
|
||||
5
src/routes/home/settings/data.svelte
Normal file
5
src/routes/home/settings/data.svelte
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svelte:head>
|
||||
<title>Settings | Data</title>
|
||||
</svelte:head>
|
||||
|
||||
<h3>Your Twitter data</h3>
|
||||
3
src/routes/home/settings/index.svelte
Normal file
3
src/routes/home/settings/index.svelte
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svelte:head>
|
||||
<title>Settings</title>
|
||||
</svelte:head>
|
||||
5
src/routes/home/settings/personalization.svelte
Normal file
5
src/routes/home/settings/personalization.svelte
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svelte:head>
|
||||
<title>Settings | Personalization</title>
|
||||
</svelte:head>
|
||||
|
||||
<h3>Personalization and data</h3>
|
||||
5
src/routes/home/settings/resources.svelte
Normal file
5
src/routes/home/settings/resources.svelte
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
<svelte:head>
|
||||
<title>Settings | Resources</title>
|
||||
</svelte:head>
|
||||
|
||||
<h3>Additional resources</h3>
|
||||
Loading…
Reference in a new issue