commit 9a4659fafc0ee03d15d903b6afb4e52f34b4c427
parent a5252e2e8b65d8611e7b9f706a356ec532fe160c
Author: ashermorgan <59518073+ashermorgan@users.noreply.github.com>
Date: Thu, 26 Aug 2021 12:14:18 -0700
Save time table targets in localStorage
Diffstat:
5 files changed, 122 insertions(+), 18 deletions(-)
diff --git a/src/assets/rotate-ccw.svg b/src/assets/rotate-ccw.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-rotate-ccw"><polyline points="1 4 1 10 7 10"></polyline><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"></path></svg>
diff --git a/src/components/TimeTable.vue b/src/components/TimeTable.vue
@@ -46,6 +46,9 @@
<th>Edit Targets</th>
<th>
+ <button class="icon" title="Reset Targets" @click="resetTargets">
+ <img alt="" src="@/assets/rotate-ccw.svg">
+ </button>
<button class="icon" title="Close" @click="inEditMode=false">
<img alt="" src="@/assets/x.svg">
</button>
@@ -73,7 +76,7 @@
</tr>
<tr v-if="targets.length === 0" class="empty-message">
- <td colspan="4">
+ <td colspan="2">
There aren't any targets,<br>
click
<img alt="Add Target" src="@/assets/plus-circle.svg">
@@ -84,9 +87,9 @@
<tfoot>
<tr>
- <td colspan="4">
+ <td colspan="2">
<button class="icon" title="Add Target" @click="targets.push({distanceValue: 1,
- distanceUnit: 'miles'})">
+ distanceUnit: 'miles'})">
<img alt="" src="@/assets/plus-circle.svg">
</button>
</td>
@@ -98,6 +101,7 @@
<script>
import unitUtils from '@/utils/units';
+import storage from '@/utils/localStorage';
import DecimalInput from '@/components/DecimalInput.vue';
@@ -124,6 +128,14 @@ export default {
type: Array,
default: () => [],
},
+
+ /**
+ * The localStorage key for the list of targets
+ */
+ storageKey: {
+ type: String,
+ default: null,
+ },
},
data() {
@@ -151,7 +163,7 @@ export default {
/**
* The time table targets
*/
- targets: this.defaultTargets,
+ targets: storage.get(this.storageKey, this.defaultTargets),
};
},
@@ -174,6 +186,55 @@ export default {
return result;
},
},
+
+ watch: {
+ /**
+ * Sort targets
+ */
+ inEditMode() {
+ this.sortTargets();
+ },
+
+ /**
+ * Save targets
+ */
+ targets: {
+ handler(newValue) {
+ if (this.storageKey !== null) {
+ storage.set(this.storageKey, newValue);
+ }
+ },
+ deep: true,
+ },
+ },
+
+ methods: {
+ /**
+ * Restore the default targets
+ */
+ resetTargets() {
+ // Clone default targets array
+ this.targets = JSON.parse(JSON.stringify(this.defaultTargets));
+
+ // Sort targets
+ this.sortTargets();
+ },
+
+ /**
+ * Sort the targets by distance
+ */
+ sortTargets() {
+ this.targets.sort((a, b) => unitUtils.convertDistance(a.distanceValue, a.distanceUnit,
+ 'meters') - unitUtils.convertDistance(b.distanceValue, b.distanceUnit, 'meters'));
+ },
+ },
+
+ /**
+ * Close edit targets table
+ */
+ deactivated() {
+ this.inEditMode = false;
+ },
};
</script>
diff --git a/src/utils/localStorage.js b/src/utils/localStorage.js
@@ -0,0 +1,38 @@
+// The global localStorage prefix
+const prefix = 'running-tools';
+
+/**
+ * Get the value of a key from localStorage
+ * @param {String} key The key
+ * @param {Object} defaultValue The default value
+ * @returns {Object} The value
+ */
+function get(key, defaultValue) {
+ // Clone defaultValue
+ const clonedDefault = JSON.parse(JSON.stringify(defaultValue));
+
+ if (key === null) {
+ return clonedDefault;
+ }
+ let value;
+ try {
+ value = JSON.parse(localStorage.getItem(`${prefix}.${key}`));
+ } catch {
+ return clonedDefault;
+ }
+ return value === null ? clonedDefault : value;
+}
+
+/**
+ * Set the value of a key in localStorage
+ * @param {String} key The key
+ * @param {Object} value The value
+ * */
+function set(key, value) {
+ localStorage.setItem(`${prefix}.${key}`, JSON.stringify(value));
+}
+
+export default {
+ get,
+ set,
+};
diff --git a/src/views/PaceCalculator.vue b/src/views/PaceCalculator.vue
@@ -15,7 +15,8 @@
<p>is the same pace as running</p>
- <time-table class="output" :calculate-result="calculatePace" :default-targets="defaultTargets"/>
+ <time-table class="output" :calculate-result="calculatePace" :default-targets="defaultTargets"
+ storage-key="pace-calculator-targets"/>
</div>
</template>
@@ -74,12 +75,6 @@ export default {
{ distanceValue: 1600, distanceUnit: 'meters' },
{ distanceValue: 3200, distanceUnit: 'meters' },
- { distanceValue: 1, distanceUnit: 'miles' },
- { distanceValue: 2, distanceUnit: 'miles' },
- { distanceValue: 3, distanceUnit: 'miles' },
- { distanceValue: 5, distanceUnit: 'miles' },
- { distanceValue: 10, distanceUnit: 'miles' },
-
{ distanceValue: 2, distanceUnit: 'kilometers' },
{ distanceValue: 3, distanceUnit: 'kilometers' },
{ distanceValue: 4, distanceUnit: 'kilometers' },
@@ -89,6 +84,14 @@ export default {
{ distanceValue: 10, distanceUnit: 'kilometers' },
{ distanceValue: 15, distanceUnit: 'kilometers' },
+ { distanceValue: 1, distanceUnit: 'miles' },
+ { distanceValue: 2, distanceUnit: 'miles' },
+ { distanceValue: 3, distanceUnit: 'miles' },
+ { distanceValue: 5, distanceUnit: 'miles' },
+ { distanceValue: 6, distanceUnit: 'miles' },
+ { distanceValue: 8, distanceUnit: 'miles' },
+ { distanceValue: 10, distanceUnit: 'miles' },
+
{ distanceValue: 0.5, distanceUnit: 'marathons' },
{ distanceValue: 1, distanceUnit: 'marathons' },
],
diff --git a/src/views/RaceCalculator.vue b/src/views/RaceCalculator.vue
@@ -14,7 +14,8 @@
<p>is approximately equivalent to running</p>
- <time-table class="output" :calculate-result="predictTime" :default-targets="defaultTargets"/>
+ <time-table class="output" :calculate-result="predictTime" :default-targets="defaultTargets"
+ storage-key="race-calculator-targets"/>
</div>
</template>
@@ -69,18 +70,18 @@ export default {
{ distanceValue: 1600, distanceUnit: 'meters' },
{ distanceValue: 3200, distanceUnit: 'meters' },
- { distanceValue: 1, distanceUnit: 'miles' },
- { distanceValue: 2, distanceUnit: 'miles' },
- { distanceValue: 3, distanceUnit: 'miles' },
- { distanceValue: 5, distanceUnit: 'miles' },
- { distanceValue: 10, distanceUnit: 'miles' },
-
{ distanceValue: 3, distanceUnit: 'kilometers' },
{ distanceValue: 5, distanceUnit: 'kilometers' },
{ distanceValue: 8, distanceUnit: 'kilometers' },
{ distanceValue: 10, distanceUnit: 'kilometers' },
{ distanceValue: 15, distanceUnit: 'kilometers' },
+ { distanceValue: 1, distanceUnit: 'miles' },
+ { distanceValue: 2, distanceUnit: 'miles' },
+ { distanceValue: 3, distanceUnit: 'miles' },
+ { distanceValue: 5, distanceUnit: 'miles' },
+ { distanceValue: 10, distanceUnit: 'miles' },
+
{ distanceValue: 0.5, distanceUnit: 'marathons' },
{ distanceValue: 1, distanceUnit: 'marathons' },
],