Remove click counter and save

Add option to automatically save history
Create edit dialog
Reset to inital value
This commit is contained in:
CheddarCrisp 2020-02-16 09:02:59 -05:00
parent 956b524a8b
commit 76557c7428
4 changed files with 86 additions and 79 deletions

View file

@ -8,9 +8,9 @@
<div class="dialog"> <div class="dialog">
<div class="dialog-content"> <div class="dialog-content">
<label>Name: <input type="text" bind:value={newCounter.title} use:focus/></label> <label>Name: <input type="text" bind:value={newCounter.title} use:focus/></label>
<label>Initial Value: <input type="number" bind:value={newCounter.value} /></label> <label>Initial Value: <input type="number" bind:value={newCounter.initialValue} /></label>
<label>Target: <input type="number" bind:value={newCounter.max} /></label> <label>Target: <input type="number" bind:value={newCounter.max} /></label>
<label>Click counter: <input type="checkbox" bind:value={newCounter.isClickCounter} /></label> <label>Save history: <input type="checkbox" bind:checked={newCounter.saveHistory} /></label>
<button on:click={ () => { showAddDialog = false; } }>Cancel</button> <button on:click={ () => { showAddDialog = false; } }>Cancel</button>
<button class="ok" on:click={ add }>OK</button> <button class="ok" on:click={ add }>OK</button>
</div> </div>
@ -28,15 +28,11 @@ function focus(node){
node.focus(); node.focus();
} }
function save(counter){
alert('Save ' + counter.title);
}
function showAdd(){ function showAdd(){
newCounter = { newCounter = {
title: '', title: '',
value: 0, initialValue: 0,
isClickCounter: false, saveHistory: false,
history: [] history: []
} }
@ -44,7 +40,12 @@ function showAdd(){
} }
function add(){ function add(){
counters.add(newCounter); const counter = {
...newCounter,
value: newCounter.initialValue
}
counters.add(counter);
showAddDialog = false; showAddDialog = false;
} }
@ -67,16 +68,6 @@ function add(){
color: white; color: white;
} }
.dialog-content > label {
display: flex;
width: 100%;
margin-bottom: 5px;
}
.dialog-content > label > input {
margin-left: auto;
}
.ok { .ok {
margin-left: auto; margin-left: auto;
} }

View file

@ -1,20 +1,17 @@
<div class="counter" on:click="{ clickCount }"> <div class="counter">
<header>{ counter.title }</header> <header>{ counter.title }</header>
<span class="value">{ counter.value }</span> <span class="value">{ counter.value }</span>
{#if counter.max} {#if counter.max}
<MyProgress value={ counter.value } max={ counter.max }></MyProgress> <MyProgress value={ counter.value } max={ counter.max }></MyProgress>
{/if} {/if}
<div class="controls"> <div class="controls">
{#if !counter.isClickCounter}
<button on:click={ () => { showIncrement = true; } }><i class="material-icons">add</i></button> <button on:click={ () => { showIncrement = true; } }><i class="material-icons">add</i></button>
<button on:click={ () => { showSet = true; } }><i class="material-icons">create</i></button> <button on:click={ () => { showSet = true; } }><i class="material-icons">edit</i></button>
{/if}
<span class="message">{ message }</span>
<button class="reset" on:click={ reset }><i class="material-icons">undo</i></button> <button class="reset" on:click={ reset }><i class="material-icons">undo</i></button>
<button on:click={ save }><i class="material-icons">save</i></button> <button on:click={ startEdit }><i class="material-icons">edit</i></button>
<button on:click={ remove }><i class="material-icons">delete</i></button> <button on:click={ remove }><i class="material-icons">delete</i></button>
</div> </div>
{#if showDialog} {#if showValueDialog}
<div class="dialog"> <div class="dialog">
<div class="dialog-content"> <div class="dialog-content">
<h1>{ showIncrement ? "Add" : "Set" }</h1> <h1>{ showIncrement ? "Add" : "Set" }</h1>
@ -23,7 +20,19 @@
<button class="ok" on:click={ dialogDone }>OK</button> <button class="ok" on:click={ dialogDone }>OK</button>
</div> </div>
</div> </div>
{/if} {/if}
{#if showEditDialog}
<div class="dialog">
<div class="dialog-content">
<label>Name: <input type="text" bind:value={editingCounter.title} use:focus/></label>
<label>Initial Value: <input type="number" bind:value={editingCounter.initialValue} /></label>
<label>Target: <input type="number" bind:value={editingCounter.max} /></label>
<label>Save history: <input type="checkbox" bind:checked={editingCounter.saveHistory} /></label>
<button on:click={ () => { showEditDialog = false; } }>Cancel</button>
<button class="ok" on:click={ finishEdit }>OK</button>
</div>
</div>
{/if}
</div> </div>
<script> <script>
import MyProgress from './MyProgress.svelte'; import MyProgress from './MyProgress.svelte';
@ -40,18 +49,10 @@ $: counter = $counters.find(x => x.id == counterId);
let dialogValue; let dialogValue;
let showIncrement; let showIncrement;
let showSet; let showSet;
let message = ''; let showEditDialog;
let editingCounter;
$: showDialog = showIncrement || showSet; $: showValueDialog = showIncrement || showSet;
const formatter = new Intl.DateTimeFormat('en-US',
{
month: 'short',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: 'numeric'
});
function focus(node){ function focus(node){
node.focus(); node.focus();
@ -61,6 +62,18 @@ function update(newCounter){
counters.update(newCounter); counters.update(newCounter);
} }
function startEdit(e){
e.stopPropagation();
editingCounter = {...counter};
showEditDialog = true;
}
function finishEdit(){
update(editingCounter);
showEditDialog = false;
}
function dialogCancel(){ function dialogCancel(){
showIncrement = false; showIncrement = false;
showSet = false; showSet = false;
@ -88,50 +101,18 @@ function reset(e){
if(confirm(`Reset ${counter.title}?`)){ if(confirm(`Reset ${counter.title}?`)){
const newCounter = { const newCounter = {
...counter, ...counter,
value: 0 value: counter.initialValue
} }
update(newCounter); update(newCounter);
} }
} }
function save(e) {
e.stopPropagation();
const time = new Date();
const data = {
time,
value: counter.value
}
const newCounter = {
...counter,
history: [...counter.history, data]
}
message = `Saved ${data.value} at ${formatter.format(data.time)}`;
setTimeout(() => message = '', 5000);
update(newCounter);
}
function remove(){ function remove(){
if(confirm(`Remove ${counter.title}?`)) if(confirm(`Remove ${counter.title}?`))
counters.remove(counter); counters.remove(counter);
} }
function clickCount() {
if(!counter.isClickCounter)
return;
const newCounter = {
...counter,
value: counter.value + 1
}
update(newCounter);
}
</script> </script>
<style> <style>
.counter{ .counter{
@ -148,11 +129,6 @@ function clickCount() {
display: flex; display: flex;
} }
.message {
flex: 1;
text-align: center;
}
header { header {
font-size: 22px; font-size: 22px;
font-weight: 600; font-weight: 600;
@ -165,6 +141,10 @@ header {
margin-left: 0; margin-left: 0;
} }
.reset {
margin-left: auto;
}
.dialog-value { .dialog-value {
width: 100%; width: 100%;
margin: 5px 0; margin: 5px 0;

View file

@ -6,13 +6,37 @@ function createCounters(){
const {subscribe,set,update:updateVal} = writable([]); const {subscribe,set,update:updateVal} = writable([]);
getDb('counters').then(counters => { getDb('counters').then(counters => {
if(counters) if(counters) {
set(counters); const updatedCounters = counters.map(counter => {
return {
initialValue: 0,
showHistory: false,
...counter
}
});
set(updatedCounters);
}
}); });
function updateHistory(counter){
if(counter.saveHistory){
const time = new Date();
const data = {
time,
value: counter.value
};
counter.history = [...counter.history, data];
}
}
function add(counter){ function add(counter){
const newCounter = { id: uuid(), ...counter }; const newCounter = { id: uuid(), ...counter };
updateHistory(newCounter);
updateVal(counters => { updateVal(counters => {
const newCounters = [...counters, newCounter]; const newCounters = [...counters, newCounter];
@ -23,6 +47,8 @@ function createCounters(){
} }
function update(counter){ function update(counter){
updateHistory(counter);
updateVal(counters => { updateVal(counters => {
const counterIndex = counters.findIndex(x => x.id == counter.id); const counterIndex = counters.findIndex(x => x.id == counter.id);

View file

@ -50,7 +50,7 @@ button {
background-color: #E0E0E0; background-color: #E0E0E0;
pointer-events: all; pointer-events: all;
width: 250px; width: 300px;
border-radius: 5px; border-radius: 5px;
box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24);
@ -60,6 +60,16 @@ button {
flex-wrap: wrap; flex-wrap: wrap;
} }
.dialog-content > label {
display: flex;
width: 100%;
margin-bottom: 5px;
}
.dialog-content > label > input {
margin-left: auto;
}
input[type="text"], input[type="text"],
input[type="number"] { input[type="number"] {
font-size: 16px; font-size: 16px;