Added alerts

This commit is contained in:
jableader 2024-09-22 08:02:21 +10:00
parent 84a76151e4
commit cc3f18ad70
7 changed files with 146 additions and 3 deletions

View file

@ -15,13 +15,19 @@
<div class="viewport">
<router-view/>
</div>
<alert-toast />
</template>
<script>
import data from './data.js'
import AlertToast from './components/AlertToast.vue'
export default {
name: 'App',
name: 'App',
components: {
'alert-toast': AlertToast
},
computed: {
currentRoute() {
return this.$route.path

10
src/alert.js Normal file
View file

@ -0,0 +1,10 @@
const subscribers = [];
export default {
subscribe(callback) {
subscribers.push(callback);
},
show(message) { // { message, heading, type: ["success", "error", "info"] }
subscribers.forEach(callback => callback(message));
}
}

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>error-filled</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="add" fill="#000000" transform="translate(42.666667, 42.666667)">
<path d="M213.333333,3.55271368e-14 C331.136,3.55271368e-14 426.666667,95.5306667 426.666667,213.333333 C426.666667,331.136 331.136,426.666667 213.333333,426.666667 C95.5306667,426.666667 3.55271368e-14,331.136 3.55271368e-14,213.333333 C3.55271368e-14,95.5306667 95.5306667,3.55271368e-14 213.333333,3.55271368e-14 Z M262.250667,134.250667 L213.333333,183.168 L164.416,134.250667 L134.250667,164.416 L183.168,213.333333 L134.250667,262.250667 L164.416,292.416 L213.333333,243.498667 L262.250667,292.416 L292.416,262.250667 L243.498667,213.333333 L292.416,164.416 L262.250667,134.250667 Z" id="Combined-Shape">
</path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M12 22c5.523 0 10-4.477 10-10S17.523 2 12 2 2 6.477 2 12s4.477 10 10 10zm-1.5-5.009c0-.867.659-1.491 1.491-1.491.85 0 1.509.624 1.509 1.491 0 .867-.659 1.509-1.509 1.509-.832 0-1.491-.642-1.491-1.509zM11.172 6a.5.5 0 0 0-.499.522l.306 7a.5.5 0 0 0 .5.478h1.043a.5.5 0 0 0 .5-.478l.305-7a.5.5 0 0 0-.5-.522h-1.655z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 607 B

View file

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>success-filled</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="add-copy-2" fill="#000000" transform="translate(42.666667, 42.666667)">
<path d="M213.333333,3.55271368e-14 C95.51296,3.55271368e-14 3.55271368e-14,95.51296 3.55271368e-14,213.333333 C3.55271368e-14,331.153707 95.51296,426.666667 213.333333,426.666667 C331.153707,426.666667 426.666667,331.153707 426.666667,213.333333 C426.666667,95.51296 331.153707,3.55271368e-14 213.333333,3.55271368e-14 Z M293.669333,137.114453 L323.835947,167.281067 L192,299.66912 L112.916693,220.585813 L143.083307,190.4192 L192,239.335893 L293.669333,137.114453 Z" id="Shape">
</path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1,014 B

View file

@ -0,0 +1,98 @@
<template>
<div v-if="showAlert" :class="['alert', type]" @click="dismiss">
<img v-if="icon" :src="icon" alt="Notification icon" />
<div class="message-container">
<h4 class="heading">{{ heading }}</h4>
<p class="message">{{ message }}</p>
</div>
</div>
</template>
<style scoped>
/* Display as a toast, in the bottom right corner */
/* Place the icon to the left for the full height, then have the heading and message stacked to the right */
.alert {
position: fixed;
bottom: 1em;
right: 1em;
display: flex;
align-items: center;
padding: 1em;
border-radius: 5px;
color: white;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.5);
text-align: left;
}
.alert img {
width: 2em;
height: 2em;
margin-right: 1em;
/* Invert svg colors */
filter: invert(1);
}
.alert.error {
background-color: #f44336;
}
.alert.success {
background-color: #4CAF50;
}
.alert.info {
background-color: #2196F3;
}
</style>
<script>
import alert from '@/alert';
const alertIcons = {
error: require('@/assets/notification-error.svg'),
success: require('@/assets/notification-success.svg'),
info: require('@/assets/notification-info.svg')
};
export default {
name: 'AlertToast',
data() {
return {
showAlert: false,
heading: '',
message: '',
type: ''
};
},
computed: {
icon() {
return this.type && alertIcons[this.type] ? alertIcons[this.type] : null;
}
},
mounted() {
alert.subscribe(this.show);
},
methods: {
show({ heading, message, type }) {
this.heading = heading;
this.message = message;
this.type = type;
this.showAlert = true;
setTimeout(() => {
this.showAlert = false;
}, 5000);
},
dismiss() {
this.showAlert = false;
},
}
}
</script>

View file

@ -36,7 +36,9 @@
</template>
<script>
import data from '@/data.js'
import data from '@/data.js';
import alert from '@/alert.js';
import RecipeSearchBox from '@/components/recipes/RecipeSearchBox.vue';
import RecipeCard from '@/components/recipes/RecipeCard.vue';
import DatePicker from './DatePicker.vue';
@ -115,10 +117,11 @@ export default {
const meal = await data.saveMeal(this.meal);
if (meal?.id >= 0) {
this.$router.push(`/meals/${meal.id}`);
alert.show({ heading: 'Meal saved', message: 'Meal saved successfully', type: 'success' });
return;
}
alert('Failed to save meal');
alert.show({ heading: 'Error saving meal', message: 'An error occurred while saving the meal', type: 'error' });
},
onEditAdditionalIngredients(editing) {
if (editing && this.meal.extra_ingredients.length === 0) {