aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/App.vue23
-rw-r--r--src/components/EditPage.vue183
2 files changed, 203 insertions, 3 deletions
diff --git a/src/App.vue b/src/App.vue
index 80e462e..ddccf26 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -6,11 +6,13 @@
prepend-icon="mdi-home"
title="Home"
value="home"
+ @click="atHome = true"
></v-list-item>
<v-list-item
prepend-icon="mdi-pencil"
title="Edit"
value="edit"
+ @click="atHome = false"
></v-list-item>
<v-list-item
prepend-icon="mdi-theme-light-dark"
@@ -19,9 +21,17 @@
@click="toggleTheme"
></v-list-item> </v-list
></v-navigation-drawer>
+ <v-snackbar color="grey" v-model="snackbar">
+ {{ snackbarText }}
+
+ <template v-slot:actions>
+ <v-btn variant="snackbarText" @click="snackbar = false"> Close </v-btn>
+ </template>
+ </v-snackbar>
<v-main>
- <v-container>
- <HomePage class="float-end w-50" />
+ <v-container class="float-end w-50">
+ <HomePage v-if="atHome == true" />
+ <EditPage v-else @snackbar-notification="setSnackbarText" />
</v-container>
</v-main>
</v-app>
@@ -30,18 +40,21 @@
<script>
import { useTheme } from "vuetify";
import HomePage from "./components/HomePage.vue";
+import EditPage from "./components/EditPage.vue";
export default {
name: "App",
components: {
HomePage,
+ EditPage,
},
data: () => ({
drawer: null,
+ atHome: true,
snackbar: false,
- snackbarColor: "black",
+ snackbarText: "Default snackbar text (End-user shouldn't see this)",
bg: {
backgroundColor: "grey",
// backgroundImage: "url(https://wallpapercave.com/wp/wp9649930.jpg)",
@@ -65,6 +78,10 @@ export default {
toggleDrawer() {
this.drawer = !this.drawer;
},
+ setSnackbarText(text) {
+ this.snackbarText = text;
+ this.snackbar = true;
+ },
},
};
</script>
diff --git a/src/components/EditPage.vue b/src/components/EditPage.vue
new file mode 100644
index 0000000..ea47926
--- /dev/null
+++ b/src/components/EditPage.vue
@@ -0,0 +1,183 @@
+<template>
+ <v-switch
+ v-model="switchModel"
+ label="I want to create a new SubCard"
+ ></v-switch>
+
+ <v-form v-show="switchModel" lazy-validate ref="form1" v-model="valid1">
+ <v-text-field
+ v-model="title"
+ :counter="titleMaxLength"
+ :rules="titleRules"
+ label="Title"
+ required
+ ></v-text-field>
+
+ <v-textarea
+ auto-grow
+ clearable
+ clear-icon="mdi-close-circle"
+ outlined
+ name="textarea"
+ label="Content"
+ v-model="content"
+ :rules="contentRules"
+ required
+ ></v-textarea>
+
+ <v-btn
+ :disabled="!valid1"
+ variant="outlined"
+ class="mr-4"
+ @click="
+ validate(this.$refs.form1);
+ write(this.$refs.form1);
+ "
+ >
+ Save
+ </v-btn>
+
+ <v-btn variant="outlined" class="mr-4" @click="reset(this.$refs.form1)">
+ Reset Form
+ </v-btn>
+ </v-form>
+
+ <v-form v-show="!switchModel" lazy-validate ref="form2" v-model="valid2">
+ <v-select
+ v-model="select"
+ variant="outlined"
+ :items="items"
+ :rules="[(v) => !!v || 'Item is required']"
+ label="Item"
+ required
+ ></v-select>
+
+ <v-textarea
+ auto-grow
+ clearable
+ clear-icon="mdi-close-circle"
+ outlined
+ name="textarea"
+ label="Content"
+ v-model="content"
+ :rules="contentRules"
+ required
+ ></v-textarea>
+
+ <v-btn
+ :disabled="!valid2"
+ variant="outlined"
+ class="mr-4"
+ @click="
+ validate(this.$refs.form2);
+ write(this.$refs.form2);
+ "
+ >
+ Save
+ </v-btn>
+
+ <v-btn variant="outlined" class="mr-4" @click="reset(this.$refs.form2)">
+ Reset Validation
+ </v-btn>
+ <v-btn variant="outlined" class="mr-4" @click="deleteItem">
+ Delete Item
+ </v-btn>
+ </v-form>
+</template>
+
+<script>
+export default {
+ name: "EditPage",
+
+ emits: ["snackbarNotification"],
+
+ data: () => ({
+ valid1: true,
+ valid2: true,
+ title: "",
+ titleMaxLength: 15,
+ titleRules: [
+ (v) => !!v || "Title is required",
+ (v) => {
+ let titleMaxLength = 15;
+ return (
+ (v && v.length <= titleMaxLength) ||
+ `Title must be less than ${titleMaxLength} characters`
+ );
+ },
+ ],
+ content: "",
+ contentRules: [(v) => !!v || "Content is required"],
+ select: null,
+ items: [],
+ switchModel: false,
+ LSData: {},
+ }),
+
+ mounted() {
+ this.loadFromLS();
+ this.readAllItems();
+ },
+
+ methods: {
+ validate(form) {
+ form.validate();
+ },
+ reset(form) {
+ // Resets validation of all registered inputs without modifying their state.
+ // TODO: clearify this (do we need form.reset() ?)
+ form.resetValidation();
+ },
+ write(form) {
+ if (form == this.$refs.form1 && this.title in this.LSData) {
+ this.$emit("snackbarNotification", "Title already exists");
+ return;
+ }
+ if (form == this.$refs.form2) {
+ // Sync LSData(title) with form data
+ this.title = this.select;
+ }
+ this.LSData[this.title] = this.content;
+ this.writeToLS();
+ this.$emit("snackbarNotification", "Done!");
+ // Let's do a reset.
+ this.reset(form);
+ // Re-read all items.
+ this.readAllItems();
+ },
+ readAllItems() {
+ this.items = []; // Reset items list
+ for (let key in this.LSData) {
+ this.items.push(key);
+ }
+ },
+ deleteItem() {
+ delete this.LSData[this.select];
+ this.writeToLS();
+ // Re-read all items.
+ this.readAllItems();
+ this.$emit("snackbarNotification", "Item deleted");
+ this.reset(this.$refs.form2);
+ },
+
+ // LocalStorage
+ loadFromLS() {
+ this.LSData = JSON.parse(localStorage.getItem("LSData")) || this.LSData;
+ },
+ writeToLS() {
+ localStorage.setItem("LSData", JSON.stringify(this.LSData));
+ },
+ clearLS() {
+ localStorage.clear();
+ },
+ },
+
+ watch: {
+ // eslint-disable-next-line no-unused-vars
+ select(newSelected, _) {
+ // Load content whenever select changes
+ this.content = this.LSData[newSelected];
+ },
+ },
+};
+</script>