133 lines
4.5 KiB
Svelte
133 lines
4.5 KiB
Svelte
|
<script lang="ts">
|
||
|
import { notes } from '$lib';
|
||
|
import { page } from '$app/stores';
|
||
|
import { goto } from '$app/navigation';
|
||
|
import { onMount } from 'svelte';
|
||
|
import { renderMarkdown } from '$lib/markdown';
|
||
|
|
||
|
let note: any;
|
||
|
$: isEditing = $page.url.searchParams.get('edit') === 'true';
|
||
|
let editedTitle = '';
|
||
|
let editedContent = '';
|
||
|
|
||
|
$: id = $page.params.id;
|
||
|
|
||
|
onMount(() => {
|
||
|
const unsubscribe = notes.subscribe(allNotes => {
|
||
|
if (!allNotes || !id) return;
|
||
|
|
||
|
note = allNotes.find(n => n.id === id);
|
||
|
if (note) {
|
||
|
editedTitle = note.title;
|
||
|
editedContent = note.content;
|
||
|
} else if (allNotes.length > 0) {
|
||
|
// Only redirect if we have loaded notes and didn't find this one
|
||
|
goto('/');
|
||
|
}
|
||
|
});
|
||
|
return () => unsubscribe();
|
||
|
});
|
||
|
|
||
|
async function handleSave() {
|
||
|
if (!editedTitle || !editedContent) return;
|
||
|
|
||
|
try {
|
||
|
await notes.update(id, {
|
||
|
title: editedTitle,
|
||
|
content: editedContent
|
||
|
});
|
||
|
isEditing = false;
|
||
|
} catch (error) {
|
||
|
console.error('Failed to update note:', error);
|
||
|
}
|
||
|
}
|
||
|
</script>
|
||
|
|
||
|
<div class="container">
|
||
|
<section class="section">
|
||
|
{#if note}
|
||
|
{#if isEditing}
|
||
|
<form on:submit|preventDefault={handleSave}>
|
||
|
<div class="field">
|
||
|
<label class="label" for="title">Title</label>
|
||
|
<div class="control">
|
||
|
<input
|
||
|
id="title"
|
||
|
class="input"
|
||
|
type="text"
|
||
|
bind:value={editedTitle}
|
||
|
required
|
||
|
>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="field">
|
||
|
<label class="label" for="content">Content</label>
|
||
|
<div class="control">
|
||
|
<textarea
|
||
|
id="content"
|
||
|
class="textarea"
|
||
|
bind:value={editedContent}
|
||
|
rows="10"
|
||
|
required
|
||
|
></textarea>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="field is-grouped">
|
||
|
<div class="control">
|
||
|
<button type="submit" class="button is-primary">Save</button>
|
||
|
</div>
|
||
|
<div class="control">
|
||
|
<button
|
||
|
type="button"
|
||
|
class="button is-light"
|
||
|
on:click={() => {
|
||
|
isEditing = false;
|
||
|
goto(`/notes/${id}`);
|
||
|
}}
|
||
|
>
|
||
|
Cancel
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</form>
|
||
|
{:else}
|
||
|
<div class="level">
|
||
|
<div class="level-left">
|
||
|
<div class="level-item">
|
||
|
<h1 class="title">{note.title}</h1>
|
||
|
</div>
|
||
|
</div>
|
||
|
<div class="level-right">
|
||
|
<div class="level-item">
|
||
|
<button
|
||
|
class="button is-primary"
|
||
|
on:click={() => isEditing = true}
|
||
|
>
|
||
|
Edit
|
||
|
</button>
|
||
|
</div>
|
||
|
</div>
|
||
|
</div>
|
||
|
|
||
|
<div class="content">
|
||
|
{@html renderMarkdown(note.content)}
|
||
|
</div>
|
||
|
|
||
|
<p class="has-text-grey is-size-7">
|
||
|
Last updated: {note.updatedAt.toLocaleString()}
|
||
|
</p>
|
||
|
{/if}
|
||
|
{:else}
|
||
|
<div class="notification is-danger">
|
||
|
Note not found
|
||
|
</div>
|
||
|
{/if}
|
||
|
|
||
|
<div class="mt-4">
|
||
|
<a href="/" class="button is-light">Back to Notes</a>
|
||
|
</div>
|
||
|
</section>
|
||
|
</div>
|