177 lines
4.8 KiB
Svelte
177 lines
4.8 KiB
Svelte
<script>
|
|
import MainInput from './lib/MainInput.svelte'
|
|
import Note from './lib/Note.svelte'
|
|
import Actions from './lib/Actions.svelte'
|
|
|
|
import Storage from './storage'
|
|
import {createNote, toggleDoneState, applyFilterSort} from './note'
|
|
|
|
const storage = new Storage()
|
|
let notes = storage.getNotes()
|
|
let filter = storage.getFilter()
|
|
let theme = storage.getTheme()
|
|
let shownNotes = applyFilterSort(notes, filter)
|
|
let hasNotes = notes.length > 0
|
|
|
|
$: hasFinishedNotes = notes.filter(note => !note.done).length === notes.length
|
|
$: darkMode = theme === "dark"
|
|
$: document.body.className = theme;
|
|
|
|
function handleNewNote(e) {
|
|
notes.push(createNote(e.detail))
|
|
notes = notes // Trigger reactiveness
|
|
shownNotes = applyFilterSort(notes, filter)
|
|
|
|
storage.saveNotes(notes)
|
|
}
|
|
|
|
function handleToggle(e) {
|
|
notes = toggleDoneState(notes, e.detail.created)
|
|
shownNotes = applyFilterSort(notes, filter)
|
|
|
|
storage.saveNotes(notes)
|
|
}
|
|
|
|
function handleFilter(e) {
|
|
filter = e.detail
|
|
shownNotes = applyFilterSort(notes, filter)
|
|
|
|
storage.saveFilter(filter)
|
|
}
|
|
|
|
function handleClearDone(e) {
|
|
notes = notes.filter(note => {
|
|
const ids = shownNotes.map(note => note.created)
|
|
const noteShown = ids.includes(note.created)
|
|
const noteDone = note.done
|
|
return !(noteDone && noteShown)
|
|
})
|
|
shownNotes = applyFilterSort(notes, filter)
|
|
|
|
storage.saveNotes(notes)
|
|
}
|
|
|
|
function handleClearFilter(e) {
|
|
filter = ''
|
|
shownNotes = applyFilterSort(notes, '')
|
|
|
|
storage.saveFilter('')
|
|
}
|
|
|
|
function handleToggleDarkMode(e) {
|
|
console.log("Dark Mode: " + !darkMode)
|
|
theme = theme === "dark" ? "" : "dark"
|
|
|
|
storage.saveTheme(theme)
|
|
}
|
|
</script>
|
|
|
|
<svelte:head>
|
|
<title>Todo</title>
|
|
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>🎯</text></svg>">
|
|
</svelte:head>
|
|
|
|
<main>
|
|
<h1>
|
|
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" class="bi bi-patch-check" viewBox="0 0 16 16">
|
|
<path fill-rule="evenodd" d="M10.354 6.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7 8.793l2.646-2.647a.5.5 0 0 1 .708 0z"/>
|
|
<path d="m10.273 2.513-.921-.944.715-.698.622.637.89-.011a2.89 2.89 0 0 1 2.924 2.924l-.01.89.636.622a2.89 2.89 0 0 1 0 4.134l-.637.622.011.89a2.89 2.89 0 0 1-2.924 2.924l-.89-.01-.622.636a2.89 2.89 0 0 1-4.134 0l-.622-.637-.89.011a2.89 2.89 0 0 1-2.924-2.924l.01-.89-.636-.622a2.89 2.89 0 0 1 0-4.134l.637-.622-.011-.89a2.89 2.89 0 0 1 2.924-2.924l.89.01.622-.636a2.89 2.89 0 0 1 4.134 0l-.715.698a1.89 1.89 0 0 0-2.704 0l-.92.944-1.32-.016a1.89 1.89 0 0 0-1.911 1.912l.016 1.318-.944.921a1.89 1.89 0 0 0 0 2.704l.944.92-.016 1.32a1.89 1.89 0 0 0 1.912 1.911l1.318-.016.921.944a1.89 1.89 0 0 0 2.704 0l.92-.944 1.32.016a1.89 1.89 0 0 0 1.911-1.912l-.016-1.318.944-.921a1.89 1.89 0 0 0 0-2.704l-.944-.92.016-1.32a1.89 1.89 0 0 0-1.912-1.911l-1.318.016z"/>
|
|
</svg>
|
|
Just do it
|
|
</h1>
|
|
|
|
<MainInput on:added={handleNewNote} />
|
|
|
|
<section class="notes">
|
|
{#each shownNotes as note}
|
|
<Note note={note} on:toggle={handleToggle} on:filter={handleFilter} />
|
|
{/each}
|
|
</section>
|
|
|
|
<Actions
|
|
filter={filter}
|
|
hasFinishedNotes={hasFinishedNotes}
|
|
darkMode={darkMode}
|
|
on:clearDone={handleClearDone}
|
|
on:clearFilter={handleClearFilter}
|
|
on:toggleDarkMode={handleToggleDarkMode} />
|
|
|
|
<footer>
|
|
Made by <a href="https://inhji.de">Inhji</a> with svelte and vitejs. <a href="https://git.inhji.de/projects/notes-vitejs">Check the source</a>.
|
|
</footer>
|
|
</main>
|
|
|
|
<style>
|
|
:root {
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
|
|
Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
|
|
|
|
--gray-50: #F8FAFC;
|
|
--gray-100: #F1F5F9;
|
|
--gray-200: #E2E8F0;
|
|
--gray-300: #CBD5E1;
|
|
--gray-400: #94A3B8;
|
|
--gray-500: #64748B;
|
|
--gray-600: #475569;
|
|
--gray-700: #334155;
|
|
--gray-800: #1E293B;
|
|
--gray-900: #0F172A;
|
|
}
|
|
|
|
:global(.dark) {
|
|
--gray-50: #0F172A;
|
|
--gray-100: #1E293B;
|
|
--gray-200: #334155;
|
|
--gray-300: #475569;
|
|
--gray-400: #64748B;
|
|
--gray-500: #94A3B8;
|
|
--gray-600: #CBD5E1;
|
|
--gray-700: #E2E8F0;
|
|
--gray-800: #F1F5F9;
|
|
--gray-900: #F8FAFC;
|
|
}
|
|
|
|
:global(body) {
|
|
padding: 0;
|
|
margin: 0;
|
|
color: var(--gray-800);
|
|
background: var(--gray-100);
|
|
transition: 0.1s ease-in all;
|
|
}
|
|
|
|
main {
|
|
padding: 2rem;
|
|
max-width: 50rem;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
footer {
|
|
color: var(--gray-400);
|
|
font-size: 90%;
|
|
text-align: center;
|
|
padding: 1rem;
|
|
}
|
|
|
|
.notes {
|
|
margin: 0.5rem 0;
|
|
}
|
|
|
|
a {
|
|
color: var(--gray-500);
|
|
}
|
|
|
|
h1 {
|
|
color: var(--gray-900);
|
|
font-weight: 300;
|
|
text-align: left;
|
|
letter-spacing: 1px;
|
|
}
|
|
|
|
h1 svg {
|
|
width: 1.5rem;
|
|
margin-bottom: -1px;
|
|
color: var(--gray-700);
|
|
|
|
}
|
|
</style>
|