diff --git a/package-lock.json b/package-lock.json
index 9a1dc456e..ec9056f7d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -21,6 +21,7 @@
         "js-cookie": "^2.2.1",
         "js-sha256": "^0.9.0",
         "libphonenumber-js": "^1.10.44",
+        "pinia": "^2.1.7",
         "prismjs": "^1.24.1",
         "qrcode": "^1.5.1",
         "query-builder-vue": "^1.2.0",
@@ -36,10 +37,9 @@
         "vue-notion": "^3.0.0-beta.1",
         "vue-router": "^4.2.5",
         "vue-signature-pad": "^3.0.2",
-        "vue2-editor": "^2.10.3",
+        "vue3-editor": "^0.1.1",
         "vue3-vt-notifications": "^1.0.0",
-        "vuedraggable": "^4.1.0",
-        "vuex": "^4.1.0"
+        "vuedraggable": "^4.1.0"
       },
       "devDependencies": {
         "@babel/core": "^7.20.12",
@@ -104,12 +104,12 @@
       }
     },
     "node_modules/@babel/code-frame": {
-      "version": "7.22.13",
-      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz",
-      "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.23.5.tgz",
+      "integrity": "sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==",
       "dev": true,
       "dependencies": {
-        "@babel/highlight": "^7.22.13",
+        "@babel/highlight": "^7.23.4",
         "chalk": "^2.4.2"
       },
       "engines": {
@@ -117,30 +117,30 @@
       }
     },
     "node_modules/@babel/compat-data": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.3.tgz",
-      "integrity": "sha512-BmR4bWbDIoFJmJ9z2cZ8Gmm2MXgEDgjdWgpKmKWUt54UGFJdlj31ECtbaDvCG/qVdG3AQ1SfpZEs01lUFbzLOQ==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz",
+      "integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/core": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.3.tgz",
-      "integrity": "sha512-Jg+msLuNuCJDyBvFv5+OKOUjWMZgd85bKjbICd3zWrKAo+bJ49HJufi7CQE0q0uR8NGyO6xkCACScNqyjHSZew==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.5.tgz",
+      "integrity": "sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==",
       "dev": true,
       "dependencies": {
         "@ampproject/remapping": "^2.2.0",
-        "@babel/code-frame": "^7.22.13",
-        "@babel/generator": "^7.23.3",
+        "@babel/code-frame": "^7.23.5",
+        "@babel/generator": "^7.23.5",
         "@babel/helper-compilation-targets": "^7.22.15",
         "@babel/helper-module-transforms": "^7.23.3",
-        "@babel/helpers": "^7.23.2",
-        "@babel/parser": "^7.23.3",
+        "@babel/helpers": "^7.23.5",
+        "@babel/parser": "^7.23.5",
         "@babel/template": "^7.22.15",
-        "@babel/traverse": "^7.23.3",
-        "@babel/types": "^7.23.3",
+        "@babel/traverse": "^7.23.5",
+        "@babel/types": "^7.23.5",
         "convert-source-map": "^2.0.0",
         "debug": "^4.1.0",
         "gensync": "^1.0.0-beta.2",
@@ -174,12 +174,12 @@
       }
     },
     "node_modules/@babel/generator": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.3.tgz",
-      "integrity": "sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.5.tgz",
+      "integrity": "sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==",
       "dev": true,
       "dependencies": {
-        "@babel/types": "^7.23.3",
+        "@babel/types": "^7.23.5",
         "@jridgewell/gen-mapping": "^0.3.2",
         "@jridgewell/trace-mapping": "^0.3.17",
         "jsesc": "^2.5.1"
@@ -229,17 +229,17 @@
       }
     },
     "node_modules/@babel/helper-create-class-features-plugin": {
-      "version": "7.22.15",
-      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz",
-      "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.5.tgz",
+      "integrity": "sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A==",
       "dev": true,
       "dependencies": {
         "@babel/helper-annotate-as-pure": "^7.22.5",
-        "@babel/helper-environment-visitor": "^7.22.5",
-        "@babel/helper-function-name": "^7.22.5",
-        "@babel/helper-member-expression-to-functions": "^7.22.15",
+        "@babel/helper-environment-visitor": "^7.22.20",
+        "@babel/helper-function-name": "^7.23.0",
+        "@babel/helper-member-expression-to-functions": "^7.23.0",
         "@babel/helper-optimise-call-expression": "^7.22.5",
-        "@babel/helper-replace-supers": "^7.22.9",
+        "@babel/helper-replace-supers": "^7.22.20",
         "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5",
         "@babel/helper-split-export-declaration": "^7.22.6",
         "semver": "^6.3.1"
@@ -453,9 +453,9 @@
       }
     },
     "node_modules/@babel/helper-string-parser": {
-      "version": "7.22.5",
-      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
-      "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz",
+      "integrity": "sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
@@ -471,9 +471,9 @@
       }
     },
     "node_modules/@babel/helper-validator-option": {
-      "version": "7.22.15",
-      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz",
-      "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz",
+      "integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==",
       "dev": true,
       "engines": {
         "node": ">=6.9.0"
@@ -494,23 +494,23 @@
       }
     },
     "node_modules/@babel/helpers": {
-      "version": "7.23.2",
-      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz",
-      "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.5.tgz",
+      "integrity": "sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==",
       "dev": true,
       "dependencies": {
         "@babel/template": "^7.22.15",
-        "@babel/traverse": "^7.23.2",
-        "@babel/types": "^7.23.0"
+        "@babel/traverse": "^7.23.5",
+        "@babel/types": "^7.23.5"
       },
       "engines": {
         "node": ">=6.9.0"
       }
     },
     "node_modules/@babel/highlight": {
-      "version": "7.22.20",
-      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz",
-      "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.23.4.tgz",
+      "integrity": "sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==",
       "dev": true,
       "dependencies": {
         "@babel/helper-validator-identifier": "^7.22.20",
@@ -522,9 +522,9 @@
       }
     },
     "node_modules/@babel/parser": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.3.tgz",
-      "integrity": "sha512-uVsWNvlVsIninV2prNz/3lHCb+5CJ+e+IUBfbjToAHODtfGYLfCFuY4AU7TskI+dAKk+njsPiBjq1gKTvZOBaw==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.5.tgz",
+      "integrity": "sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==",
       "bin": {
         "parser": "bin/babel-parser.js"
       },
@@ -843,9 +843,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-async-generator-functions": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.3.tgz",
-      "integrity": "sha512-59GsVNavGxAXCDDbakWSMJhajASb4kBCqDjqJsv+p5nKdbz7istmZ3HrX3L2LuiI80+zsOADCvooqQH3qGCucQ==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.4.tgz",
+      "integrity": "sha512-efdkfPhHYTtn0G6n2ddrESE91fgXxjlqLsnUtPWnJs4a4mZIbUaK7ffqKIIUKXSHwcDvaCVX6GXkaJJFqtX7jw==",
       "dev": true,
       "dependencies": {
         "@babel/helper-environment-visitor": "^7.22.20",
@@ -893,9 +893,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-block-scoping": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.3.tgz",
-      "integrity": "sha512-QPZxHrThbQia7UdvfpaRRlq/J9ciz1J4go0k+lPBXbgaNeY7IQrBj/9ceWjvMMI07/ZBzHl/F0R/2K0qH7jCVw==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz",
+      "integrity": "sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==",
       "dev": true,
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.22.5"
@@ -924,9 +924,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-class-static-block": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.3.tgz",
-      "integrity": "sha512-PENDVxdr7ZxKPyi5Ffc0LjXdnJyrJxyqF5T5YjlVg4a0VFfQHW0r8iAtRiDXkfHlu1wwcvdtnndGYIeJLSuRMQ==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz",
+      "integrity": "sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==",
       "dev": true,
       "dependencies": {
         "@babel/helper-create-class-features-plugin": "^7.22.15",
@@ -941,9 +941,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-classes": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.3.tgz",
-      "integrity": "sha512-FGEQmugvAEu2QtgtU0uTASXevfLMFfBeVCIIdcQhn/uBQsMTjBajdnAtanQlOcuihWh10PZ7+HWvc7NtBwP74w==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.5.tgz",
+      "integrity": "sha512-jvOTR4nicqYC9yzOHIhXG5emiFEOpappSJAl73SDSEDcybD+Puuze8Tnpb9p9qEyYup24tq891gkaygIFvWDqg==",
       "dev": true,
       "dependencies": {
         "@babel/helper-annotate-as-pure": "^7.22.5",
@@ -1026,9 +1026,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-dynamic-import": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.3.tgz",
-      "integrity": "sha512-vTG+cTGxPFou12Rj7ll+eD5yWeNl5/8xvQvF08y5Gv3v4mZQoyFf8/n9zg4q5vvCWt5jmgymfzMAldO7orBn7A==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz",
+      "integrity": "sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==",
       "dev": true,
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.22.5",
@@ -1058,9 +1058,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-export-namespace-from": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.3.tgz",
-      "integrity": "sha512-yCLhW34wpJWRdTxxWtFZASJisihrfyMOTOQexhVzA78jlU+dH7Dw+zQgcPepQ5F3C6bAIiblZZ+qBggJdHiBAg==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz",
+      "integrity": "sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==",
       "dev": true,
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.22.5",
@@ -1106,9 +1106,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-json-strings": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.3.tgz",
-      "integrity": "sha512-H9Ej2OiISIZowZHaBwF0tsJOih1PftXJtE8EWqlEIwpc7LMTGq0rPOrywKLQ4nefzx8/HMR0D3JGXoMHYvhi0A==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz",
+      "integrity": "sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==",
       "dev": true,
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.22.5",
@@ -1137,9 +1137,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-logical-assignment-operators": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.3.tgz",
-      "integrity": "sha512-+pD5ZbxofyOygEp+zZAfujY2ShNCXRpDRIPOiBmTO693hhyOEteZgl876Xs9SAHPQpcV0vz8LvA/T+w8AzyX8A==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz",
+      "integrity": "sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==",
       "dev": true,
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.22.5",
@@ -1266,9 +1266,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.3.tgz",
-      "integrity": "sha512-xzg24Lnld4DYIdysyf07zJ1P+iIfJpxtVFOzX4g+bsJ3Ng5Le7rXx9KwqKzuyaUeRnt+I1EICwQITqc0E2PmpA==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz",
+      "integrity": "sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==",
       "dev": true,
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.22.5",
@@ -1282,9 +1282,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-numeric-separator": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.3.tgz",
-      "integrity": "sha512-s9GO7fIBi/BLsZ0v3Rftr6Oe4t0ctJ8h4CCXfPoEJwmvAPMyNrfkOOJzm6b9PX9YXcCJWWQd/sBF/N26eBiMVw==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz",
+      "integrity": "sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==",
       "dev": true,
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.22.5",
@@ -1298,9 +1298,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-object-rest-spread": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.3.tgz",
-      "integrity": "sha512-VxHt0ANkDmu8TANdE9Kc0rndo/ccsmfe2Cx2y5sI4hu3AukHQ5wAu4cM7j3ba8B9548ijVyclBU+nuDQftZsog==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz",
+      "integrity": "sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==",
       "dev": true,
       "dependencies": {
         "@babel/compat-data": "^7.23.3",
@@ -1333,9 +1333,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-optional-catch-binding": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.3.tgz",
-      "integrity": "sha512-LxYSb0iLjUamfm7f1D7GpiS4j0UAC8AOiehnsGAP8BEsIX8EOi3qV6bbctw8M7ZvLtcoZfZX5Z7rN9PlWk0m5A==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz",
+      "integrity": "sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==",
       "dev": true,
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.22.5",
@@ -1349,9 +1349,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-optional-chaining": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.3.tgz",
-      "integrity": "sha512-zvL8vIfIUgMccIAK1lxjvNv572JHFJIKb4MWBz5OGdBQA0fB0Xluix5rmOby48exiJc987neOmP/m9Fnpkz3Tg==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz",
+      "integrity": "sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==",
       "dev": true,
       "dependencies": {
         "@babel/helper-plugin-utils": "^7.22.5",
@@ -1397,9 +1397,9 @@
       }
     },
     "node_modules/@babel/plugin-transform-private-property-in-object": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.3.tgz",
-      "integrity": "sha512-a5m2oLNFyje2e/rGKjVfAELTVI5mbA0FeZpBnkOWWV7eSmKQ+T/XW0Vf+29ScLzSxX+rnsarvU0oie/4m6hkxA==",
+      "version": "7.23.4",
+      "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz",
+      "integrity": "sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==",
       "dev": true,
       "dependencies": {
         "@babel/helper-annotate-as-pure": "^7.22.5",
@@ -1600,15 +1600,15 @@
       }
     },
     "node_modules/@babel/preset-env": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.3.tgz",
-      "integrity": "sha512-ovzGc2uuyNfNAs/jyjIGxS8arOHS5FENZaNn4rtE7UdKMMkqHCvboHfcuhWLZNX5cB44QfcGNWjaevxMzzMf+Q==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.23.5.tgz",
+      "integrity": "sha512-0d/uxVD6tFGWXGDSfyMD1p2otoaKmu6+GD+NfAx0tMaH+dxORnp7T9TaVQ6mKyya7iBtCIVxHjWT7MuzzM9z+A==",
       "dev": true,
       "dependencies": {
-        "@babel/compat-data": "^7.23.3",
+        "@babel/compat-data": "^7.23.5",
         "@babel/helper-compilation-targets": "^7.22.15",
         "@babel/helper-plugin-utils": "^7.22.5",
-        "@babel/helper-validator-option": "^7.22.15",
+        "@babel/helper-validator-option": "^7.23.5",
         "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.23.3",
         "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.23.3",
         "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.23.3",
@@ -1632,25 +1632,25 @@
         "@babel/plugin-syntax-top-level-await": "^7.14.5",
         "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
         "@babel/plugin-transform-arrow-functions": "^7.23.3",
-        "@babel/plugin-transform-async-generator-functions": "^7.23.3",
+        "@babel/plugin-transform-async-generator-functions": "^7.23.4",
         "@babel/plugin-transform-async-to-generator": "^7.23.3",
         "@babel/plugin-transform-block-scoped-functions": "^7.23.3",
-        "@babel/plugin-transform-block-scoping": "^7.23.3",
+        "@babel/plugin-transform-block-scoping": "^7.23.4",
         "@babel/plugin-transform-class-properties": "^7.23.3",
-        "@babel/plugin-transform-class-static-block": "^7.23.3",
-        "@babel/plugin-transform-classes": "^7.23.3",
+        "@babel/plugin-transform-class-static-block": "^7.23.4",
+        "@babel/plugin-transform-classes": "^7.23.5",
         "@babel/plugin-transform-computed-properties": "^7.23.3",
         "@babel/plugin-transform-destructuring": "^7.23.3",
         "@babel/plugin-transform-dotall-regex": "^7.23.3",
         "@babel/plugin-transform-duplicate-keys": "^7.23.3",
-        "@babel/plugin-transform-dynamic-import": "^7.23.3",
+        "@babel/plugin-transform-dynamic-import": "^7.23.4",
         "@babel/plugin-transform-exponentiation-operator": "^7.23.3",
-        "@babel/plugin-transform-export-namespace-from": "^7.23.3",
+        "@babel/plugin-transform-export-namespace-from": "^7.23.4",
         "@babel/plugin-transform-for-of": "^7.23.3",
         "@babel/plugin-transform-function-name": "^7.23.3",
-        "@babel/plugin-transform-json-strings": "^7.23.3",
+        "@babel/plugin-transform-json-strings": "^7.23.4",
         "@babel/plugin-transform-literals": "^7.23.3",
-        "@babel/plugin-transform-logical-assignment-operators": "^7.23.3",
+        "@babel/plugin-transform-logical-assignment-operators": "^7.23.4",
         "@babel/plugin-transform-member-expression-literals": "^7.23.3",
         "@babel/plugin-transform-modules-amd": "^7.23.3",
         "@babel/plugin-transform-modules-commonjs": "^7.23.3",
@@ -1658,15 +1658,15 @@
         "@babel/plugin-transform-modules-umd": "^7.23.3",
         "@babel/plugin-transform-named-capturing-groups-regex": "^7.22.5",
         "@babel/plugin-transform-new-target": "^7.23.3",
-        "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.3",
-        "@babel/plugin-transform-numeric-separator": "^7.23.3",
-        "@babel/plugin-transform-object-rest-spread": "^7.23.3",
+        "@babel/plugin-transform-nullish-coalescing-operator": "^7.23.4",
+        "@babel/plugin-transform-numeric-separator": "^7.23.4",
+        "@babel/plugin-transform-object-rest-spread": "^7.23.4",
         "@babel/plugin-transform-object-super": "^7.23.3",
-        "@babel/plugin-transform-optional-catch-binding": "^7.23.3",
-        "@babel/plugin-transform-optional-chaining": "^7.23.3",
+        "@babel/plugin-transform-optional-catch-binding": "^7.23.4",
+        "@babel/plugin-transform-optional-chaining": "^7.23.4",
         "@babel/plugin-transform-parameters": "^7.23.3",
         "@babel/plugin-transform-private-methods": "^7.23.3",
-        "@babel/plugin-transform-private-property-in-object": "^7.23.3",
+        "@babel/plugin-transform-private-property-in-object": "^7.23.4",
         "@babel/plugin-transform-property-literals": "^7.23.3",
         "@babel/plugin-transform-regenerator": "^7.23.3",
         "@babel/plugin-transform-reserved-words": "^7.23.3",
@@ -1714,9 +1714,9 @@
       "dev": true
     },
     "node_modules/@babel/runtime": {
-      "version": "7.23.2",
-      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz",
-      "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.5.tgz",
+      "integrity": "sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==",
       "dependencies": {
         "regenerator-runtime": "^0.14.0"
       },
@@ -1739,19 +1739,19 @@
       }
     },
     "node_modules/@babel/traverse": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.3.tgz",
-      "integrity": "sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.5.tgz",
+      "integrity": "sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==",
       "dev": true,
       "dependencies": {
-        "@babel/code-frame": "^7.22.13",
-        "@babel/generator": "^7.23.3",
+        "@babel/code-frame": "^7.23.5",
+        "@babel/generator": "^7.23.5",
         "@babel/helper-environment-visitor": "^7.22.20",
         "@babel/helper-function-name": "^7.23.0",
         "@babel/helper-hoist-variables": "^7.22.5",
         "@babel/helper-split-export-declaration": "^7.22.6",
-        "@babel/parser": "^7.23.3",
-        "@babel/types": "^7.23.3",
+        "@babel/parser": "^7.23.5",
+        "@babel/types": "^7.23.5",
         "debug": "^4.1.0",
         "globals": "^11.1.0"
       },
@@ -1760,12 +1760,12 @@
       }
     },
     "node_modules/@babel/types": {
-      "version": "7.23.3",
-      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.3.tgz",
-      "integrity": "sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw==",
+      "version": "7.23.5",
+      "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.5.tgz",
+      "integrity": "sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==",
       "dev": true,
       "dependencies": {
-        "@babel/helper-string-parser": "^7.22.5",
+        "@babel/helper-string-parser": "^7.23.4",
         "@babel/helper-validator-identifier": "^7.22.20",
         "to-fast-properties": "^2.0.0"
       },
@@ -2330,14 +2330,14 @@
       }
     },
     "node_modules/@sentry-internal/tracing": {
-      "version": "7.80.0",
-      "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.80.0.tgz",
-      "integrity": "sha512-P1Ab9gamHLsbH9D82i1HY8xfq9dP8runvc4g50AAd6OXRKaJ45f2KGRZUmnMEVqBQ7YoPYp2LFMkrhNYbcZEoQ==",
+      "version": "7.84.0",
+      "resolved": "https://registry.npmjs.org/@sentry-internal/tracing/-/tracing-7.84.0.tgz",
+      "integrity": "sha512-y9bGYA0OM6PEREfd+nk4UURZy29tpIw+7vQwpxWfEVs2fqq0/5TBFX/tKFb8AKUI9lVM8v0bcF0bNSCnuPQZHQ==",
       "dev": true,
       "dependencies": {
-        "@sentry/core": "7.80.0",
-        "@sentry/types": "7.80.0",
-        "@sentry/utils": "7.80.0"
+        "@sentry/core": "7.84.0",
+        "@sentry/types": "7.84.0",
+        "@sentry/utils": "7.84.0"
       },
       "engines": {
         "node": ">=8"
@@ -2393,12 +2393,12 @@
       }
     },
     "node_modules/@sentry/bundler-plugin-core": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.10.0.tgz",
-      "integrity": "sha512-bjcYvMrCQgqTiRRkWGNpeZ7EJOu0JQFYj+rrcQpwaVO+ll1eWNGW1nNveU+8vpnXrlaIAvieBxCrcCj5V9y1+Q==",
+      "version": "2.10.2",
+      "resolved": "https://registry.npmjs.org/@sentry/bundler-plugin-core/-/bundler-plugin-core-2.10.2.tgz",
+      "integrity": "sha512-7IoekLtROlJZqTxtHQ3IhocBuf9dsEq+JjqlHMyZXoq+QKuvJFvMd/4T+r6KjZ15kMZOIkR+spK3V7duH201hw==",
       "dev": true,
       "dependencies": {
-        "@sentry/cli": "^2.21.2",
+        "@sentry/cli": "^2.22.3",
         "@sentry/node": "^7.60.0",
         "@sentry/utils": "^7.60.0",
         "dotenv": "^16.3.1",
@@ -2412,11 +2412,10 @@
       }
     },
     "node_modules/@sentry/cli": {
-      "version": "2.21.3",
-      "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.21.3.tgz",
-      "integrity": "sha512-gv8SNaMVNggiE/+6fPxEj8+y5uj9PqAQ8QS277aZ/HSXFgoidnNecE4QGHh4n+AkT0qCSQ/byxZsojVXkwkC7g==",
+      "version": "2.22.3",
+      "resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-2.22.3.tgz",
+      "integrity": "sha512-VFHdtrHsMyTRSZhDLeMyXvit7xB4e81KugIEwMve95c7h5HO672bfmCcM/403CAugj4NzvQ+IR2NKF/2SsEPlg==",
       "dev": true,
-      "hasInstallScript": true,
       "dependencies": {
         "https-proxy-agent": "^5.0.0",
         "node-fetch": "^2.6.7",
@@ -2429,15 +2428,139 @@
       },
       "engines": {
         "node": ">= 10"
+      },
+      "optionalDependencies": {
+        "@sentry/cli-darwin": "2.22.3",
+        "@sentry/cli-linux-arm": "2.22.3",
+        "@sentry/cli-linux-arm64": "2.22.3",
+        "@sentry/cli-linux-i686": "2.22.3",
+        "@sentry/cli-linux-x64": "2.22.3",
+        "@sentry/cli-win32-i686": "2.22.3",
+        "@sentry/cli-win32-x64": "2.22.3"
+      }
+    },
+    "node_modules/@sentry/cli-darwin": {
+      "version": "2.22.3",
+      "resolved": "https://registry.npmjs.org/@sentry/cli-darwin/-/cli-darwin-2.22.3.tgz",
+      "integrity": "sha512-A1DwFTffg3+fF68qujaJI07dk/1H1pRuihlvS5WQ9sD7nQLnXZGoLUht4eULixhDzZYinWHKkcWzQ6k40UTvNA==",
+      "dev": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@sentry/cli-linux-arm": {
+      "version": "2.22.3",
+      "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm/-/cli-linux-arm-2.22.3.tgz",
+      "integrity": "sha512-mDtLVbqbCu/5b/v2quTAMzY/atGlJVvrqO2Wvpro0Jb/LYhn7Y1pVBdoXEDcnOX82/pseFkLT8PFfq/OcezPhA==",
+      "cpu": [
+        "arm"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux",
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@sentry/cli-linux-arm64": {
+      "version": "2.22.3",
+      "resolved": "https://registry.npmjs.org/@sentry/cli-linux-arm64/-/cli-linux-arm64-2.22.3.tgz",
+      "integrity": "sha512-PnBPb4LJ+A2LlqLjtVFn4mEizcVdxBSLZvB85pEGzq9DRXjZ6ZEuGWFHTVnWvjd79TB/s0me29QnLc3n4B6lgA==",
+      "cpu": [
+        "arm64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux",
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@sentry/cli-linux-i686": {
+      "version": "2.22.3",
+      "resolved": "https://registry.npmjs.org/@sentry/cli-linux-i686/-/cli-linux-i686-2.22.3.tgz",
+      "integrity": "sha512-wxvbpQ2hiw4hwJWfJMp7K45BV40nXL62f91jLuftFXIbieKX1Li57NNKNu2JUVn7W1bJxkwz/PKGGTXSgeJlRw==",
+      "cpu": [
+        "x86",
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux",
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@sentry/cli-linux-x64": {
+      "version": "2.22.3",
+      "resolved": "https://registry.npmjs.org/@sentry/cli-linux-x64/-/cli-linux-x64-2.22.3.tgz",
+      "integrity": "sha512-0GxsYNO5GyRWifeOpng+MmdUFZRA64bgA1n1prsEsXnoeLcm3Zj4Q63hBZmiwz9Qbhf5ibohkpf94a7dI7pv3A==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "linux",
+        "freebsd"
+      ],
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@sentry/cli-win32-i686": {
+      "version": "2.22.3",
+      "resolved": "https://registry.npmjs.org/@sentry/cli-win32-i686/-/cli-win32-i686-2.22.3.tgz",
+      "integrity": "sha512-YERPsd7ClBrxKcmCUw+ZrAvQfbyIZFrqh269hgDuXFodpsB7LPGnI33ilo0uzmKdq2vGppTb6Z3gf1Rbq0Hadg==",
+      "cpu": [
+        "x86",
+        "ia32"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=10"
+      }
+    },
+    "node_modules/@sentry/cli-win32-x64": {
+      "version": "2.22.3",
+      "resolved": "https://registry.npmjs.org/@sentry/cli-win32-x64/-/cli-win32-x64-2.22.3.tgz",
+      "integrity": "sha512-NUh56xWvgJo2KuC9lI6o6nTPXdzbpQUB4qGwJ73L9NP3HT2P1I27jtHyrC2zlXTVlYE23gQZGrL3wgW4Jy80QA==",
+      "cpu": [
+        "x64"
+      ],
+      "dev": true,
+      "optional": true,
+      "os": [
+        "win32"
+      ],
+      "engines": {
+        "node": ">=10"
       }
     },
     "node_modules/@sentry/core": {
-      "version": "7.80.0",
-      "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.80.0.tgz",
-      "integrity": "sha512-nJiiymdTSEyI035/rdD3VOq6FlOZ2wWLR5bit9LK8a3rzHU3UXkwScvEo6zYgs0Xp1sC0yu1S9+0BEiYkmi29A==",
+      "version": "7.84.0",
+      "resolved": "https://registry.npmjs.org/@sentry/core/-/core-7.84.0.tgz",
+      "integrity": "sha512-tbuwunbBx2kSex15IHCqHDnrMfIlqPc6w/76fwkGqokz3oh9GSEGlLICwmBWL8AypWimUg13IDtFpD0TJTriWA==",
       "dependencies": {
-        "@sentry/types": "7.80.0",
-        "@sentry/utils": "7.80.0"
+        "@sentry/types": "7.84.0",
+        "@sentry/utils": "7.84.0"
       },
       "engines": {
         "node": ">=8"
@@ -2477,13 +2600,13 @@
       }
     },
     "node_modules/@sentry/integrations": {
-      "version": "7.80.0",
-      "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.80.0.tgz",
-      "integrity": "sha512-9xI+jtqSBrAG/Y2f4OyeJhl6WZR3i0qCXRwqCZoCFCDgN4ZQORc4VBwaC3nW2s9jgfb13FC2FQToGOVrRnsetg==",
+      "version": "7.84.0",
+      "resolved": "https://registry.npmjs.org/@sentry/integrations/-/integrations-7.84.0.tgz",
+      "integrity": "sha512-aUu95BhnHSf/W/F4BvsFnf4x+piHiah5a180YTMqWcHMkJr7MnCWNIad9RJuHlcINSfyHtUr5+Z4Bajzqg60lw==",
       "dependencies": {
-        "@sentry/core": "7.80.0",
-        "@sentry/types": "7.80.0",
-        "@sentry/utils": "7.80.0",
+        "@sentry/core": "7.84.0",
+        "@sentry/types": "7.84.0",
+        "@sentry/utils": "7.84.0",
         "localforage": "^1.8.1"
       },
       "engines": {
@@ -2512,15 +2635,15 @@
       }
     },
     "node_modules/@sentry/node": {
-      "version": "7.80.0",
-      "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.80.0.tgz",
-      "integrity": "sha512-J35fqe8J5ac/17ZXT0ML3opYGTOclqYNE9Sybs1y9n6BqacHyzH8By72YrdI03F7JJDHwrcGw+/H8hGpkCwi0Q==",
+      "version": "7.84.0",
+      "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.84.0.tgz",
+      "integrity": "sha512-Xm3fIXT3TZOQi+6uQBavI8iOehD3PkY7v0y3hog0d4lQTH88vQK9BBsI+jZEq81Em+RG/u7vZNiFo6YMTnWF7Q==",
       "dev": true,
       "dependencies": {
-        "@sentry-internal/tracing": "7.80.0",
-        "@sentry/core": "7.80.0",
-        "@sentry/types": "7.80.0",
-        "@sentry/utils": "7.80.0",
+        "@sentry-internal/tracing": "7.84.0",
+        "@sentry/core": "7.84.0",
+        "@sentry/types": "7.84.0",
+        "@sentry/utils": "7.84.0",
         "https-proxy-agent": "^5.0.0"
       },
       "engines": {
@@ -2563,31 +2686,31 @@
       }
     },
     "node_modules/@sentry/types": {
-      "version": "7.80.0",
-      "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.80.0.tgz",
-      "integrity": "sha512-4bpMO+2jWiWLDa8zbTASWWNLWe6yhjfPsa7/6VH5y9x1NGtL8oRbqUsTgsvjF3nmeHEMkHQsC8NHPaQ/ibFmZQ==",
+      "version": "7.84.0",
+      "resolved": "https://registry.npmjs.org/@sentry/types/-/types-7.84.0.tgz",
+      "integrity": "sha512-VqGLIF3JOUrk7yIXjLXJvAORkZL1e3dDX0Q1okRehwyt/5CRE+mdUTeJZkBo9P9mBwgMyvtwklzOGGrzjb4eMA==",
       "engines": {
         "node": ">=8"
       }
     },
     "node_modules/@sentry/utils": {
-      "version": "7.80.0",
-      "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.80.0.tgz",
-      "integrity": "sha512-XbBCEl6uLvE50ftKwrEo6XWdDaZXHXu+kkHXTPWQEcnbvfZKLuG9V0Hxtxxq3xQgyWmuF05OH1GcqYqiO+v5Yg==",
+      "version": "7.84.0",
+      "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-7.84.0.tgz",
+      "integrity": "sha512-qdUVuxnRBvaf05AU+28R+xYtZmi/Ymf8os3Njq9g4XuA+QEkZLbzmIpRK5W9Ja7vUtjOeg29Xgg43A8znde9LQ==",
       "dependencies": {
-        "@sentry/types": "7.80.0"
+        "@sentry/types": "7.84.0"
       },
       "engines": {
         "node": ">=8"
       }
     },
     "node_modules/@sentry/vite-plugin": {
-      "version": "2.10.0",
-      "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-2.10.0.tgz",
-      "integrity": "sha512-jOJQnu3ox+HcD1HCul5LBy6YEhS0oVFjrFshoFD2PtHI5sMldbwNWrkkTXcknNy/0o4d5cAtdsEuVzEnbdd+Gg==",
+      "version": "2.10.2",
+      "resolved": "https://registry.npmjs.org/@sentry/vite-plugin/-/vite-plugin-2.10.2.tgz",
+      "integrity": "sha512-30uu0L8ZCpAKOxAXmtyqwL06sG8UEBXGY5mxUDITyQYDf8pKuiOEf5018KlEDjhYVypfMQH3jq5xXUUka+/ipg==",
       "dev": true,
       "dependencies": {
-        "@sentry/bundler-plugin-core": "2.10.0",
+        "@sentry/bundler-plugin-core": "2.10.2",
         "unplugin": "1.0.1"
       },
       "engines": {
@@ -2676,9 +2799,9 @@
       }
     },
     "node_modules/@types/eslint": {
-      "version": "8.44.7",
-      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.7.tgz",
-      "integrity": "sha512-f5ORu2hcBbKei97U73mf+l9t4zTGl74IqZ0GQk4oVea/VS8tQZYkUveSYojk+frraAVYId0V2WC9O4PTNru2FQ==",
+      "version": "8.44.8",
+      "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.44.8.tgz",
+      "integrity": "sha512-4K8GavROwhrYl2QXDXm0Rv9epkA8GBFu0EI+XrrnnuCl7u8CWBRusX7fXJfanhZTDWSAL24gDI/UqXyUM0Injw==",
       "dev": true,
       "peer": true,
       "dependencies": {
@@ -2705,9 +2828,9 @@
       "peer": true
     },
     "node_modules/@types/imagemin": {
-      "version": "8.0.4",
-      "resolved": "https://registry.npmjs.org/@types/imagemin/-/imagemin-8.0.4.tgz",
-      "integrity": "sha512-t7vady38h/FTQAxFe6gJvaTxjgi/uw54ZrDbqyKx3yOMPu3NQjQexCoLxBR03FRv0HcKJMV2MqGLeY7BuPl6/A==",
+      "version": "8.0.5",
+      "resolved": "https://registry.npmjs.org/@types/imagemin/-/imagemin-8.0.5.tgz",
+      "integrity": "sha512-tah3dm+5sG+fEDAz6CrQ5evuEaPX9K6DF3E5a01MPOKhA2oGBoC+oA5EJzSugB905sN4DE19EDzldT2Cld2g6Q==",
       "dev": true,
       "dependencies": {
         "@types/node": "*"
@@ -2763,9 +2886,9 @@
       "dev": true
     },
     "node_modules/@types/node": {
-      "version": "20.9.0",
-      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.9.0.tgz",
-      "integrity": "sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==",
+      "version": "20.10.1",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-20.10.1.tgz",
+      "integrity": "sha512-T2qwhjWwGH81vUEx4EXmBKsTJRXFXNZTL4v0gi01+zyBmCwzE6TyHszqX01m+QHTEq+EZNo13NeJIdEqf+Myrg==",
       "dev": true,
       "dependencies": {
         "undici-types": "~5.26.4"
@@ -2778,14 +2901,14 @@
       "dev": true
     },
     "node_modules/@types/sortablejs": {
-      "version": "1.15.5",
-      "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.5.tgz",
-      "integrity": "sha512-qqqbEFbB1EZt08I1Ok2BA3Sx0zlI8oizdIguMsajk4Yo/iHgXhCb3GM6N09JOJqT9xIMYM9LTFy8vit3RNY71Q=="
+      "version": "1.15.7",
+      "resolved": "https://registry.npmjs.org/@types/sortablejs/-/sortablejs-1.15.7.tgz",
+      "integrity": "sha512-PvgWCx1Lbgm88FdQ6S7OGvLIjWS66mudKPlfdrWil0TjsO5zmoZmzoKiiwRShs1dwPgrlkr0N4ewuy0/+QUXYQ=="
     },
     "node_modules/@types/source-list-map": {
-      "version": "0.1.5",
-      "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.5.tgz",
-      "integrity": "sha512-cHBTLeIGIREJx839cDfMLKWao+FaJOlaPz4mnFHXUzShS8sXhzw6irhvIpYvp28TbTmTeAt3v+QgHMANsGbQtA==",
+      "version": "0.1.6",
+      "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.6.tgz",
+      "integrity": "sha512-5JcVt1u5HDmlXkwOD2nslZVllBBc7HDuOICfiZah2Z0is8M8g+ddAEawbmd3VjedfDHBzxCaXLs07QEmb7y54g==",
       "dev": true
     },
     "node_modules/@types/svgo": {
@@ -2799,9 +2922,9 @@
       }
     },
     "node_modules/@types/tapable": {
-      "version": "1.0.11",
-      "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.11.tgz",
-      "integrity": "sha512-R3ltemSqZ/TKOBeyy+GBfZCLX3AYpxqarIbUMNe7+lxdazJp4iWLFpmjgBeZoRiKrWNImer1oWOlG2sDR6vGaw==",
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.12.tgz",
+      "integrity": "sha512-bTHG8fcxEqv1M9+TD14P8ok8hjxoOCkfKc8XXLaaD05kI7ohpeI956jtDOD3XHKBQrlyPughUtzm1jtVhHpA5Q==",
       "dev": true
     },
     "node_modules/@types/uglify-js": {
@@ -2819,9 +2942,9 @@
       "integrity": "sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow=="
     },
     "node_modules/@types/webpack": {
-      "version": "4.41.36",
-      "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.36.tgz",
-      "integrity": "sha512-pF+DVW1pMLmgsPXqJr5QimdxIzOhe8oGKB98gdqAm0egKBy1lOLD5mRxbYboMQRkpYcG7BYcpqYblpKyvE7vhQ==",
+      "version": "4.41.38",
+      "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.38.tgz",
+      "integrity": "sha512-oOW7E931XJU1mVfCnxCVgv8GLFL768pDO5u2Gzk82i8yTIgX6i7cntyZOkZYb/JtYM8252SN9bQp9tgkVDSsRw==",
       "dev": true,
       "dependencies": {
         "@types/node": "*",
@@ -2853,62 +2976,62 @@
       }
     },
     "node_modules/@vitejs/plugin-vue": {
-      "version": "4.4.1",
-      "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.4.1.tgz",
-      "integrity": "sha512-HCQG8VDFDM7YDAdcj5QI5DvUi+r6xvo9LgvYdk7LSkUNwdpempdB5horkMSZsbdey9Ywsf5aaU8kEPw9M5kREA==",
+      "version": "4.5.1",
+      "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.5.1.tgz",
+      "integrity": "sha512-DaUzYFr+2UGDG7VSSdShKa9sIWYBa1LL8KC0MNOf2H5LjcTPjob0x8LbkqXWmAtbANJCkpiQTj66UVcQkN2s3g==",
       "dev": true,
       "engines": {
         "node": "^14.18.0 || >=16.0.0"
       },
       "peerDependencies": {
-        "vite": "^4.0.0",
+        "vite": "^4.0.0 || ^5.0.0",
         "vue": "^3.2.25"
       }
     },
     "node_modules/@vue/compat": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/compat/-/compat-3.3.8.tgz",
-      "integrity": "sha512-ywp40WMF1DKZ4X/HbLPd5gHDyxDk/itDHp8JiSodvI9OyiA53HQS2hstLCh652HDue58gTQlo80HJwQCj+hYRw==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/compat/-/compat-3.3.9.tgz",
+      "integrity": "sha512-Ut7sKNk9o/ApJCr4SppyMlUbwy+5n/CCcmJKCvnsoJSOe3WfX2/dBJYVZZQzJtB2e2XV7jRrya4aKRkOp5+KfQ==",
       "dependencies": {
-        "@babel/parser": "^7.23.0",
+        "@babel/parser": "^7.23.3",
         "estree-walker": "^2.0.2",
         "source-map-js": "^1.0.2"
       },
       "peerDependencies": {
-        "vue": "3.3.8"
+        "vue": "3.3.9"
       }
     },
     "node_modules/@vue/compiler-core": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.8.tgz",
-      "integrity": "sha512-hN/NNBUECw8SusQvDSqqcVv6gWq8L6iAktUR0UF3vGu2OhzRqcOiAno0FmBJWwxhYEXRlQJT5XnoKsVq1WZx4g==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.9.tgz",
+      "integrity": "sha512-+/Lf68Vr/nFBA6ol4xOtJrW+BQWv3QWKfRwGSm70jtXwfhZNF4R/eRgyVJYoxFRhdCTk/F6g99BP0ffPgZihfQ==",
       "dependencies": {
-        "@babel/parser": "^7.23.0",
-        "@vue/shared": "3.3.8",
+        "@babel/parser": "^7.23.3",
+        "@vue/shared": "3.3.9",
         "estree-walker": "^2.0.2",
         "source-map-js": "^1.0.2"
       }
     },
     "node_modules/@vue/compiler-dom": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.8.tgz",
-      "integrity": "sha512-+PPtv+p/nWDd0AvJu3w8HS0RIm/C6VGBIRe24b9hSyNWOAPEUosFZ5diwawwP8ip5sJ8n0Pe87TNNNHnvjs0FQ==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.9.tgz",
+      "integrity": "sha512-nfWubTtLXuT4iBeDSZ5J3m218MjOy42Vp2pmKVuBKo2/BLcrFUX8nCSr/bKRFiJ32R8qbdnnnBgRn9AdU5v0Sg==",
       "dependencies": {
-        "@vue/compiler-core": "3.3.8",
-        "@vue/shared": "3.3.8"
+        "@vue/compiler-core": "3.3.9",
+        "@vue/shared": "3.3.9"
       }
     },
     "node_modules/@vue/compiler-sfc": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.8.tgz",
-      "integrity": "sha512-WMzbUrlTjfYF8joyT84HfwwXo+8WPALuPxhy+BZ6R4Aafls+jDBnSz8PDz60uFhuqFbl3HxRfxvDzrUf3THwpA==",
-      "dependencies": {
-        "@babel/parser": "^7.23.0",
-        "@vue/compiler-core": "3.3.8",
-        "@vue/compiler-dom": "3.3.8",
-        "@vue/compiler-ssr": "3.3.8",
-        "@vue/reactivity-transform": "3.3.8",
-        "@vue/shared": "3.3.8",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.9.tgz",
+      "integrity": "sha512-wy0CNc8z4ihoDzjASCOCsQuzW0A/HP27+0MDSSICMjVIFzk/rFViezkR3dzH+miS2NDEz8ywMdbjO5ylhOLI2A==",
+      "dependencies": {
+        "@babel/parser": "^7.23.3",
+        "@vue/compiler-core": "3.3.9",
+        "@vue/compiler-dom": "3.3.9",
+        "@vue/compiler-ssr": "3.3.9",
+        "@vue/reactivity-transform": "3.3.9",
+        "@vue/shared": "3.3.9",
         "estree-walker": "^2.0.2",
         "magic-string": "^0.30.5",
         "postcss": "^8.4.31",
@@ -2927,12 +3050,12 @@
       }
     },
     "node_modules/@vue/compiler-ssr": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.8.tgz",
-      "integrity": "sha512-hXCqQL/15kMVDBuoBYpUnSYT8doDNwsjvm3jTefnXr+ytn294ySnT8NlsFHmTgKNjwpuFy7XVV8yTeLtNl/P6w==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.9.tgz",
+      "integrity": "sha512-NO5oobAw78R0G4SODY5A502MGnDNiDjf6qvhn7zD7TJGc8XDeIEw4fg6JU705jZ/YhuokBKz0A5a/FL/XZU73g==",
       "dependencies": {
-        "@vue/compiler-dom": "3.3.8",
-        "@vue/shared": "3.3.8"
+        "@vue/compiler-dom": "3.3.9",
+        "@vue/shared": "3.3.9"
       }
     },
     "node_modules/@vue/component-compiler-utils": {
@@ -2999,21 +3122,21 @@
       "integrity": "sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA=="
     },
     "node_modules/@vue/reactivity": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.8.tgz",
-      "integrity": "sha512-ctLWitmFBu6mtddPyOKpHg8+5ahouoTCRtmAHZAXmolDtuZXfjL2T3OJ6DL6ezBPQB1SmMnpzjiWjCiMYmpIuw==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.9.tgz",
+      "integrity": "sha512-VmpIqlNp+aYDg2X0xQhJqHx9YguOmz2UxuUJDckBdQCNkipJvfk9yA75woLWElCa0Jtyec3lAAt49GO0izsphw==",
       "dependencies": {
-        "@vue/shared": "3.3.8"
+        "@vue/shared": "3.3.9"
       }
     },
     "node_modules/@vue/reactivity-transform": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.8.tgz",
-      "integrity": "sha512-49CvBzmZNtcHua0XJ7GdGifM8GOXoUMOX4dD40Y5DxI3R8OUhMlvf2nvgUAcPxaXiV5MQQ1Nwy09ADpnLQUqRw==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.9.tgz",
+      "integrity": "sha512-HnUFm7Ry6dFa4Lp63DAxTixUp8opMtQr6RxQCpDI1vlh12rkGIeYqMvJtK+IKyEfEOa2I9oCkD1mmsPdaGpdVg==",
       "dependencies": {
-        "@babel/parser": "^7.23.0",
-        "@vue/compiler-core": "3.3.8",
-        "@vue/shared": "3.3.8",
+        "@babel/parser": "^7.23.3",
+        "@vue/compiler-core": "3.3.9",
+        "@vue/shared": "3.3.9",
         "estree-walker": "^2.0.2",
         "magic-string": "^0.30.5"
       }
@@ -3030,48 +3153,48 @@
       }
     },
     "node_modules/@vue/runtime-core": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.8.tgz",
-      "integrity": "sha512-qurzOlb6q26KWQ/8IShHkMDOuJkQnQcTIp1sdP4I9MbCf9FJeGVRXJFr2mF+6bXh/3Zjr9TDgURXrsCr9bfjUw==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.9.tgz",
+      "integrity": "sha512-xxaG9KvPm3GTRuM4ZyU8Tc+pMVzcu6eeoSRQJ9IE7NmCcClW6z4B3Ij6L4EDl80sxe/arTtQ6YmgiO4UZqRc+w==",
       "dependencies": {
-        "@vue/reactivity": "3.3.8",
-        "@vue/shared": "3.3.8"
+        "@vue/reactivity": "3.3.9",
+        "@vue/shared": "3.3.9"
       }
     },
     "node_modules/@vue/runtime-dom": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.8.tgz",
-      "integrity": "sha512-Noy5yM5UIf9UeFoowBVgghyGGPIDPy1Qlqt0yVsUdAVbqI8eeMSsTqBtauaEoT2UFXUk5S64aWVNJN4MJ2vRdA==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.9.tgz",
+      "integrity": "sha512-e7LIfcxYSWbV6BK1wQv9qJyxprC75EvSqF/kQKe6bdZEDNValzeRXEVgiX7AHI6hZ59HA4h7WT5CGvm69vzJTQ==",
       "dependencies": {
-        "@vue/runtime-core": "3.3.8",
-        "@vue/shared": "3.3.8",
+        "@vue/runtime-core": "3.3.9",
+        "@vue/shared": "3.3.9",
         "csstype": "^3.1.2"
       }
     },
     "node_modules/@vue/server-renderer": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.8.tgz",
-      "integrity": "sha512-zVCUw7RFskvPuNlPn/8xISbrf0zTWsTSdYTsUTN1ERGGZGVnRxM2QZ3x1OR32+vwkkCm0IW6HmJ49IsPm7ilLg==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.9.tgz",
+      "integrity": "sha512-w0zT/s5l3Oa3ZjtLW88eO4uV6AQFqU8X5GOgzq7SkQQu6vVr+8tfm+OI2kDBplS/W/XgCBuFXiPw6T5EdwXP0A==",
       "dependencies": {
-        "@vue/compiler-ssr": "3.3.8",
-        "@vue/shared": "3.3.8"
+        "@vue/compiler-ssr": "3.3.9",
+        "@vue/shared": "3.3.9"
       },
       "peerDependencies": {
-        "vue": "3.3.8"
+        "vue": "3.3.9"
       }
     },
     "node_modules/@vue/shared": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.8.tgz",
-      "integrity": "sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw=="
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.9.tgz",
+      "integrity": "sha512-ZE0VTIR0LmYgeyhurPTpy4KzKsuDyQbMSdM49eKkMnT5X4VfFBLysMzjIZhLEFQYjjOVVfbvUDHckwjDFiO2eA=="
     },
     "node_modules/@vueuse/components": {
-      "version": "10.6.0",
-      "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-10.6.0.tgz",
-      "integrity": "sha512-vc9cmt3fd+wpMjhlq/wuXvEafSRY1XWlgzrxaExfVCRpWyLeqZ57hQ7rmcxbLkIbeaYqOO6Swc1OiT700hyR+A==",
+      "version": "10.6.1",
+      "resolved": "https://registry.npmjs.org/@vueuse/components/-/components-10.6.1.tgz",
+      "integrity": "sha512-Yx7h201xJG3V4+rY1wRAYy8EI9Q1r+gpwCJzgyZ0CWPyDWyZCxPXNjPhBJsXcSzJ1h1ph9tE5cVqEXHtEs6bjg==",
       "dependencies": {
-        "@vueuse/core": "10.6.0",
-        "@vueuse/shared": "10.6.0",
+        "@vueuse/core": "10.6.1",
+        "@vueuse/shared": "10.6.1",
         "vue-demi": ">=0.14.6"
       }
     },
@@ -3101,13 +3224,13 @@
       }
     },
     "node_modules/@vueuse/core": {
-      "version": "10.6.0",
-      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.6.0.tgz",
-      "integrity": "sha512-+Yee+g9+9BEbvkyGdn4Bf4yZx9EfocAytpV2ZlrlP7xcz+qznLmZIDqDroTvc5vtMkWZicisgEv8dt3+jL+HQg==",
+      "version": "10.6.1",
+      "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.6.1.tgz",
+      "integrity": "sha512-Pc26IJbqgC9VG1u6VY/xrXXfxD33hnvxBnKrLlA2LJlyHII+BSrRoTPJgGYq7qZOu61itITFUnm6QbacwZ4H8Q==",
       "dependencies": {
         "@types/web-bluetooth": "^0.0.20",
-        "@vueuse/metadata": "10.6.0",
-        "@vueuse/shared": "10.6.0",
+        "@vueuse/metadata": "10.6.1",
+        "@vueuse/shared": "10.6.1",
         "vue-demi": ">=0.14.6"
       },
       "funding": {
@@ -3140,17 +3263,17 @@
       }
     },
     "node_modules/@vueuse/metadata": {
-      "version": "10.6.0",
-      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.6.0.tgz",
-      "integrity": "sha512-mzKHkHoiK6xVz01VzQjM2l6ofUanEaofgEGPgDHcAzlvOTccPRTIdEuzneOUTYxgfm1vkDikS6rtrEw/NYlaTQ==",
+      "version": "10.6.1",
+      "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-10.6.1.tgz",
+      "integrity": "sha512-qhdwPI65Bgcj23e5lpGfQsxcy0bMjCAsUGoXkJ7DsoeDUdasbZ2DBa4dinFCOER3lF4gwUv+UD2AlA11zdzMFw==",
       "funding": {
         "url": "https://github.com/sponsors/antfu"
       }
     },
     "node_modules/@vueuse/shared": {
-      "version": "10.6.0",
-      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.6.0.tgz",
-      "integrity": "sha512-0t4MVE18sO+/4Gh0jfeOXBTjKeV4606N9kIrDOLPjFl8Rwnlodn+QC5A4LfJuysK7aOsTMjF3KnzNeueaI0xlQ==",
+      "version": "10.6.1",
+      "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-10.6.1.tgz",
+      "integrity": "sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==",
       "dependencies": {
         "vue-demi": ">=0.14.6"
       },
@@ -4583,9 +4706,9 @@
       }
     },
     "node_modules/caniuse-lite": {
-      "version": "1.0.30001561",
-      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001561.tgz",
-      "integrity": "sha512-NTt0DNoKe958Q0BE0j0c1V9jbUzhBxHIEJy7asmGrpE0yG63KTV7PLHPnK2E1O9RsQrQ081I3NLuXGS6zht3cw==",
+      "version": "1.0.30001565",
+      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001565.tgz",
+      "integrity": "sha512-xrE//a3O7TP0vaJ8ikzkD2c2NgcVUvsEe2IvFTntV4Yd1Z9FVzh+gW+enX96L0psrbaFMcVcH2l90xNuGDWc8w==",
       "dev": true,
       "funding": [
         {
@@ -4813,9 +4936,9 @@
       }
     },
     "node_modules/codemirror": {
-      "version": "5.65.15",
-      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.15.tgz",
-      "integrity": "sha512-YC4EHbbwQeubZzxLl5G4nlbLc1T21QTrKGaOal/Pkm9dVDMZXMH7+ieSPEOZCtO9I68i8/oteJKOxzHC2zR+0g=="
+      "version": "5.65.16",
+      "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-5.65.16.tgz",
+      "integrity": "sha512-br21LjYmSlVL0vFCPWPfhzUCT34FM/pAdK7rRIZwa0rrtrIdotvP4Oh4GUHsu2E3IrQMCfRkL/fN3ytMNxVQvg=="
     },
     "node_modules/collection-visit": {
       "version": "1.0.0",
@@ -4855,10 +4978,13 @@
       }
     },
     "node_modules/component-emitter": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
-      "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
-      "dev": true
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz",
+      "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==",
+      "dev": true,
+      "funding": {
+        "url": "https://github.com/sponsors/sindresorhus"
+      }
     },
     "node_modules/compose-function": {
       "version": "3.0.3",
@@ -4940,9 +5066,9 @@
       "hasInstallScript": true
     },
     "node_modules/core-js-compat": {
-      "version": "3.33.2",
-      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.2.tgz",
-      "integrity": "sha512-axfo+wxFVxnqf8RvxTzoAlzW4gRoacrHeoFlc9n0x50+7BEyZL/Rt3hicaED1/CEd7I6tPCPVUYcJwCMO5XUYw==",
+      "version": "3.33.3",
+      "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.33.3.tgz",
+      "integrity": "sha512-cNzGqFsh3Ot+529GIXacjTJ7kegdt5fPXxCBVS1G0iaZpuo/tBz399ymceLJveQhFFZ8qThHiP3fzuoQjKN2ow==",
       "dev": true,
       "dependencies": {
         "browserslist": "^4.22.1"
@@ -5637,9 +5763,9 @@
       "dev": true
     },
     "node_modules/electron-to-chromium": {
-      "version": "1.4.580",
-      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.580.tgz",
-      "integrity": "sha512-T5q3pjQon853xxxHUq3ZP68ZpvJHuSMY2+BZaW3QzjS4HvNuvsMmZ/+lU+nCrftre1jFZ+OSlExynXWBihnXzw==",
+      "version": "1.4.600",
+      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.600.tgz",
+      "integrity": "sha512-KD6CWjf1BnQG+NsXuyiTDDT1eV13sKuYsOUioXkQweYTQIbgHkXPry9K7M+7cKtYHnSUPitVaLrXYB1jTkkYrw==",
       "dev": true
     },
     "node_modules/emoji-regex": {
@@ -5778,9 +5904,9 @@
       "dev": true
     },
     "node_modules/es-module-lexer": {
-      "version": "1.4.0",
-      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.0.tgz",
-      "integrity": "sha512-lcCr3v3OLezdfFyx9r5NRYHOUTQNnFEQ9E87Mx8Kc+iqyJNkO7MJoB4GQRTlIMw9kLLTwGw0OAkm4BQQud/d9g==",
+      "version": "1.4.1",
+      "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz",
+      "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==",
       "dev": true,
       "peer": true
     },
@@ -6136,9 +6262,9 @@
       }
     },
     "node_modules/eslint-plugin-node/node_modules/ignore": {
-      "version": "5.2.4",
-      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz",
-      "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==",
+      "version": "5.3.0",
+      "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.0.tgz",
+      "integrity": "sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==",
       "dev": true,
       "engines": {
         "node": ">= 4"
@@ -7064,9 +7190,9 @@
       }
     },
     "node_modules/flat-cache": {
-      "version": "3.1.1",
-      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz",
-      "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==",
+      "version": "3.2.0",
+      "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
+      "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
       "dev": true,
       "dependencies": {
         "flatted": "^3.2.9",
@@ -7074,7 +7200,7 @@
         "rimraf": "^3.0.2"
       },
       "engines": {
-        "node": ">=12.0.0"
+        "node": "^10.12.0 || >=12.0.0"
       }
     },
     "node_modules/flatted": {
@@ -9019,9 +9145,9 @@
       }
     },
     "node_modules/libphonenumber-js": {
-      "version": "1.10.49",
-      "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.49.tgz",
-      "integrity": "sha512-gvLtyC3tIuqfPzjvYLH9BmVdqzGDiSi4VjtWe2fAgSdBf0yt8yPmbNnRIHNbR5IdtVkm0ayGuzwQKTWmU0hdjQ=="
+      "version": "1.10.51",
+      "resolved": "https://registry.npmjs.org/libphonenumber-js/-/libphonenumber-js-1.10.51.tgz",
+      "integrity": "sha512-vY2I+rQwrDQzoPds0JeTEpeWzbUJgqoV0O4v31PauHBb/e+1KCXKylHcDnBMgJZ9fH9mErsEbROJY3Z3JtqEmg=="
     },
     "node_modules/lie": {
       "version": "3.1.1",
@@ -9562,9 +9688,9 @@
       }
     },
     "node_modules/node-releases": {
-      "version": "2.0.13",
-      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz",
-      "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==",
+      "version": "2.0.14",
+      "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
+      "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
       "dev": true
     },
     "node_modules/normalize-package-data": {
@@ -9810,13 +9936,13 @@
       }
     },
     "node_modules/object.assign": {
-      "version": "4.1.4",
-      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz",
-      "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==",
+      "version": "4.1.5",
+      "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+      "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
       "dev": true,
       "dependencies": {
-        "call-bind": "^1.0.2",
-        "define-properties": "^1.1.4",
+        "call-bind": "^1.0.5",
+        "define-properties": "^1.2.1",
         "has-symbols": "^1.0.3",
         "object-keys": "^1.1.1"
       },
@@ -10172,9 +10298,9 @@
       }
     },
     "node_modules/path-scurry/node_modules/lru-cache": {
-      "version": "10.0.1",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz",
-      "integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==",
+      "version": "10.1.0",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz",
+      "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==",
       "dev": true,
       "engines": {
         "node": "14 || >=16.14"
@@ -10242,6 +10368,56 @@
         "node": ">=6"
       }
     },
+    "node_modules/pinia": {
+      "version": "2.1.7",
+      "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz",
+      "integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==",
+      "dependencies": {
+        "@vue/devtools-api": "^6.5.0",
+        "vue-demi": ">=0.14.5"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/posva"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.4.0",
+        "typescript": ">=4.4.4",
+        "vue": "^2.6.14 || ^3.3.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        },
+        "typescript": {
+          "optional": true
+        }
+      }
+    },
+    "node_modules/pinia/node_modules/vue-demi": {
+      "version": "0.14.6",
+      "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.6.tgz",
+      "integrity": "sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==",
+      "hasInstallScript": true,
+      "bin": {
+        "vue-demi-fix": "bin/vue-demi-fix.js",
+        "vue-demi-switch": "bin/vue-demi-switch.js"
+      },
+      "engines": {
+        "node": ">=12"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/antfu"
+      },
+      "peerDependencies": {
+        "@vue/composition-api": "^1.0.0-rc.1",
+        "vue": "^3.0.0-0 || ^2.6.0"
+      },
+      "peerDependenciesMeta": {
+        "@vue/composition-api": {
+          "optional": true
+        }
+      }
+    },
     "node_modules/pinkie": {
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
@@ -10457,21 +10633,27 @@
       }
     },
     "node_modules/postcss-load-config": {
-      "version": "4.0.1",
-      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.1.tgz",
-      "integrity": "sha512-vEJIc8RdiBRu3oRAI0ymerOn+7rPuMvRXslTvZUKZonDHFIczxztIyJ1urxM1x9JXEikvpWWTUUqal5j/8QgvA==",
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+      "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
       "dev": true,
+      "funding": [
+        {
+          "type": "opencollective",
+          "url": "https://opencollective.com/postcss/"
+        },
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/ai"
+        }
+      ],
       "dependencies": {
-        "lilconfig": "^2.0.5",
-        "yaml": "^2.1.1"
+        "lilconfig": "^3.0.0",
+        "yaml": "^2.3.4"
       },
       "engines": {
         "node": ">= 14"
       },
-      "funding": {
-        "type": "opencollective",
-        "url": "https://opencollective.com/postcss/"
-      },
       "peerDependencies": {
         "postcss": ">=8.0.9",
         "ts-node": ">=9.0.0"
@@ -10485,6 +10667,15 @@
         }
       }
     },
+    "node_modules/postcss-load-config/node_modules/lilconfig": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz",
+      "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==",
+      "dev": true,
+      "engines": {
+        "node": ">=14"
+      }
+    },
     "node_modules/postcss-modules-extract-imports": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
@@ -10732,9 +10923,9 @@
       }
     },
     "node_modules/query-builder-vue/node_modules/core-js": {
-      "version": "3.33.2",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.2.tgz",
-      "integrity": "sha512-XeBzWI6QL3nJQiHmdzbAOiMYqjrb7hwU7A39Qhvd/POSa/t9E1AeZyEZx3fNvp/vtM8zXwhoL0FsiS0hD0pruQ==",
+      "version": "3.33.3",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.3.tgz",
+      "integrity": "sha512-lo0kOocUlLKmm6kv/FswQL8zbkH7mVsLJ/FULClOhv8WRVmKLVcs6XPNQAzstfeJTCHMyButEwG+z1kHxHoDZw==",
       "hasInstallScript": true,
       "funding": {
         "type": "opencollective",
@@ -11998,9 +12189,9 @@
       }
     },
     "node_modules/sortablejs": {
-      "version": "1.15.0",
-      "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz",
-      "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w=="
+      "version": "1.15.1",
+      "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.1.tgz",
+      "integrity": "sha512-P5Cjvb0UG1ZVNiDPj/n4V+DinttXG6K8n7vM/HQf0C25K3YKQTQY6fsr/sEGsJGpQ9exmPxluHxKBc0mLKU1lQ=="
     },
     "node_modules/source-list-map": {
       "version": "2.0.1",
@@ -12464,15 +12655,16 @@
       }
     },
     "node_modules/svgo": {
-      "version": "3.0.3",
-      "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.3.tgz",
-      "integrity": "sha512-X4UZvLhOglD5Xrp834HzGHf8RKUW0Ahigg/08yRO1no9t2NxffOkMiQ0WmaMIbaGlVTlSst2zWANsdhz5ybXgA==",
+      "version": "3.0.5",
+      "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.0.5.tgz",
+      "integrity": "sha512-HQKHEo73pMNOlDlBcLgZRcHW2+1wo7bFYayAXkGN0l/2+h68KjlfZyMRhdhaGvoHV2eApOovl12zoFz42sT6rQ==",
       "dev": true,
       "dependencies": {
         "@trysound/sax": "0.2.0",
         "commander": "^7.2.0",
         "css-select": "^5.1.0",
         "css-tree": "^2.2.1",
+        "css-what": "^6.1.0",
         "csso": "5.0.5",
         "picocolors": "^1.0.0"
       },
@@ -13476,28 +13668,25 @@
       }
     },
     "node_modules/vite-plugin-full-reload": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.0.5.tgz",
-      "integrity": "sha512-kVZFDFWr0DxiHn6MuDVTQf7gnWIdETGlZh0hvTiMXzRN80vgF4PKbONSq8U1d0WtHsKaFODTQgJeakLacoPZEQ==",
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/vite-plugin-full-reload/-/vite-plugin-full-reload-1.1.0.tgz",
+      "integrity": "sha512-3cObNDzX6DdfhD9E7kf6w2mNunFpD7drxyNgHLw+XwIYAgb+Xt16SEXo0Up4VH+TMf3n+DSVJZtW2POBGcBYAA==",
       "dev": true,
       "dependencies": {
         "picocolors": "^1.0.0",
         "picomatch": "^2.3.1"
-      },
-      "peerDependencies": {
-        "vite": "^2 || ^3 || ^4"
       }
     },
     "node_modules/vue": {
-      "version": "3.3.8",
-      "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.8.tgz",
-      "integrity": "sha512-5VSX/3DabBikOXMsxzlW8JyfeLKlG9mzqnWgLQLty88vdZL7ZJgrdgBOmrArwxiLtmS+lNNpPcBYqrhE6TQW5w==",
+      "version": "3.3.9",
+      "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.9.tgz",
+      "integrity": "sha512-sy5sLCTR8m6tvUk1/ijri3Yqzgpdsmxgj6n6yl7GXXCXqVbmW2RCXe9atE4cEI6Iv7L89v5f35fZRRr5dChP9w==",
       "dependencies": {
-        "@vue/compiler-dom": "3.3.8",
-        "@vue/compiler-sfc": "3.3.8",
-        "@vue/runtime-dom": "3.3.8",
-        "@vue/server-renderer": "3.3.8",
-        "@vue/shared": "3.3.8"
+        "@vue/compiler-dom": "3.3.9",
+        "@vue/compiler-sfc": "3.3.9",
+        "@vue/runtime-dom": "3.3.9",
+        "@vue/server-renderer": "3.3.9",
+        "@vue/shared": "3.3.9"
       },
       "peerDependencies": {
         "typescript": "*"
@@ -13697,12 +13886,26 @@
       "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
       "dev": true
     },
-    "node_modules/vue2-editor": {
-      "version": "2.10.3",
-      "resolved": "https://registry.npmjs.org/vue2-editor/-/vue2-editor-2.10.3.tgz",
-      "integrity": "sha512-99rWL93xfGeFRrq8NY5L7U+Cog/Uenx+UOOJragtxtbhBE9Rv5/C3P/YhJhjMECSbQyHFjUriqv1S3mghvU9Kg==",
+    "node_modules/vue3-editor": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/vue3-editor/-/vue3-editor-0.1.1.tgz",
+      "integrity": "sha512-rH1U28wi+mHQlJFr4mvMW3D0oILnjV/BY9TslzWc6zM5zwv48I8LQk4sVzggN2KTDIGAdlDsmdReAd+7fhMYmQ==",
       "dependencies": {
-        "quill": "^1.3.6"
+        "core-js": "^3.6.5",
+        "quill": "^1.3.7"
+      },
+      "peerDependencies": {
+        "vue": "^3.0.0"
+      }
+    },
+    "node_modules/vue3-editor/node_modules/core-js": {
+      "version": "3.33.3",
+      "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.33.3.tgz",
+      "integrity": "sha512-lo0kOocUlLKmm6kv/FswQL8zbkH7mVsLJ/FULClOhv8WRVmKLVcs6XPNQAzstfeJTCHMyButEwG+z1kHxHoDZw==",
+      "hasInstallScript": true,
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/core-js"
       }
     },
     "node_modules/vue3-vt-notifications": {
@@ -13729,17 +13932,6 @@
       "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz",
       "integrity": "sha512-pBXvQCs5/33fdN1/39pPL0NZF20LeRbLQ5jtnheIPN9JQAaufGjKdWduZn4U7wCtVuzKhmRkI0DFYHYRbB2H1w=="
     },
-    "node_modules/vuex": {
-      "version": "4.1.0",
-      "resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz",
-      "integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==",
-      "dependencies": {
-        "@vue/devtools-api": "^6.0.0-beta.11"
-      },
-      "peerDependencies": {
-        "vue": "^3.2.0"
-      }
-    },
     "node_modules/watchpack": {
       "version": "2.4.0",
       "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz",
diff --git a/package.json b/package.json
index cf316bd52..be0bfae5e 100644
--- a/package.json
+++ b/package.json
@@ -21,6 +21,7 @@
     "js-cookie": "^2.2.1",
     "js-sha256": "^0.9.0",
     "libphonenumber-js": "^1.10.44",
+    "pinia": "^2.1.7",
     "prismjs": "^1.24.1",
     "qrcode": "^1.5.1",
     "query-builder-vue": "^1.2.0",
@@ -38,8 +39,7 @@
     "vue-signature-pad": "^3.0.2",
     "vue3-editor": "^0.1.1",
     "vue3-vt-notifications": "^1.0.0",
-    "vuedraggable": "^4.1.0",
-    "vuex": "^4.1.0"
+    "vuedraggable": "^4.1.0"
   },
   "devDependencies": {
     "@babel/core": "^7.20.12",
diff --git a/resources/js/app.js b/resources/js/app.js
index 6ab82ac20..d935a7ac4 100644
--- a/resources/js/app.js
+++ b/resources/js/app.js
@@ -1,5 +1,5 @@
 import { createApp, configureCompat, ref } from 'vue'
-import store from '~/store'
+import { createPinia } from 'pinia'
 import router from '~/router'
 import App from '~/components/App.vue'
 import Base from './base.js'
@@ -11,9 +11,10 @@ import '~/components'
 
 import '../sass/app.scss'
 
+const pinia = createPinia()
 const app = createApp(App)
   .use(router)
-  .use(store)
+  .use(pinia)
   .mixin(Base)
 
 registerPlugin(app)
@@ -25,7 +26,9 @@ configureCompat({
   // GLOBAL_MOUNT: false,
   COMPONENT_V_MODEL: false,
   INSTANCE_SET: false,
-  INSTANCE_DELETE: false
+  INSTANCE_DELETE: false,
+  ATTR_FALSE_VALUE: false,
+  WATCH_ARRAY: false
 })
 
 router.app = app
diff --git a/resources/js/components/App.vue b/resources/js/components/App.vue
index d6f39cb47..c9fd48f20 100644
--- a/resources/js/components/App.vue
+++ b/resources/js/components/App.vue
@@ -37,6 +37,8 @@
 </template>
 
 <script>
+import { computed } from 'vue'
+import { useAppStore } from '../stores/app'
 import Loading from './Loading.vue'
 import Hotjar from './service/Hotjar.vue'
 import Amplitude from './service/Amplitude.vue'
@@ -44,7 +46,6 @@ import Crisp from './service/Crisp.vue'
 import StopImpersonation from './pages/StopImpersonation.vue'
 import Notifications from './common/Notifications.vue'
 import SeoMeta from '../mixins/seo-meta.js'
-import { mapState } from 'vuex'
 
 // Load layout components dynamically.
 const requireContext = import.meta.glob('../layouts/**.vue', { eager: true })
@@ -74,6 +75,13 @@ export default {
 
   mixins: [SeoMeta],
 
+  setup () {
+    const appStore = useAppStore()
+    return {
+      layout : computed(() => appStore.layout)
+    }
+  },
+
   data: () => ({
     metaTitle: 'OpnForm',
     metaDescription: 'Create beautiful forms for free. Unlimited fields, unlimited submissions. It\'s free and it takes less than 1 minute to create your first form.',
@@ -95,9 +103,6 @@ export default {
     isOnboardingPage () {
       return this.$route.name === 'onboarding'
     },
-    ...mapState({
-      layout: state => state.app.layout
-    }),
     layoutComponent () {
       return layouts[this.layout]
     }
diff --git a/resources/js/components/Loading.vue b/resources/js/components/Loading.vue
index a7bc69870..672053da5 100644
--- a/resources/js/components/Loading.vue
+++ b/resources/js/components/Loading.vue
@@ -10,7 +10,8 @@
 
 <script>
 // https://github.com/nuxt/nuxt.js/blob/master/lib/app/components/nuxt-loading.vue
-import { mapState } from 'vuex'
+import { computed } from 'vue'
+import { useAppStore } from '../stores/app';
 
 export default {
   data: () => ({
@@ -19,12 +20,13 @@ export default {
     failedColor: 'red'
   }),
 
-  computed: {
-    ...mapState({
-      percent: state => state.app.loader.percent,
-      canSuccess: state => state.app.loader.canSuccess,
-      show: state => state.app.loader.show
-    })
+  setup () {
+    const appStore = useAppStore()
+    return {
+      percent : computed(() => appStore.loader.percent),
+      canSuccess : computed(() => appStore.loader.canSuccess),
+      show : computed(() => appStore.loader.show)
+    }
   }
 }
 </script>
diff --git a/resources/js/components/LoginWithGithub.vue b/resources/js/components/LoginWithGithub.vue
index 5f9974b39..e505a244d 100644
--- a/resources/js/components/LoginWithGithub.vue
+++ b/resources/js/components/LoginWithGithub.vue
@@ -14,9 +14,18 @@
 </template>
 
 <script>
+import { useAuthStore } from '../stores/auth'
+
 export default {
   name: 'LoginWithGithub',
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authStore
+    }
+  },
+
   computed: {
     githubAuth: () => window.config.githubAuth,
     url: () => '/api/oauth/github'
@@ -34,9 +43,7 @@ export default {
     async login () {
       const newWindow = openWindow('', 'Login')
 
-      const url = await this.$store.dispatch('auth/fetchOauthUrl', {
-        provider: 'github'
-      })
+      const url = await this.authStore.fetchOauthUrl('github')
 
       newWindow.location.href = url
     },
@@ -49,9 +56,7 @@ export default {
         return
       }
 
-      this.$store.dispatch('auth/saveToken', {
-        token: e.data.token
-      })
+      this.authStore.saveToken(e.data.token)
 
       this.$router.push({ name: 'home' })
     }
diff --git a/resources/js/components/Navbar.vue b/resources/js/components/Navbar.vue
index 47645c892..62036358c 100644
--- a/resources/js/components/Navbar.vue
+++ b/resources/js/components/Navbar.vue
@@ -132,7 +132,10 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../stores/auth';
+import { useFormsStore } from '../stores/forms';
+import { useWorkspacesStore } from '../stores/workspaces';
 import Dropdown from './common/Dropdown.vue'
 import WorkspaceDropdown from './WorkspaceDropdown.vue'
 
@@ -142,6 +145,18 @@ export default {
     Dropdown
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    const formsStore = useFormsStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      authStore,
+      formsStore,
+      workspacesStore,
+      user : computed(() => authStore.user)
+    }
+  },
+
   data: () => ({
     appName: window.config.appName
   }),
@@ -151,12 +166,12 @@ export default {
     helpUrl: () => window.config.links.help_url,
     form () {
       if (this.$route.name && this.$route.name.startsWith('forms.show_public')) {
-        return this.$store.getters['open/forms/getBySlug'](this.$route.params.slug)
+        return this.formsStore.getBySlug(this.$route.params.slug)
       }
       return null
     },
     workspace () {
-      return this.$store.getters['open/workspaces/getCurrent']()
+      return this.workspacesStore.getCurrent()
     },
     paidPlansEnabled () {
       return window.config.paid_plans_enabled
@@ -182,9 +197,6 @@ export default {
     isIframe () {
       return window.location !== window.parent.location || window.frameElement
     },
-    ...mapGetters({
-      user: 'auth/user'
-    }),
     userOnboarded () {
       return this.user && this.user.workspaces_count > 0
     },
@@ -196,11 +208,11 @@ export default {
   methods: {
     async logout () {
       // Log out the user.
-      await this.$store.dispatch('auth/logout')
+      await this.authStore.logout()
 
       // Reset store
-      this.$store.dispatch('open/workspaces/resetState')
-      this.$store.dispatch('open/forms/resetState')
+      this.workspacesStore.resetState()
+      this.formsStore.resetState()
 
       // Redirect to login.
       this.$router.push({ name: 'login' })
diff --git a/resources/js/components/WorkspaceDropdown.vue b/resources/js/components/WorkspaceDropdown.vue
index 96a4e052d..266ba6192 100644
--- a/resources/js/components/WorkspaceDropdown.vue
+++ b/resources/js/components/WorkspaceDropdown.vue
@@ -41,8 +41,11 @@
 </template>
 
 <script>
+import { computed } from 'vue'
+import { useAuthStore } from '../stores/auth'
+import { useFormsStore } from '../stores/forms'
+import { useWorkspacesStore } from '../stores/workspaces'
 import Dropdown from './common/Dropdown.vue'
-import { mapGetters, mapState } from 'vuex'
 
 export default {
 
@@ -51,20 +54,26 @@ export default {
     Dropdown
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    const formsStore = useFormsStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      formsStore,
+      workspacesStore,
+      user : computed(() => authStore.user),
+      workspaces : computed(() => workspacesStore.content),
+      loading : computed(() => workspacesStore.loading)
+    }
+  },
+
   data: () => ({
     appName: window.config.appName
   }),
 
   computed: {
-    ...mapState({
-      workspaces: state => state['open/workspaces'].content,
-      loading: state => state['open/workspaces'].loading
-    }),
-    ...mapGetters({
-      user: 'auth/user'
-    }),
     workspace () {
-      return this.$store.getters['open/workspaces/getCurrent']()
+      return this.workspacesStore.getCurrent()
     }
   },
 
@@ -76,12 +85,12 @@ export default {
 
   methods: {
     switchWorkspace (workspace) {
-      this.$store.commit('open/workspaces/setCurrentId', workspace.id)
+      this.workspacesStore.setCurrentId(workspace.id)
       this.$refs.dropdown.close()
       if (this.$route.name !== 'home') {
         this.$router.push({ name: 'home' })
       }
-      this.$store.dispatch('open/forms/load', workspace.id)
+      this.formsStore.load(workspace.id)
     },
     isUrl (str) {
       try {
diff --git a/resources/js/components/common/Breadcrumb.vue b/resources/js/components/common/Breadcrumb.vue
index ee6d46b5a..782fda712 100644
--- a/resources/js/components/common/Breadcrumb.vue
+++ b/resources/js/components/common/Breadcrumb.vue
@@ -54,7 +54,8 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth';
 
 export default {
   name: 'Breadcrumb',
@@ -66,20 +67,22 @@ export default {
     path: { type: Array }
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authenticated : computed(() => authStore.check)
+    }
+  },
+
   data () {
     return {
       displayHome: true
     }
   },
 
-  computed: {
-    ...mapGetters({
-      authenticated: 'auth/check'
-    })
-  },
+  computed: {},
 
-  mounted () {
-  },
+  mounted () {},
 
   methods: {}
 }
diff --git a/resources/js/components/common/ProTag.vue b/resources/js/components/common/ProTag.vue
index 1cc39eeb9..e5c16fd9e 100644
--- a/resources/js/components/common/ProTag.vue
+++ b/resources/js/components/common/ProTag.vue
@@ -37,8 +37,10 @@
 </template>
 
 <script>
+import { computed } from 'vue'
 import Modal from '../Modal.vue'
-import {mapGetters} from 'vuex'
+import { useAuthStore } from '../../stores/auth';
+import { useWorkspacesStore } from '../../stores/workspaces';
 import PricingTable from "../pages/pricing/PricingTable.vue";
 
 export default {
@@ -46,6 +48,15 @@ export default {
   components: {PricingTable, Modal},
   props: {},
 
+  setup () {
+    const authStore = useAuthStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      user : computed(() => authStore.user),
+      currentWorkSpace : computed(() => workspacesStore.getCurrent())
+    }
+  },
+
   data() {
     return {
       showPremiumModal: false,
@@ -54,10 +65,6 @@ export default {
   },
 
   computed: {
-    ...mapGetters({
-      user: 'auth/user',
-      currentWorkSpace: 'open/workspaces/getCurrent',
-    }),
     shouldDisplayProTag() {
       if (!window.config.paid_plans_enabled) return false
       if (!this.user || !this.currentWorkSpace) return true
diff --git a/resources/js/components/forms/PhoneInput.vue b/resources/js/components/forms/PhoneInput.vue
index ab84778c4..1d118ce45 100644
--- a/resources/js/components/forms/PhoneInput.vue
+++ b/resources/js/components/forms/PhoneInput.vue
@@ -11,7 +11,7 @@
                 :data="countries"
                 :disabled="disabled || countries.length===1" :searchable="true" :search-keys="['name']" :option-key="'code'" :color="color"
                 :has-error="hasValidation && form.errors.has(name)"
-                :placeholder="'Select a country'" :uppercase-labels="true" :theme="theme" @input="onChangeCountryCode"
+                :placeholder="'Select a country'" :uppercase-labels="true" :theme="theme" @update:model-value="onChangeCountryCode"
       >
         <template #option="props">
           <div class="flex items-center space-x-2 hover:text-white">
@@ -29,7 +29,7 @@
       </v-select>
       <input v-model="inputVal" type="text" class="inline-flex-grow !border-l-0 !rounded-l-none" :disabled="disabled"
             :class="[theme.default.input, { '!ring-red-500 !ring-2': hasValidation && form.errors.has(name), '!cursor-not-allowed !bg-gray-200': disabled }]"
-            :placeholder="placeholder" :style="inputStyle" @input="onInput"
+            :placeholder="placeholder" :style="inputStyle" @update:model-value="onInput"
       >
     </div>
 
diff --git a/resources/js/components/forms/components/InputWrapper.vue b/resources/js/components/forms/components/InputWrapper.vue
index d99cef580..c8703be35 100644
--- a/resources/js/components/forms/components/InputWrapper.vue
+++ b/resources/js/components/forms/components/InputWrapper.vue
@@ -22,7 +22,7 @@
       </input-help>
     </slot>
     <slot name="error">
-      <has-error v-if="hasValidation" :form="form" :field="name" />
+      <has-error v-if="hasValidation && form" :form="form" :field="name" />
     </slot>
   </div>
 </template>
diff --git a/resources/js/components/open/components/RecordOperations.vue b/resources/js/components/open/components/RecordOperations.vue
index 11de34940..972bff6af 100644
--- a/resources/js/components/open/components/RecordOperations.vue
+++ b/resources/js/components/open/components/RecordOperations.vue
@@ -16,8 +16,6 @@
 </template>
 
 <script>
-import { mapState } from 'vuex'
-import store from '~/store'
 import axios from 'axios'
 
 export default {
diff --git a/resources/js/components/open/forms/OpenForm.vue b/resources/js/components/open/forms/OpenForm.vue
index d6a0abd99..d140afa9c 100644
--- a/resources/js/components/open/forms/OpenForm.vue
+++ b/resources/js/components/open/forms/OpenForm.vue
@@ -62,6 +62,9 @@
 <script>
 import axios from 'axios'
 import Form from 'vform'
+import { computed } from 'vue'
+import { useRecordsStore } from '../../../stores/records'
+import { useWorkingFormStore } from '../../../stores/working_form'
 import OpenFormButton from './OpenFormButton.vue'
 import clonedeep from 'clone-deep'
 import FormLogicPropertyResolver from '../../../forms/FormLogicPropertyResolver.js'
@@ -100,6 +103,16 @@ export default {
     },
     adminPreview: { type: Boolean, default: false } // If used in FormEditorPreview
   },
+
+  setup () {
+    const recordsStore = useRecordsStore()
+    const workingFormStore = useWorkingFormStore()
+    return {
+      recordsStore,
+      workingFormStore
+    }
+  },
+
   data () {
     return {
       dataForm: null,
@@ -154,8 +167,8 @@ export default {
             newFields.push(...group)
           }
         })
-        // set the properties on working_form vuex
-        this.$store.commit('open/working_form/setProperties', newFields)
+        // set the properties on working_form store
+        this.workingFormStore.setProperties(newFields)
       }
     },
     /**
@@ -293,12 +306,12 @@ export default {
       if (!this.form || !this.form.editable_submissions || !this.form.submission_id) {
         return null
       }
-      await this.$store.dispatch('open/records/loadRecord',
+      await this.recordsStore.loadRecord(
         axios.get('/api/forms/' + this.form.slug + '/submissions/' + this.form.submission_id).then((response) => {
           return { submission_id: this.form.submission_id, ...response.data.data }
         })
       )
-      return this.$store.getters['open/records/getById'](this.form.submission_id)
+      return this.recordsStore.getById(this.form.submission_id)
     },
     async initForm () {
       if (this.isPublicFormPage && this.form.editable_submissions) {
diff --git a/resources/js/components/open/forms/OpenFormField.vue b/resources/js/components/open/forms/OpenFormField.vue
index b96ae6d91..d77dda902 100644
--- a/resources/js/components/open/forms/OpenFormField.vue
+++ b/resources/js/components/open/forms/OpenFormField.vue
@@ -78,9 +78,10 @@
 </template>
 
 <script>
+import { computed } from 'vue'
+import { useWorkingFormStore } from '../../../stores/working_form';
 import FormLogicPropertyResolver from '../../../forms/FormLogicPropertyResolver.js'
 import FormPendingSubmissionKey from '../../../mixins/forms/form-pending-submission-key.js'
-import {mapState} from "vuex";
 
 export default {
   name: 'OpenFormField',
@@ -113,15 +114,21 @@ export default {
     },
     adminPreview: {type: Boolean, default: false} // If used in FormEditorPreview
   },
+
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore,
+      selectedFieldIndex : computed(() => workingFormStore.selectedFieldIndex),
+      showEditFieldSidebar : computed(() => workingFormStore.showEditFieldSidebar)
+    }
+  },
+
   data() {
     return {}
   },
 
   computed: {
-    ...mapState({
-      selectedFieldIndex: state => state['open/working_form'].selectedFieldIndex,
-      showEditFieldSidebar: state => state['open/working_form'].showEditFieldSidebar
-    }),
     fieldComponents() {
       return {
         text: 'TextInput',
@@ -214,10 +221,10 @@ export default {
 
   methods: {
     editFieldOptions() {
-      this.$store.commit('open/working_form/openSettingsForField', this.field)
+      this.workingFormStore.openSettingsForField(this.field)
     },
     openAddFieldSidebar() {
-      this.$store.commit('open/working_form/openAddFieldSidebar', this.field)
+      this.workingFormStore.openAddFieldSidebar(this.field)
     },
     /**
      * Get the right input component for the field/options combination
diff --git a/resources/js/components/open/forms/components/AdvancedFormUrlSettings.vue b/resources/js/components/open/forms/components/AdvancedFormUrlSettings.vue
index 0cce1d600..03ba81c1a 100644
--- a/resources/js/components/open/forms/components/AdvancedFormUrlSettings.vue
+++ b/resources/js/components/open/forms/components/AdvancedFormUrlSettings.vue
@@ -13,12 +13,12 @@
                          label="Hide Form Title"
                          :disabled="form.hide_title===true"
                          :help="hideTitleHelp"
-                         @input="onChangeHideTitle"
+                         @update:model-value="onChangeHideTitle"
     />
     <toggle-switch-input :value="value.auto_submit" name="auto_submit" class="mt-4"
                          label="Auto Submit Form"
                          help="Form will auto submit immediate after open URL"
-                         @input="onChangeAutoSubmit"
+                         @update:model-value="onChangeAutoSubmit"
     />
   </collapse>
 </template>
diff --git a/resources/js/components/open/forms/components/FormEditor.vue b/resources/js/components/open/forms/components/FormEditor.vue
index 01c6eed33..4ab59ff63 100644
--- a/resources/js/components/open/forms/components/FormEditor.vue
+++ b/resources/js/components/open/forms/components/FormEditor.vue
@@ -85,7 +85,11 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../../../stores/auth';
+import { useFormsStore } from '../../../../stores/forms';
+import { useWorkingFormStore } from '../../../../stores/working_form';
+import { useWorkspacesStore } from '../../../../stores/workspaces';
 import AddFormBlockSidebar from './form-components/AddFormBlockSidebar.vue'
 import FormFieldEditSidebar from '../fields/FormFieldEditSidebar.vue'
 import FormErrorModal from './form-components/FormErrorModal.vue'
@@ -143,6 +147,19 @@ export default {
     }
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    const formsStore = useFormsStore()
+    const workingFormStore = useWorkingFormStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      formsStore,
+      workingFormStore,
+      workspacesStore,
+      user : computed(() => authStore.user)
+    }
+  },
+
   data () {
     return {
       showFormErrorModal: false,
@@ -153,23 +170,20 @@ export default {
   },
 
   computed: {
-    ...mapGetters({
-      user: 'auth/user'
-    }),
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     createdForm () {
-      return this.$store.getters['open/forms/getById'](this.createdFormId)
+      return this.formsStore.getById(this.createdFormId)
     },
     workspace () {
-      return this.$store.getters['open/workspaces/getCurrent']()
+      return this.workspacesStore.getCurrent()
     },
     steps () {
       return [
@@ -245,7 +259,7 @@ export default {
       this.validationErrorResponse = null
       this.form.put('/api/open/forms/{id}/'.replace('{id}', this.form.id)).then((response) => {
         const data = response.data
-        this.$store.commit('open/forms/addOrUpdate', data.form)
+        this.formsStore.addOrUpdate(data.form)
         this.$emit('on-save')
         this.$router.push({ name: 'forms.show', params: { slug: this.form.slug } })
         this.$logEvent('form_saved', { form_id: this.form.id, form_slug: this.form.slug })
@@ -266,7 +280,7 @@ export default {
 
       this.updateFormLoading = true
       this.form.post('/api/open/forms').then((response) => {
-        this.$store.commit('open/forms/addOrUpdate', response.data.form)
+        this.formsStore.addOrUpdate(response.data.form)
         this.$emit('on-save')
         this.createdFormId = response.data.form.id
 
diff --git a/resources/js/components/open/forms/components/FormFieldsEditor.vue b/resources/js/components/open/forms/components/FormFieldsEditor.vue
index 9d8c0e291..f524c02d3 100644
--- a/resources/js/components/open/forms/components/FormFieldsEditor.vue
+++ b/resources/js/components/open/forms/components/FormFieldsEditor.vue
@@ -166,6 +166,8 @@
 </template>
 
 <script>
+import { computed } from 'vue'
+import { useWorkingFormStore } from '../../../../stores/working_form'
 import draggable from 'vuedraggable'
 import ProTag from '../../../common/ProTag.vue'
 import clonedeep from 'clone-deep'
@@ -182,6 +184,13 @@ export default {
     EditableDiv
   },
 
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
+
   data () {
     return {
       formFields: [],
@@ -192,11 +201,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   },
@@ -313,7 +322,7 @@ export default {
       return type
     },
     editOptions (index) {
-      this.$store.commit('open/working_form/openSettingsForField', index)
+      this.workingFormStore.openSettingsForField(index)
     },
     removeBlock (blockIndex) {
       const newFields = clonedeep(this.formFields)
@@ -322,10 +331,10 @@ export default {
       this.closeSidebar()
     },
     closeSidebar () {
-      this.$store.commit('open/working_form/closeEditFieldSidebar')
+      this.workingFormStore.closeEditFieldSidebar()
     },
     openAddFieldSidebar () {
-      this.$store.commit('open/working_form/openAddFieldSidebar', null)
+      this.workingFormStore.openAddFieldSidebar(null)
     }
   }
 }
diff --git a/resources/js/components/open/forms/components/FormSubmissions.vue b/resources/js/components/open/forms/components/FormSubmissions.vue
index e1fce1dd2..3700f7ca7 100644
--- a/resources/js/components/open/forms/components/FormSubmissions.vue
+++ b/resources/js/components/open/forms/components/FormSubmissions.vue
@@ -25,7 +25,7 @@
           </h4>
           <div v-for="field in properties" :key="field.id" class="p-2 border">
             {{ field.name }}
-            <v-switch v-model="displayColumns[field.id]" class="float-right" @input="onChangeDisplayColumns" />
+            <v-switch v-model="displayColumns[field.id]" class="float-right" @update:model-value="onChangeDisplayColumns" />
           </div>
         </template>
         <template v-if="removed_properties.length > 0">
@@ -34,7 +34,7 @@
           </h4>
           <div v-for="field in removed_properties" :key="field.id" class="p-2 border">
             {{ field.name }}
-            <v-switch v-model="displayColumns[field.id]" class="float-right" @input="onChangeDisplayColumns" />
+            <v-switch v-model="displayColumns[field.id]" class="float-right" @update:model-value="onChangeDisplayColumns" />
           </div>
         </template>
       </div>
@@ -83,6 +83,7 @@
 import axios from 'axios'
 import Fuse from 'fuse.js'
 import Form from 'vform'
+import { useWorkingFormStore } from '../../../../stores/working_form'
 import ScrollShadow from '../../../common/ScrollShadow.vue'
 import OpenTable from '../../tables/OpenTable.vue'
 import clonedeep from 'clone-deep'
@@ -92,6 +93,15 @@ export default {
   name: 'FormSubmissions',
   components: { ScrollShadow, OpenTable, VSwitch },
   props: {},
+
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
+
+
   data () {
     return {
       formInitDone: false,
@@ -111,10 +121,10 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     exportUrl () {
diff --git a/resources/js/components/open/forms/components/form-components/AddFormBlockSidebar.vue b/resources/js/components/open/forms/components/form-components/AddFormBlockSidebar.vue
index f07f48657..fe5806d4f 100644
--- a/resources/js/components/open/forms/components/form-components/AddFormBlockSidebar.vue
+++ b/resources/js/components/open/forms/components/form-components/AddFormBlockSidebar.vue
@@ -30,7 +30,7 @@
             <div class="mx-auto">
               <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-500" fill="none" viewBox="0 0 24 24"
                    stroke="currentColor" stroke-width="2" v-html="block.icon"
-              />
+              ></svg>
             </div>
             <p class="w-full text-xs text-gray-500 uppercase text-center font-semibold mt-1">
               {{ block.title }}
@@ -50,7 +50,7 @@
             <div class="mx-auto">
               <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-gray-500" fill="none" viewBox="0 0 24 24"
                    stroke="currentColor" stroke-width="2" v-html="block.icon"
-              />
+              ></svg>
             </div>
             <p class="w-full text-xs text-gray-500 uppercase text-center font-semibold mt-1">
               {{ block.title }}
@@ -63,14 +63,26 @@
 </template>
 
 <script>
-import { mapState } from 'vuex'
 import Form from 'vform'
 import clonedeep from 'clone-deep'
+import { computed } from 'vue'
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 
 export default {
   name: 'AddFormBlockSidebar',
   components: {},
   props: {},
+
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore,
+      selectedFieldIndex : computed(() => workingFormStore.selectedFieldIndex),
+      showAddFieldSidebar : computed(() => workingFormStore.showAddFieldSidebar)
+    }
+  },
+
+
   data () {
     return {
       blockForm: null,
@@ -162,17 +174,13 @@ export default {
   },
 
   computed: {
-    ...mapState({
-      selectedFieldIndex: state => state['open/working_form'].selectedFieldIndex,
-      showAddFieldSidebar: state => state['open/working_form'].showAddFieldSidebar
-    }),
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     showSidebar () {
@@ -209,7 +217,7 @@ export default {
 
   methods: {
     closeSidebar () {
-      this.$store.commit('open/working_form/closeAddFieldSidebar')
+      this.workingFormStore.closeAddFieldSidebar()
     },
     reset () {
       this.blockForm = new Form({
@@ -231,12 +239,12 @@ export default {
         const newFields = clonedeep(this.form.properties)
         newFields.push(newBlock)
         this.form.properties = newFields
-        this.$store.commit('open/working_form/openSettingsForField', this.form.properties.length - 1)
+        this.workingFormStore.openSettingsForField(this.form.properties.length - 1)
       } else {
         const newFields = clonedeep(this.form.properties)
         newFields.splice(this.selectedFieldIndex + 1, 0, newBlock)
         this.form.properties = newFields
-        this.$store.commit('open/working_form/openSettingsForField', this.selectedFieldIndex + 1)
+        this.workingFormStore.openSettingsForField(this.selectedFieldIndex + 1)
       }
       this.reset()
     },
diff --git a/resources/js/components/open/forms/components/form-components/FormAboutSubmission.vue b/resources/js/components/open/forms/components/form-components/FormAboutSubmission.vue
index 4d90b492e..66440d1a4 100644
--- a/resources/js/components/open/forms/components/form-components/FormAboutSubmission.vue
+++ b/resources/js/components/open/forms/components/form-components/FormAboutSubmission.vue
@@ -129,6 +129,7 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
 import ProTag from '../../../../common/ProTag.vue'
 import VTransition from '../../../../common/transitions/VTransition.vue'
@@ -136,6 +137,12 @@ import VTransition from '../../../../common/transitions/VTransition.vue'
 export default {
   components: {EditorOptionsPanel, ProTag, VTransition},
   props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
   data () {
     return {
       submissionOptions: {}
@@ -145,11 +152,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     /**
diff --git a/resources/js/components/open/forms/components/form-components/FormAccess.vue b/resources/js/components/open/forms/components/form-components/FormAccess.vue
index 9f6575158..356fd73c2 100644
--- a/resources/js/components/open/forms/components/form-components/FormAccess.vue
+++ b/resources/js/components/open/forms/components/form-components/FormAccess.vue
@@ -38,11 +38,18 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
 
 export default {
   components: { EditorOptionsPanel },
   props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
   data () {
     return {
     }
@@ -50,11 +57,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   },
diff --git a/resources/js/components/open/forms/components/form-components/FormCustomCode.vue b/resources/js/components/open/forms/components/form-components/FormCustomCode.vue
index f15767dab..6ea69b3f9 100644
--- a/resources/js/components/open/forms/components/form-components/FormCustomCode.vue
+++ b/resources/js/components/open/forms/components/form-components/FormCustomCode.vue
@@ -17,12 +17,18 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
 import CodeInput from '../../../../forms/CodeInput.vue'
 
 export default {
   components: { EditorOptionsPanel, CodeInput },
-  props: {
+  props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
   },
   data () {
     return {
@@ -32,11 +38,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   },
diff --git a/resources/js/components/open/forms/components/form-components/FormCustomSeo.vue b/resources/js/components/open/forms/components/form-components/FormCustomSeo.vue
index 44a136c3f..4fe2d2d07 100644
--- a/resources/js/components/open/forms/components/form-components/FormCustomSeo.vue
+++ b/resources/js/components/open/forms/components/form-components/FormCustomSeo.vue
@@ -23,11 +23,18 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
 
 export default {
   components: { EditorOptionsPanel },
   props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
   data () {
     return {
     }
@@ -35,11 +42,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   },
diff --git a/resources/js/components/open/forms/components/form-components/FormCustomization.vue b/resources/js/components/open/forms/components/form-components/FormCustomization.vue
index cd5540553..15e10d71a 100644
--- a/resources/js/components/open/forms/components/form-components/FormCustomization.vue
+++ b/resources/js/components/open/forms/components/form-components/FormCustomization.vue
@@ -71,7 +71,7 @@
     />
     <toggle-switch-input name="confetti_on_submission" :form="form" class="mt-4"
                          label="Confetti on successful submisison"
-                         @input="onChangeConfettiOnSubmission"
+                         @update:model-value="onChangeConfettiOnSubmission"
     />
     <toggle-switch-input name="auto_save" :form="form"
                          label="Auto save form response"
@@ -81,6 +81,7 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
 import ProTag from '../../../../common/ProTag.vue'
 
@@ -88,6 +89,12 @@ export default {
   components: { EditorOptionsPanel, ProTag },
   props: {
   },
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
   data () {
     return {
       isMounted: false
@@ -97,11 +104,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   },
diff --git a/resources/js/components/open/forms/components/form-components/FormEditorPreview.vue b/resources/js/components/open/forms/components/form-components/FormEditorPreview.vue
index 43c22e79a..fd10eddb3 100644
--- a/resources/js/components/open/forms/components/form-components/FormEditorPreview.vue
+++ b/resources/js/components/open/forms/components/form-components/FormEditorPreview.vue
@@ -59,12 +59,18 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import VSwitch from '../../../../forms/components/VSwitch.vue'
 import OpenCompleteForm from '../../OpenCompleteForm.vue'
 
 export default {
   components: { OpenCompleteForm, VSwitch },
-  props: {
+  props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
   },
   data () {
     return {
@@ -75,11 +81,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     creating () { // returns true if we are creating a form
diff --git a/resources/js/components/open/forms/components/form-components/FormInformation.vue b/resources/js/components/open/forms/components/form-components/FormInformation.vue
index e73d6cd75..0f5e53d67 100644
--- a/resources/js/components/open/forms/components/form-components/FormInformation.vue
+++ b/resources/js/components/open/forms/components/form-components/FormInformation.vue
@@ -66,14 +66,27 @@
 </template>
 
 <script>
+import { computed } from 'vue'
+import clonedeep from 'clone-deep'
+import { useFormsStore } from '../../../../../stores/forms'
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
 import SelectInput from '../../../../forms/SelectInput.vue'
-import { mapState } from 'vuex'
-import clonedeep from 'clone-deep'
 
 export default {
   components: { SelectInput, EditorOptionsPanel },
   props: {},
+
+  setup () {
+    const formsStore = useFormsStore()
+    const workingFormStore = useWorkingFormStore()
+    return {
+      formsStore,
+      workingFormStore,
+      forms : computed(() => formsStore.content)
+    }
+  },
+
   data () {
     return {
       showCopyFormSettingsModal: false,
@@ -106,20 +119,17 @@ export default {
         }
       })
     },
-    ...mapState({
-      forms: state => state['open/forms'].content
-    }),
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     allTagsOptions () {
-      return this.$store.getters['open/forms/getAllTags'].map((tagname) => {
+      return this.formsStore.getAllTags.map((tagname) => {
         return {
           name: tagname,
           value: tagname
diff --git a/resources/js/components/open/forms/components/form-components/FormNotifications.vue b/resources/js/components/open/forms/components/form-components/FormNotifications.vue
index fd275d24a..5685cebe3 100644
--- a/resources/js/components/open/forms/components/form-components/FormNotifications.vue
+++ b/resources/js/components/open/forms/components/form-components/FormNotifications.vue
@@ -31,6 +31,7 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
 import FormNotificationsOption from './components/FormNotificationsOption.vue'
 import FormNotificationsSlack from './components/FormNotificationsSlack.vue'
@@ -40,7 +41,12 @@ import FormNotificationsWebhook from './components/FormNotificationsWebhook.vue'
 
 export default {
   components: { FormNotificationsSubmissionConfirmation, FormNotificationsSlack, FormNotificationsDiscord, FormNotificationsOption, EditorOptionsPanel, FormNotificationsWebhook },
-  props: {
+  props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
   },
   data () {
     return {
@@ -50,11 +56,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     zapierUrl: () => window.config.links.zapier_integration
diff --git a/resources/js/components/open/forms/components/form-components/FormSecurityPrivacy.vue b/resources/js/components/open/forms/components/form-components/FormSecurityPrivacy.vue
index e736d25cd..884f1be26 100644
--- a/resources/js/components/open/forms/components/form-components/FormSecurityPrivacy.vue
+++ b/resources/js/components/open/forms/components/form-components/FormSecurityPrivacy.vue
@@ -17,11 +17,17 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
 
 export default {
   components: { EditorOptionsPanel },
-  props: {
+  props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
   },
   data () {
     return {
@@ -30,11 +36,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   },
diff --git a/resources/js/components/open/forms/components/form-components/FormStructure.vue b/resources/js/components/open/forms/components/form-components/FormStructure.vue
index 20b901fa5..56e5dd602 100644
--- a/resources/js/components/open/forms/components/form-components/FormStructure.vue
+++ b/resources/js/components/open/forms/components/form-components/FormStructure.vue
@@ -11,12 +11,18 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../stores/working_form'
 import EditorOptionsPanel from '../../../editors/EditorOptionsPanel.vue'
 import FormFieldsEditor from '../FormFieldsEditor.vue'
 
 export default {
   components: { EditorOptionsPanel, FormFieldsEditor },
-  props: {
+  props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
   },
   data () {
     return {
@@ -26,11 +32,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   }
diff --git a/resources/js/components/open/forms/components/form-components/components/FormNotificationsDiscord.vue b/resources/js/components/open/forms/components/form-components/components/FormNotificationsDiscord.vue
index 16ae57f57..8d9e8a5e1 100644
--- a/resources/js/components/open/forms/components/form-components/components/FormNotificationsDiscord.vue
+++ b/resources/js/components/open/forms/components/form-components/components/FormNotificationsDiscord.vue
@@ -46,12 +46,19 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../../stores/working_form'
 import ProTag from '../../../../../common/ProTag.vue'
 import FormNotificationsMessageActions from './FormNotificationsMessageActions.vue'
 
 export default {
   components: { ProTag, FormNotificationsMessageActions },
   props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
   data () {
     return {
       showModal: false
@@ -61,11 +68,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   },
diff --git a/resources/js/components/open/forms/components/form-components/components/FormNotificationsOption.vue b/resources/js/components/open/forms/components/form-components/components/FormNotificationsOption.vue
index df478c42d..d2d5628b5 100644
--- a/resources/js/components/open/forms/components/form-components/components/FormNotificationsOption.vue
+++ b/resources/js/components/open/forms/components/form-components/components/FormNotificationsOption.vue
@@ -50,11 +50,18 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../../stores/working_form'
 import ProTag from '../../../../../common/ProTag.vue'
 
 export default {
   components: { ProTag },
   props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
   data () {
     return {
       showModal: false
@@ -64,11 +71,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     replayToEmailField () {
diff --git a/resources/js/components/open/forms/components/form-components/components/FormNotificationsSlack.vue b/resources/js/components/open/forms/components/form-components/components/FormNotificationsSlack.vue
index dde15fcc1..a230c537d 100644
--- a/resources/js/components/open/forms/components/form-components/components/FormNotificationsSlack.vue
+++ b/resources/js/components/open/forms/components/form-components/components/FormNotificationsSlack.vue
@@ -47,12 +47,19 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../../stores/working_form'
 import ProTag from '../../../../../common/ProTag.vue'
 import FormNotificationsMessageActions from './FormNotificationsMessageActions.vue'
 
 export default {
   components: { ProTag, FormNotificationsMessageActions },
   props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
   data () {
     return {
       showModal: false
@@ -62,11 +69,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   },
diff --git a/resources/js/components/open/forms/components/form-components/components/FormNotificationsSubmissionConfirmation.vue b/resources/js/components/open/forms/components/form-components/components/FormNotificationsSubmissionConfirmation.vue
index 92eaf4d6f..8fe9e7f43 100644
--- a/resources/js/components/open/forms/components/form-components/components/FormNotificationsSubmissionConfirmation.vue
+++ b/resources/js/components/open/forms/components/form-components/components/FormNotificationsSubmissionConfirmation.vue
@@ -62,11 +62,18 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../../stores/working_form'
 import ProTag from '../../../../../common/ProTag.vue'
 
 export default {
   components: { ProTag },
   props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
   data () {
     return {
       showModal: false
@@ -76,11 +83,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     emailSubmissionConfirmationField () {
diff --git a/resources/js/components/open/forms/components/form-components/components/FormNotificationsWebhook.vue b/resources/js/components/open/forms/components/form-components/components/FormNotificationsWebhook.vue
index eec910275..bcaca9fb4 100644
--- a/resources/js/components/open/forms/components/form-components/components/FormNotificationsWebhook.vue
+++ b/resources/js/components/open/forms/components/form-components/components/FormNotificationsWebhook.vue
@@ -43,11 +43,18 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../../../../stores/working_form'
 import ProTag from '../../../../../common/ProTag.vue'
 
 export default {
   components: { ProTag },
   props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
   data () {
     return {
       showModal: false
@@ -57,11 +64,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     }
   },
diff --git a/resources/js/components/open/forms/components/form-logic-components/FormBlockLogicEditor.vue b/resources/js/components/open/forms/components/form-logic-components/FormBlockLogicEditor.vue
index fce7cdbcc..fb78ab0af 100644
--- a/resources/js/components/open/forms/components/form-logic-components/FormBlockLogicEditor.vue
+++ b/resources/js/components/open/forms/components/form-logic-components/FormBlockLogicEditor.vue
@@ -38,7 +38,7 @@
                   :multiple="true" class="mt-1" placeholder="Actions..."
                   help="Action(s) triggerred when above conditions are true"
                   :options="actionOptions"
-                  @input="onActionInput"
+                  @update:model-value="onActionInput"
     />
 
     <modal :show="showCopyFormModal" @close="showCopyFormModal = false">
diff --git a/resources/js/components/open/forms/components/templates/FormTemplateModal.vue b/resources/js/components/open/forms/components/templates/FormTemplateModal.vue
index 0ce7f8a3c..65a87a5f0 100644
--- a/resources/js/components/open/forms/components/templates/FormTemplateModal.vue
+++ b/resources/js/components/open/forms/components/templates/FormTemplateModal.vue
@@ -72,10 +72,11 @@
 </template>
 
 <script>
-import Form from 'vform'
-import store from '~/store'
-import { mapState, mapGetters } from 'vuex'
 import axios from 'axios'
+import Form from 'vform'
+import { computed } from 'vue'
+import { useAuthStore } from '../../../../../stores/auth'
+import { useTemplatesStore } from '../../../../../stores/templates'
 import QuestionsEditor from './QuestionsEditor.vue'
 
 export default {
@@ -87,6 +88,18 @@ export default {
     template: { type: Object, required: false, default: () => {} }
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    const templatesStore = useTemplatesStore()
+    return {
+      templatesStore,
+      user : computed(() => authStore.user),
+      templates : computed(() => templatesStore.content),
+      industries : computed(() => templatesStore.industries),
+      types : computed(() => templatesStore.types)
+    }
+  },
+
   data: () => ({
     templateForm: null
   }),
@@ -104,18 +117,10 @@ export default {
       related_templates: null,
       questions: []
     })
-    store.dispatch('open/templates/loadIfEmpty')
+    this.templatesStore.loadIfEmpty()
   },
 
   computed: {
-    ...mapState({
-      templates: state => state['open/templates'].content,
-      industries: state => state['open/templates'].industries,
-      types: state => state['open/templates'].types
-    }),
-    ...mapGetters({
-      user: 'auth/user'
-    }),
     typesOptions () {
       return Object.values(this.types).map((type) => {
         return {
@@ -156,7 +161,7 @@ export default {
         if (response.data.message) {
           this.alertSuccess(response.data.message)
         }
-        this.$store.commit('open/templates/addOrUpdate', response.data.data)
+        this.templatesStore.addOrUpdate(response.data.data)
         this.$emit('close')
       })
     },
@@ -166,7 +171,7 @@ export default {
         if (response.data.message) {
           this.alertSuccess(response.data.message)
         }
-        this.$store.commit('open/templates/addOrUpdate', response.data.data)
+        this.templatesStore.addOrUpdate(response.data.data)
         this.$emit('close')
       })
     },
@@ -177,7 +182,7 @@ export default {
           this.alertSuccess(response.data.message)
         }
         this.$router.push({ name: 'templates' })
-        this.$store.commit('open/templates/remove', this.template)
+        this.templatesStore.remove(this.template)
         this.$emit('close')
       })
     }
diff --git a/resources/js/components/open/forms/fields/FormFieldEditSidebar.vue b/resources/js/components/open/forms/fields/FormFieldEditSidebar.vue
index 05bad871d..101e87f9c 100644
--- a/resources/js/components/open/forms/fields/FormFieldEditSidebar.vue
+++ b/resources/js/components/open/forms/fields/FormFieldEditSidebar.vue
@@ -70,8 +70,9 @@
 </template>
 
 <script>
-import { mapState } from 'vuex'
+import { computed } from 'vue'
 import clonedeep from 'clone-deep'
+import { useWorkingFormStore } from '../../../../stores/working_form'
 import ChangeFieldType from './components/ChangeFieldType.vue'
 import FieldOptions from './components/FieldOptions.vue'
 import BlockOptions from './components/BlockOptions.vue'
@@ -80,6 +81,14 @@ export default {
   name: 'FormFieldEditSidebar',
   components: { ChangeFieldType, FieldOptions, BlockOptions },
   props: {},
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore,
+      selectedFieldIndex : computed(() => workingFormStore.selectedFieldIndex),
+      showEditFieldSidebar : computed(() => workingFormStore.showEditFieldSidebar)
+    }
+  },
   data () {
     return {
 
@@ -87,17 +96,13 @@ export default {
   },
 
   computed: {
-    ...mapState({
-      selectedFieldIndex: state => state['open/working_form'].selectedFieldIndex,
-      showEditFieldSidebar: state => state['open/working_form'].showEditFieldSidebar
-    }),
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     field () {
@@ -145,7 +150,7 @@ export default {
       this.closeSidebar()
     },
     closeSidebar () {
-      this.$store.commit('open/working_form/closeEditFieldSidebar')
+      this.workingFormStore.closeEditFieldSidebar()
     },
     generateUUID () {
       let d = new Date().getTime()// Timestamp
diff --git a/resources/js/components/open/forms/fields/components/FieldOptions.vue b/resources/js/components/open/forms/fields/components/FieldOptions.vue
index f1f16cbab..6f1db50b3 100644
--- a/resources/js/components/open/forms/fields/components/FieldOptions.vue
+++ b/resources/js/components/open/forms/fields/components/FieldOptions.vue
@@ -186,7 +186,7 @@
       <text-area-input v-model="optionsText" :name="field.id+'_options_text'" class="mt-3"
                        label="Set selection options"
                        help="Add one option per line"
-                       @input="onFieldOptionsChange"
+                       @update:model-value="onFieldOptionsChange"
       />
       <v-checkbox v-model="field.allow_creation"
                   name="allow_creation" help="" @update:model-value="onFieldAllowCreationChange"
diff --git a/resources/js/components/open/tables/OpenTable.vue b/resources/js/components/open/tables/OpenTable.vue
index 39737b7db..388d94748 100644
--- a/resources/js/components/open/tables/OpenTable.vue
+++ b/resources/js/components/open/tables/OpenTable.vue
@@ -78,6 +78,7 @@
 </template>
 
 <script>
+import { useWorkingFormStore } from '../../../stores/working_form'
 import OpenText from './components/OpenText.vue'
 import OpenUrl from './components/OpenUrl.vue'
 import OpenSelect from './components/OpenSelect.vue'
@@ -119,6 +120,13 @@ export default {
     }
   },
 
+  setup () {
+    const workingFormStore = useWorkingFormStore()
+    return {
+      workingFormStore
+    }
+  },
+
   data () {
     return {
       tableHash: null,
@@ -129,10 +137,11 @@ export default {
   computed: {
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
+      /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     hasActions () {
diff --git a/resources/js/components/pages/OpenFormFooter.vue b/resources/js/components/pages/OpenFormFooter.vue
index 6bfd698d0..c2e04bc27 100644
--- a/resources/js/components/pages/OpenFormFooter.vue
+++ b/resources/js/components/pages/OpenFormFooter.vue
@@ -31,18 +31,23 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
 
 export default {
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      user : computed(() => authStore.user)
+    }
+  },
+
   data: () => ({
     appName: window.config.appName,
     currYear: new Date().getFullYear(),
   }),
 
   computed: {
-    ...mapGetters({
-      user: 'auth/user'
-    }),
     helpUrl: () => window.config.links.help_url,
     githubUrl: () => window.config.links.github_url,
     forumUrl: () => window.config.links.github_forum_url,
diff --git a/resources/js/components/pages/StopImpersonation.vue b/resources/js/components/pages/StopImpersonation.vue
index e8db87fdf..d336c0a88 100644
--- a/resources/js/components/pages/StopImpersonation.vue
+++ b/resources/js/components/pages/StopImpersonation.vue
@@ -24,28 +24,34 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth';
+import { useWorkspacesStore } from '../../stores/workspaces';
 
 export default {
+  setup () {
+    const authStore = useAuthStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      authStore,
+      workspacesStore,
+      isImpersonating : computed(() => authStore.isImpersonating),
+    }
+  },
+
   data: () => ({
     loading: false
   }),
 
-  computed: {
-    ...mapGetters({
-      isImpersonating: 'auth/isImpersonating'
-    })
-  },
+  computed: {},
 
-  mounted () {
-  },
+  mounted () {},
 
   methods: {
     reverseImpersonation () {
       this.loading = true
-      this.$store.dispatch('auth/stopImpersonating')
-        .then(() => {
-          this.$store.commit('open/workspaces/set', [])
+      this.authStore.stopImpersonating().then(() => {
+          this.workspacesStore.set([])
           this.$router.push({ name: 'settings.admin' })
           this.loading = false
         })
diff --git a/resources/js/components/pages/forms/NewFeatures.vue b/resources/js/components/pages/forms/NewFeatures.vue
index 8af3a8923..13408145e 100644
--- a/resources/js/components/pages/forms/NewFeatures.vue
+++ b/resources/js/components/pages/forms/NewFeatures.vue
@@ -62,14 +62,22 @@
 </template>
 
 <script>
+import { computed } from 'vue'
 import axios from 'axios'
-import { mapGetters } from 'vuex'
+import { useAuthStore } from '../../../stores/auth';
 import VTransition from '../../common/transitions/VTransition.vue'
 
 export default {
   components: { VTransition },
   props: {},
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      user : computed(() => authStore.user)
+    }
+  },
+
   data: () => ({
     changelogEntries: [],
     showNewFeatures: false
@@ -80,9 +88,6 @@ export default {
   },
 
   computed: {
-    ...mapGetters({
-      user: 'auth/user'
-    }),
     requestFeatureLink () {
       return window.config.links.feature_requests
     },
diff --git a/resources/js/components/pages/forms/show/ExtraMenu.vue b/resources/js/components/pages/forms/show/ExtraMenu.vue
index d59a55a4e..703ad77ce 100644
--- a/resources/js/components/pages/forms/show/ExtraMenu.vue
+++ b/resources/js/components/pages/forms/show/ExtraMenu.vue
@@ -122,8 +122,10 @@
 </template>
 
 <script>
+import { computed } from 'vue'
 import axios from 'axios'
-import {mapGetters, mapState} from 'vuex'
+import { useAuthStore } from '../../../../stores/auth'
+import { useFormsStore } from '../../../../stores/forms'
 import Dropdown from '../../../common/Dropdown.vue'
 import FormTemplateModal from '../../../open/forms/components/templates/FormTemplateModal.vue'
 
@@ -135,6 +137,15 @@ export default {
       isMainPage: { type: Boolean, required: false, default: false }
     },
 
+    setup () {
+      const authStore = useAuthStore()
+      const formsStore = useFormsStore()
+      return {
+        formsStore,
+        user : computed(() => authStore.user)
+      }
+    },
+
     data: () => ({
       loadingDuplicate: false,
       loadingDelete: false,
@@ -143,9 +154,6 @@ export default {
     }),
 
     computed: {
-      ...mapGetters({
-        user: 'auth/user'
-      }),
       formEndpoint: () => '/api/open/forms/{id}',
     },
 
@@ -163,7 +171,7 @@ export default {
         if (this.loadingDuplicate) return
         this.loadingDuplicate = true
         axios.post(this.formEndpoint.replace('{id}', this.form.id) + '/duplicate').then((response) => {
-          this.$store.commit('open/forms/addOrUpdate', response.data.new_form)
+          this.formsStore.addOrUpdate(response.data.new_form)
           this.$router.push({name: 'forms.show', params: {slug: response.data.new_form.slug}})
           this.alertSuccess('Form was successfully duplicated.')
           this.loadingDuplicate = false
@@ -173,7 +181,7 @@ export default {
         if (this.loadingDelete) return
         this.loadingDelete = true
         axios.delete(this.formEndpoint.replace('{id}', this.form.id)).then(() => {
-          this.$store.commit('open/forms/remove', this.form)
+          this.formsStore.remove(this.form)
           this.$router.push({name: 'home'})
           this.alertSuccess('Form was deleted.')
           this.loadingDelete = false
diff --git a/resources/js/components/pages/forms/show/RegenerateFormLink.vue b/resources/js/components/pages/forms/show/RegenerateFormLink.vue
index d967a6ac6..3d35ef1ed 100644
--- a/resources/js/components/pages/forms/show/RegenerateFormLink.vue
+++ b/resources/js/components/pages/forms/show/RegenerateFormLink.vue
@@ -72,7 +72,9 @@
 </template>
 
 <script>
+import { computed } from 'vue'
 import axios from 'axios'
+import { useFormsStore } from '../../../../stores/forms'
 
 export default {
   name: 'RegenerateFormLink',
@@ -81,6 +83,13 @@ export default {
     form: { type: Object, required: true }
   },
 
+  setup () {
+      const formsStore = useFormsStore()
+      return {
+        formsStore
+      }
+    },
+
   data: () => ({
     loadingNewLink: false,
     showGenerateFormLinkModal: false,
@@ -95,7 +104,7 @@ export default {
       if (this.loadingNewLink) return
       this.loadingNewLink = true
       axios.put(this.formEndpoint.replace('{id}', this.form.id) + '/regenerate-link/' + option).then((response) => {
-        this.$store.commit('open/forms/addOrUpdate', response.data.form)
+        this.formsStore.addOrUpdate(response.data.form)
         this.$router.push({name: 'forms.show', params: {slug: response.data.form.slug}})
         this.alertSuccess(response.data.message)
         this.loadingNewLink = false
diff --git a/resources/js/components/pages/pricing/CheckoutDetailsModal.vue b/resources/js/components/pages/pricing/CheckoutDetailsModal.vue
index 251bccba5..ed5341a64 100644
--- a/resources/js/components/pages/pricing/CheckoutDetailsModal.vue
+++ b/resources/js/components/pages/pricing/CheckoutDetailsModal.vue
@@ -11,14 +11,14 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
-import TextInput from '../../forms/TextInput.vue'
+import { computed } from 'vue'
+import axios from 'axios'
 import Form from 'vform'
+import { useAuthStore } from '../../../stores/auth'
+import TextInput from '../../forms/TextInput.vue'
 import VButton from '../../common/Button.vue'
-import axios from 'axios'
 
 export default {
-
   components: { VButton, TextInput },
   props: {
     show: {
@@ -34,6 +34,14 @@ export default {
       default: true
     }
   },
+
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      user : computed(() => authStore.user)
+    }
+  },
+
   data: () => ({
     form: new Form({
       name: '',
@@ -88,10 +96,6 @@ export default {
     }
   },
 
-  computed: {
-    ...mapGetters({
-      user: 'auth/user'
-    })
-  }
+  computed: {}
 }
 </script>
diff --git a/resources/js/components/pages/pricing/PricingTable.vue b/resources/js/components/pages/pricing/PricingTable.vue
index 599eb12ca..13b3bb201 100644
--- a/resources/js/components/pages/pricing/PricingTable.vue
+++ b/resources/js/components/pages/pricing/PricingTable.vue
@@ -107,7 +107,8 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../../stores/auth'
 import axios from 'axios'
 import MonthlyYearlySelector from './MonthlyYearlySelector.vue'
 import CheckoutDetailsModal from './CheckoutDetailsModal.vue'
@@ -127,6 +128,13 @@ export default {
       default: false
     }
   },
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authenticated : computed(() => authStore.check),
+      user : computed(() => authStore.user)
+    }
+  },
   data: () => ({
     isYearly: true,
     selectedPlan: 'pro',
@@ -160,11 +168,6 @@ export default {
     }
   },
 
-  computed: {
-    ...mapGetters({
-      authenticated: 'auth/check',
-      user: 'auth/user'
-    })
-  }
+  computed: {}
 }
 </script>
diff --git a/resources/js/components/pages/templates/SingleTemplate.vue b/resources/js/components/pages/templates/SingleTemplate.vue
index e1938ebd3..cd8208df6 100644
--- a/resources/js/components/pages/templates/SingleTemplate.vue
+++ b/resources/js/components/pages/templates/SingleTemplate.vue
@@ -39,7 +39,8 @@
 </template>
 
 <script>
-import store from '~/store'
+import { computed } from 'vue'
+import { useTemplatesStore } from '../../../stores/templates'
 import TemplateTags from './TemplateTags.vue'
 
 export default {
@@ -52,22 +53,29 @@ export default {
     }
   },
 
+  setup () {
+    const templatesStore = useTemplatesStore()
+    return {
+      templatesStore
+    }
+  },
+
   data: () => ({}),
 
   computed: {
     template () {
-      return this.$store.getters['open/templates/getBySlug'](this.slug)
+      return this.templatesStore.getBySlug(this.slug)
     }
   },
 
   watch: {
     slug () {
-      store.dispatch('open/templates/loadTemplate', this.slug)
+      this.templatesStore.loadTemplate(this.slug)
     }
   },
 
   mounted () {
-    store.dispatch('open/templates/loadTemplate', this.slug)
+    this.templatesStore.loadTemplate(this.slug)
   },
 
   methods: {
diff --git a/resources/js/components/pages/templates/TemplateTags.vue b/resources/js/components/pages/templates/TemplateTags.vue
index deac70898..b84cf7b1a 100644
--- a/resources/js/components/pages/templates/TemplateTags.vue
+++ b/resources/js/components/pages/templates/TemplateTags.vue
@@ -41,6 +41,9 @@
 </template>
 
 <script>
+import { computed } from 'vue'
+import { useTemplatesStore } from '../../../stores/templates'
+
 export default {
   props: {
     slug: {
@@ -53,19 +56,26 @@ export default {
     }
   },
 
+  setup () {
+    const templatesStore = useTemplatesStore()
+    return {
+      templatesStore
+    }
+  },
+
   data: () => ({}),
 
   computed: {
     template () {
-      return this.$store.getters['open/templates/getBySlug'](this.slug)
+      return this.templatesStore.getBySlug(this.slug)
     },
     types () {
       if (!this.template) return null
-      return this.$store.getters['open/templates/getTemplateTypes'](this.template.types)
+      return this.templatesStore.getTemplateTypes(this.template.types)
     },
     industries () {
       if (!this.template) return null
-      return this.$store.getters['open/templates/getTemplateIndustries'](this.template.industries)
+      return this.templatesStore.getTemplateIndustries(this.template.industries)
     }
   },
 
diff --git a/resources/js/components/pages/templates/TemplatesList.vue b/resources/js/components/pages/templates/TemplatesList.vue
index 5b34ec306..5a2468f74 100644
--- a/resources/js/components/pages/templates/TemplatesList.vue
+++ b/resources/js/components/pages/templates/TemplatesList.vue
@@ -79,24 +79,25 @@
 </template>
 
 <script>
-import store from '~/store'
-import { mapGetters, mapState } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../../stores/auth'
+import { useTemplatesStore } from '../../../stores/templates'
 import Form from 'vform'
 import Fuse from 'fuse.js'
 import SingleTemplate from './SingleTemplate.vue'
 
 const loadTemplates = function (onlyMy) {
+  const templatesStore = useTemplatesStore()
   if(onlyMy){
-    store.dispatch('open/templates/loadAll', {'onlymy':true})
+    templatesStore.loadAll({'onlymy':true})
   } else {
-    store.dispatch('open/templates/loadIfEmpty')
+    templatesStore.loadIfEmpty()
   }
 }
 
 export default {
   name: 'TemplatesList',
   components: { SingleTemplate },
-
   props: {
     onlyMy: {
       type: Boolean,
@@ -104,6 +105,18 @@ export default {
     }
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    const templatesStore = useTemplatesStore()
+    return {
+      user : computed(() => authStore.user),
+      templates : computed(() => templatesStore.content),
+      templatesLoading : computed(() => templatesStore.loading),
+      industries : computed(() => templatesStore.industries),
+      types : computed(() => templatesStore.types)
+    }
+  },
+
   data: () => ({
     selectedType: 'all',
     selectedIndustry: 'all',
@@ -119,15 +132,6 @@ export default {
   },
 
   computed: {
-    ...mapState({
-      templates: state => state['open/templates'].content,
-      templatesLoading: state => state['open/templates'].loading,
-      industries: state => state['open/templates'].industries,
-      types: state => state['open/templates'].types
-    }),
-    ...mapGetters({
-      user: 'auth/user'
-    }),
     industriesOptions () {
       return [{ name: 'All Industries', value: 'all' }].concat(Object.values(this.industries).map((industry) => {
         return {
diff --git a/resources/js/components/pages/welcome/AiFeature.vue b/resources/js/components/pages/welcome/AiFeature.vue
index c24fdad14..ca599490a 100644
--- a/resources/js/components/pages/welcome/AiFeature.vue
+++ b/resources/js/components/pages/welcome/AiFeature.vue
@@ -87,16 +87,19 @@
 </template>
 
 <script>
-import {mapGetters} from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../../stores/auth'
 
 export default {
-    props: {},
-    data: () => ({}),
-    computed: {
-      ...mapGetters({
-        authenticated: 'auth/check'
-      }),
-    },
-    methods: {}
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authenticated : computed(() => authStore.check)
+    }
+  },
+  props: {},
+  data: () => ({}),
+  computed: {},
+  methods: {}
 }
 </script>
diff --git a/resources/js/components/pages/welcome/TemplatesSlider.vue b/resources/js/components/pages/welcome/TemplatesSlider.vue
index d3f0b2e0f..eb6725ecf 100644
--- a/resources/js/components/pages/welcome/TemplatesSlider.vue
+++ b/resources/js/components/pages/welcome/TemplatesSlider.vue
@@ -36,19 +36,23 @@
 </template>
 
 <script>
-import store from '~/store'
-import { mapGetters, mapState } from 'vuex'
+import { computed } from 'vue'
+import { useTemplatesStore } from '../../../stores/templates'
 import SingleTemplate from '../templates/SingleTemplate.vue'
 
 export default {
   components: { SingleTemplate },
   props: { },
+  setup () {
+    const templatesStore = useTemplatesStore()
+    return {
+      templatesStore,
+      templates : computed(() => templatesStore.content)
+    }
+  },
   data: () => ({}),
 
   computed: {
-    ...mapState({
-      templates: state => state['open/templates'].content
-    }),
     sliderTemplates () {
       return this.templates.slice(0, 20)
     }
@@ -66,7 +70,7 @@ export default {
   },
 
   mounted() {
-    store.dispatch('open/templates/loadAll', { limit: 20 })
+    this.templatesStore.loadAll({ limit: 20 })
   },
 
   methods: {
diff --git a/resources/js/components/service/Amplitude.vue b/resources/js/components/service/Amplitude.vue
index 30c3b7c1a..12afcbedf 100644
--- a/resources/js/components/service/Amplitude.vue
+++ b/resources/js/components/service/Amplitude.vue
@@ -1,12 +1,21 @@
 <template />
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
 
 export default {
-
   name: 'Amplitude',
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authStore,
+      authenticated : computed(() => authStore.check),
+      user : computed(() => authStore.user)
+    }
+  },
+
   data: function () {
     return {
       loaded: false,
@@ -14,12 +23,7 @@ export default {
     }
   },
 
-  computed: {
-    ...mapGetters({
-      authenticated: 'auth/check',
-      user: 'auth/user'
-    })
-  },
+  computed: {},
 
   watch: {
     $route () {
diff --git a/resources/js/components/service/Hotjar.vue b/resources/js/components/service/Hotjar.vue
index 66e54ab49..3c782bc31 100644
--- a/resources/js/components/service/Hotjar.vue
+++ b/resources/js/components/service/Hotjar.vue
@@ -1,12 +1,19 @@
 <template />
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
 
 export default {
-
   name: 'Hotjar',
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authenticated : computed(() => authStore.check),
+    }
+  },
+
   watch: {
     authenticated () {
       if (this.authenticated) {
@@ -38,9 +45,6 @@ export default {
   },
 
   computed: {
-    ...mapGetters({
-      authenticated: 'auth/check'
-    }),
     isIframe () {
       return window.location !== window.parent.location || window.frameElement
     }
diff --git a/resources/js/components/vendor/appsumo/AppSumoBilling.vue b/resources/js/components/vendor/appsumo/AppSumoBilling.vue
index 5dcffbd71..24c1aac2a 100644
--- a/resources/js/components/vendor/appsumo/AppSumoBilling.vue
+++ b/resources/js/components/vendor/appsumo/AppSumoBilling.vue
@@ -21,23 +21,27 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../../stores/auth'
 import VButton from '../../common/Button.vue'
 
 export default {
-
   name: 'AppSumoBilling',
   components: { VButton },
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      user : computed(() => authStore.user),
+    }
+  },
+
   data () {
     return {
     }
   },
 
   computed: {
-    ...mapGetters({
-      user: 'auth/user'
-    }),
     licenseTier () {
       return this.user?.active_license?.meta?.tier
     },
@@ -67,10 +71,9 @@ export default {
 
   mounted () {},
 
-  created () {
-  },
-  destroyed () {
-  },
+  created () {},
+
+  destroyed () {},
 
   methods: {}
 }
diff --git a/resources/js/middleware/admin.js b/resources/js/middleware/admin.js
index 52145a6b9..097608027 100644
--- a/resources/js/middleware/admin.js
+++ b/resources/js/middleware/admin.js
@@ -1,7 +1,8 @@
-import store from '~/store'
+import { useAuthStore } from '../stores/auth';
 
 export default (to, from, next) => {
-  if (!store.getters['auth/user'].admin) {
+  const authStore = useAuthStore()
+  if (!authStore.user?.admin) {
     next({ name: 'home' })
   } else {
     next()
diff --git a/resources/js/middleware/auth.js b/resources/js/middleware/auth.js
index 2bc1d7a30..d634d772e 100644
--- a/resources/js/middleware/auth.js
+++ b/resources/js/middleware/auth.js
@@ -1,8 +1,9 @@
-import store from '~/store'
+import { useAuthStore } from '../stores/auth';
 import Cookies from 'js-cookie'
 
 export default async (to, from, next) => {
-  if (!store.getters['auth/check']) {
+  const authStore = useAuthStore()
+  if (!authStore.check) {
     Cookies.set('intended_url', to.path)
 
     next({ name: 'login' })
diff --git a/resources/js/middleware/check-auth.js b/resources/js/middleware/check-auth.js
index 8f6b10947..954a55d6d 100644
--- a/resources/js/middleware/check-auth.js
+++ b/resources/js/middleware/check-auth.js
@@ -1,4 +1,4 @@
-import store from '~/store'
+import { useAuthStore } from '../stores/auth';
 import * as Sentry from '@sentry/vue'
 
 export function initCrisp (user) {
@@ -36,12 +36,13 @@ export function initSentry (user) {
 }
 
 export default async (to, from, next) => {
-  if (!store.getters['auth/check'] &&
-    store.getters['auth/token'] !== null &&
-    store.getters['auth/token'] !== undefined
+  const authStore = useAuthStore()
+  if (!authStore.check &&
+    authStore.token !== null &&
+    authStore.token !== undefined
   ) {
     try {
-      store.dispatch('auth/fetchUser').then((user) => {
+      authStore.fetchUser().then((user) => {
         initCrisp(user)
         initSentry(user)
       })
diff --git a/resources/js/middleware/guest.js b/resources/js/middleware/guest.js
index dc45d6880..c6c78a7e4 100644
--- a/resources/js/middleware/guest.js
+++ b/resources/js/middleware/guest.js
@@ -1,7 +1,8 @@
-import store from '~/store'
+import { useAuthStore } from '../stores/auth';
 
 export default (to, from, next) => {
-  if (store.getters['auth/check']) {
+  const authStore = useAuthStore()
+  if (authStore.check) {
     next({ name: 'home' })
   } else {
     next()
diff --git a/resources/js/middleware/notion-connection.js b/resources/js/middleware/notion-connection.js
index 1054cdcad..4a0d1792d 100644
--- a/resources/js/middleware/notion-connection.js
+++ b/resources/js/middleware/notion-connection.js
@@ -1,7 +1,8 @@
-import store from '~/store'
+import { useAuthStore } from '../stores/auth';
 
 export default async (to, from, next) => {
-  if (store.getters['auth/check'] && store.getters['auth/user'].workspaces_count === 0) {
+  const authStore = useAuthStore()
+  if (authStore.check && authStore.user?.workspaces_count === 0) {
     if ([
       'forms.create',
       'forms.show',
diff --git a/resources/js/middleware/role.js b/resources/js/middleware/role.js
index c63a6cedb..a4f935282 100644
--- a/resources/js/middleware/role.js
+++ b/resources/js/middleware/role.js
@@ -1,4 +1,4 @@
-import store from '~/store'
+import { useAuthStore } from '../stores/auth';
 
 /**
  * This is middleware to check the current user role.
@@ -7,14 +7,13 @@ import store from '~/store'
  */
 
 export default (to, from, next, roles) => {
-  // Grab the user
-  const user = store.getters['auth/user']
-
+  const authStore = useAuthStore()
+  
   // Split roles into an array
   roles = roles.split(',')
 
   // Check if the user has one of the required roles...
-  if (!roles.includes(user.role)) {
+  if (!roles.includes(authStore.user?.role)) {
     next('/unauthorized')
   }
 
diff --git a/resources/js/middleware/subscribed.js b/resources/js/middleware/subscribed.js
index b8b4ba588..6b2f866e3 100644
--- a/resources/js/middleware/subscribed.js
+++ b/resources/js/middleware/subscribed.js
@@ -1,7 +1,8 @@
-import store from '~/store'
+import { useAuthStore } from '../stores/auth';
 
 export default (to, from, next) => {
-  if (!store.getters['auth/user'].is_subscribed) {
+  const authStore = useAuthStore()
+  if (!authStore.user?.is_subscribed) {
     next({ name: 'pricing' })
   } else {
     next()
diff --git a/resources/js/pages/ai-form-builder.vue b/resources/js/pages/ai-form-builder.vue
index 304019441..e2d08a6c2 100644
--- a/resources/js/pages/ai-form-builder.vue
+++ b/resources/js/pages/ai-form-builder.vue
@@ -476,7 +476,8 @@
 </template>
 
 <script>
-import {mapGetters} from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../stores/auth'
 import OpenFormFooter from '../components/pages/OpenFormFooter.vue'
 import SeoMeta from '../mixins/seo-meta.js'
 
@@ -484,6 +485,14 @@ export default {
   components: {OpenFormFooter},
   layout: 'default',
   mixins: [SeoMeta],
+
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authenticated : computed(() => authStore.check),
+    }
+  },
+
   data: () => ({
     title: window.config.appName,
     metaTitle: 'AI form builder for free',
@@ -494,9 +503,6 @@ export default {
   methods: {},
 
   computed: {
-    ...mapGetters({
-      authenticated: 'auth/check'
-    }),
     configLinks: () => window.config.links
   }
 }
diff --git a/resources/js/pages/auth/components/LoginForm.vue b/resources/js/pages/auth/components/LoginForm.vue
index 9760fb448..63c008fc9 100644
--- a/resources/js/pages/auth/components/LoginForm.vue
+++ b/resources/js/pages/auth/components/LoginForm.vue
@@ -41,8 +41,10 @@
 </template>
 
 <script>
+import { computed } from 'vue'
 import Form from 'vform'
 import Cookies from 'js-cookie'
+import { useAuthStore } from '../../../stores/auth'
 import OpenFormFooter from '../../../components/pages/OpenFormFooter.vue'
 import Testimonials from '../../../components/pages/welcome/Testimonials.vue'
 import ForgotPasswordModal from '../ForgotPasswordModal.vue'
@@ -62,6 +64,13 @@ export default {
     }
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authStore
+    }
+  },
+
   data: () => ({
     form: new Form({
       email: '',
@@ -77,13 +86,10 @@ export default {
       const { data } = await this.form.post('/api/login')
 
       // Save the token.
-      this.$store.dispatch('auth/saveToken', {
-        token: data.token,
-        remember: this.remember
-      })
+      this.authStore.saveToken(data.token, this.remember)
 
       // Fetch the user.
-      await this.$store.dispatch('auth/fetchUser')
+      await this.authStore.fetchUser()
 
       // Redirect home.
       this.redirect()
diff --git a/resources/js/pages/auth/components/RegisterForm.vue b/resources/js/pages/auth/components/RegisterForm.vue
index d76048336..9eaab50d5 100644
--- a/resources/js/pages/auth/components/RegisterForm.vue
+++ b/resources/js/pages/auth/components/RegisterForm.vue
@@ -48,7 +48,9 @@
 </template>
 
 <script>
+import { computed } from 'vue'
 import Form from 'vform'
+import { useAuthStore } from '../../../stores/auth'
 import { initCrisp } from '../../../middleware/check-auth.js'
 
 export default {
@@ -62,6 +64,13 @@ export default {
     }
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authStore
+    }
+  },
+
   data: () => ({
     form: new Form({
       name: '',
@@ -112,10 +121,10 @@ export default {
         const { data: { token } } = await this.form.post('/api/login')
 
         // Save the token.
-        this.$store.dispatch('auth/saveToken', { token })
+        this.authStore.saveToken(token)
 
         // Update the user.
-        await this.$store.dispatch('auth/updateUser', { user: data })
+        await this.authStore.updateUser(data)
 
         // Track event
         this.$logEvent('register', { source: this.form.hear_about_us })
diff --git a/resources/js/pages/forms/create-guest.vue b/resources/js/pages/forms/create-guest.vue
index 35bc20057..c7fa539de 100644
--- a/resources/js/pages/forms/create-guest.vue
+++ b/resources/js/pages/forms/create-guest.vue
@@ -24,18 +24,21 @@
 </template>
 
 <script>
-import store from '~/store'
+import { computed } from 'vue'
 import Form from 'vform'
-import { mapState, mapActions } from 'vuex'
+import { useTemplatesStore } from '../../stores/templates'
+import { useWorkingFormStore } from '../../stores/working_form'
+import { useWorkspacesStore } from '../../stores/workspaces'
 import QuickRegister from '../auth/components/QuickRegister.vue'
 import initForm from '../../mixins/form_editor/initForm.js'
 import SeoMeta from '../../mixins/seo-meta.js'
 import CreateFormBaseModal from '../../components/pages/forms/create/CreateFormBaseModal.vue'
 
 const loadTemplates = function () {
-  store.commit('open/templates/startLoading')
-  store.dispatch('open/templates/loadIfEmpty').then(() => {
-    store.commit('open/templates/stopLoading')
+  const templatesStore = useTemplatesStore()
+  templatesStore.startLoading()
+  templatesStore.loadIfEmpty().then(() => {
+    templatesStore.stopLoading()
   })
 }
 
@@ -45,13 +48,25 @@ export default {
     QuickRegister, CreateFormBaseModal
   },
   mixins: [initForm, SeoMeta],
+  middleware: 'guest',
 
   beforeRouteEnter (to, from, next) {
     loadTemplates()
     next()
   },
 
-  middleware: 'guest',
+  setup () {
+    const templatesStore = useTemplatesStore()
+    const workingFormStore = useWorkingFormStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      templatesStore,
+      workingFormStore,
+      workspacesStore,
+      workspaces : computed(() => workspacesStore.content),
+      workspacesLoading : computed(() => workspacesStore.loading)
+    }
+  },
 
   data () {
     return {
@@ -66,21 +81,17 @@ export default {
   },
 
   computed: {
-    ...mapState({
-      workspaces: state => state['open/workspaces'].content,
-      workspacesLoading: state => state['open/workspaces'].loading
-    }),
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     workspace () {
-      return this.$store.getters['open/workspaces/getCurrent']()
+      return this.workspacesStore.getCurrent()
     }
   },
 
@@ -100,12 +111,12 @@ export default {
       is_enterprise: false,
       is_pro: false
     }
-    this.$store.commit('open/workspaces/set', [guestWorkspace])
-    this.$store.commit('open/workspaces/setCurrentId', guestWorkspace.id)
+    this.workspacesStore.set([guestWorkspace])
+    this.workspacesStore.setCurrentId(guestWorkspace.id)
 
     this.initForm()
     if (this.$route.query.template !== undefined && this.$route.query.template) {
-      const template = this.$store.getters['open/templates/getBySlug'](this.$route.query.template)
+      const template = this.templatesStore.getBySlug(this.$route.query.template)
       if (template && template.structure) {
         this.form = new Form({ ...this.form.data(), ...template.structure })
       }
@@ -121,16 +132,13 @@ export default {
   unmounted () {},
 
   methods: {
-    ...mapActions({
-      loadWorkspaces: 'open/workspaces/load'
-    }),
     openRegister () {
       this.registerModal = true
     },
     afterLogin () {
       this.registerModal = false
       this.isGuest = false
-      this.loadWorkspaces()
+      this.workspacesStore.load()
       setTimeout(() => {
         if (this.$refs.editor) {
           this.$refs.editor.saveFormCreate()
diff --git a/resources/js/pages/forms/create.vue b/resources/js/pages/forms/create.vue
index 1490b38fd..07510d9d6 100644
--- a/resources/js/pages/forms/create.vue
+++ b/resources/js/pages/forms/create.vue
@@ -19,17 +19,21 @@
 </template>
 
 <script>
-import store from '~/store'
 import Form from 'vform'
-import { mapState, mapActions } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
+import { useTemplatesStore } from '../../stores/templates'
+import { useWorkingFormStore } from '../../stores/working_form'
+import { useWorkspacesStore } from '../../stores/workspaces'
 import initForm from '../../mixins/form_editor/initForm.js'
 import SeoMeta from '../../mixins/seo-meta.js'
 import CreateFormBaseModal from '../../components/pages/forms/create/CreateFormBaseModal.vue'
 
 const loadTemplates = function () {
-  store.commit('open/templates/startLoading')
-  store.dispatch('open/templates/loadIfEmpty').then(() => {
-    store.commit('open/templates/stopLoading')
+  const templatesStore = useTemplatesStore()
+  templatesStore.startLoading()
+  templatesStore.loadIfEmpty().then(() => {
+    templatesStore.stopLoading()
   })
 }
 
@@ -38,6 +42,7 @@ export default {
   components: { CreateFormBaseModal },
 
   mixins: [initForm, SeoMeta],
+  middleware: 'auth',
 
   beforeRouteEnter (to, from, next) {
     loadTemplates()
@@ -54,7 +59,20 @@ export default {
     next()
   },
 
-  middleware: 'auth',
+  setup () {
+    const authStore = useAuthStore()
+    const templatesStore = useTemplatesStore()
+    const workingFormStore = useWorkingFormStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      templatesStore,
+      workingFormStore,
+      workspacesStore,
+      user: computed(() => authStore.user),
+      workspaces : computed(() => workspacesStore.content),
+      workspacesLoading : computed(() => workspacesStore.loading)
+    }
+  },
 
   data () {
     return {
@@ -68,22 +86,17 @@ export default {
   },
 
   computed: {
-    ...mapState({
-      workspaces: state => state['open/workspaces'].content,
-      workspacesLoading: state => state['open/workspaces'].loading,
-      user: state => state.auth.user
-    }),
     form: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     workspace () {
-      return this.$store.getters['open/workspaces/getCurrent']()
+      return this.workspacesStore.getCurrent()
     }
   },
 
@@ -108,7 +121,7 @@ export default {
     this.initForm()
     this.formInitialHash = this.hashString(JSON.stringify(this.form.data()))
     if (this.$route.query.template !== undefined && this.$route.query.template) {
-      const template = this.$store.getters['open/templates/getBySlug'](this.$route.query.template)
+      const template = this.templatesStore.getBySlug(this.$route.query.template)
       if (template && template.structure) {
         this.form = new Form({ ...this.form.data(), ...template.structure })
       }
@@ -117,7 +130,7 @@ export default {
       this.showInitialFormModal = true
     }
     this.closeAlert()
-    this.loadWorkspaces()
+    this.workspacesStore.loadIfEmpty()
 
     this.stateReady = this.user !== null
   },
@@ -126,9 +139,6 @@ export default {
   unmounted () {},
 
   methods: {
-    ...mapActions({
-      loadWorkspaces: 'open/workspaces/loadIfEmpty'
-    }),
     formGenerated (form) {
       this.form = new Form({ ...this.form.data(), ...form })
     },
diff --git a/resources/js/pages/forms/edit.vue b/resources/js/pages/forms/edit.vue
index 6e8cb61a2..a55d5589e 100644
--- a/resources/js/pages/forms/edit.vue
+++ b/resources/js/pages/forms/edit.vue
@@ -14,17 +14,20 @@
 </template>
 
 <script>
-import axios from 'axios'
-import store from '~/store'
-import Breadcrumb from '../../components/common/Breadcrumb.vue'
+import { computed } from 'vue'
 import Form from 'vform'
-import { mapState } from 'vuex'
+import { useFormsStore } from '../../stores/forms'
+import { useWorkingFormStore } from '../../stores/working_form'
+import { useWorkspacesStore } from '../../stores/workspaces'
+import Breadcrumb from '../../components/common/Breadcrumb.vue'
 import SeoMeta from '../../mixins/seo-meta.js'
 
 const loadForms = function () {
-  store.commit('open/forms/startLoading')
-  store.dispatch('open/workspaces/loadIfEmpty').then(() => {
-    store.dispatch('open/forms/load', store.state['open/workspaces'].currentId)
+  const formsStore = useFormsStore()
+  const workspacesStore = useWorkspacesStore()
+  formsStore.startLoading()
+  workspacesStore.loadIfEmpty().then(() => {
+    formsStore.load(workspacesStore.currentId)
   })
 }
 
@@ -32,12 +35,15 @@ export default {
   name: 'EditForm',
   components: { Breadcrumb },
   mixins: [SeoMeta],
+  middleware: 'auth',
 
   beforeRouteEnter (to, from, next) {
-    if (!store.getters['open/forms/getBySlug'](to.params.slug)) {
+    const formsStore = useFormsStore()
+    const workingFormStore = useWorkingFormStore()
+    if (!formsStore.getBySlug(to.params.slug)) {
       loadForms()
     }
-    store.commit('open/working_form/set', null) // Reset old working form
+    workingFormStore.set(null)  // Reset old working form
     next()
   },
 
@@ -51,7 +57,17 @@ export default {
     next()
   },
 
-  middleware: 'auth',
+  setup () {
+    const formsStore = useFormsStore()
+    const workingFormStore = useWorkingFormStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      formsStore,
+      workingFormStore,
+      workspacesStore,
+      formsLoading : computed(() => formsStore.loading)
+    }
+  },
 
   data () {
     return {
@@ -62,20 +78,17 @@ export default {
   },
 
   computed: {
-    ...mapState({
-      formsLoading: state => state['open/forms'].loading
-    }),
     updatedForm: {
       get () {
-        return this.$store.state['open/working_form'].content
+        return this.workingFormStore.content
       },
       /* We add a setter */
       set (value) {
-        this.$store.commit('open/working_form/set', value)
+        this.workingFormStore.set(value)
       }
     },
     form () {
-      return this.$store.getters['open/forms/getBySlug'](this.$route.params.slug)
+      return this.formsStore.getBySlug(this.$route.params.slug)
     },
     pageLoaded () {
       return !this.loading && this.updatedForm !== null
diff --git a/resources/js/pages/forms/show-public.vue b/resources/js/pages/forms/show-public.vue
index 176c5c4f2..154fcb461 100644
--- a/resources/js/pages/forms/show-public.vue
+++ b/resources/js/pages/forms/show-public.vue
@@ -50,8 +50,9 @@
 
 <script>
 import axios from 'axios'
-import store from '~/store'
-import { mapState } from 'vuex'
+import { computed } from 'vue'
+import { useFormsStore } from '../../stores/forms'
+import { useRecordsStore } from '../../stores/records'
 import OpenCompleteForm from '../../components/open/forms/OpenCompleteForm.vue'
 import Cookies from 'js-cookie'
 import sha256 from 'js-sha256'
@@ -93,11 +94,12 @@ function handleTransparentMode (form) {
 }
 
 function loadForm (slug) {
-  if (store.state['open/forms'].loading) return
-  store.commit('open/forms/startLoading')
+  const formsStore = useFormsStore()
+  if (formsStore.loading) return
+  formsStore.startLoading()
   return axios.get('/api/forms/' + slug).then((response) => {
     const form = response.data
-    store.commit('open/forms/set', [response.data])
+    formsStore.set([response.data])
 
     // Custom code injection
     if (form.custom_code) {
@@ -108,9 +110,9 @@ function loadForm (slug) {
     handleDarkMode(form)
     handleTransparentMode(form)
 
-    store.commit('open/forms/stopLoading')
+    formsStore.stopLoading()
   }).catch(() => {
-    store.commit('open/forms/stopLoading')
+    formsStore.stopLoading()
   })
 }
 
@@ -132,6 +134,17 @@ export default {
     next()
   },
 
+  setup () {
+    const formsStore = useFormsStore()
+    const recordsStore = useRecordsStore()
+    return {
+      formsStore,
+      forms : computed(() => formsStore.content),
+      formLoading : computed(() => formsStore.loading),
+      recordLoading : computed(() => recordsStore.loading)
+    }
+  },
+
   data () {
     return {
       submitted: false
@@ -166,16 +179,11 @@ export default {
   },
 
   computed: {
-    ...mapState({
-      forms: state => state['open/forms'].content,
-      formLoading: state => state['open/forms'].loading,
-      recordLoading: state => state['open/records'].loading
-    }),
     formSlug () {
       return this.$route.params.slug
     },
     form () {
-      return this.$store.getters['open/forms/getBySlug'](this.formSlug)
+      return this.formsStore.getBySlug(this.formSlug)
     },
     isIframe () {
       return window.location !== window.parent.location || window.frameElement
diff --git a/resources/js/pages/forms/show/index.vue b/resources/js/pages/forms/show/index.vue
index 095eb5301..48539af87 100644
--- a/resources/js/pages/forms/show/index.vue
+++ b/resources/js/pages/forms/show/index.vue
@@ -116,10 +116,12 @@
 </template>
 
 <script>
-import axios from 'axios'
-import store from '~/store'
+import { computed } from 'vue'
 import Form from 'vform'
-import {mapGetters, mapState} from 'vuex'
+import { useAuthStore } from '../../../stores/auth'
+import { useFormsStore } from '../../../stores/forms'
+import { useWorkingFormStore } from '../../../stores/working_form'
+import { useWorkspacesStore } from '../../../stores/workspaces'
 import ProTag from '../../../components/common/ProTag.vue'
 import VButton from "../../../components/common/Button.vue";
 import ExtraMenu from '../../../components/pages/forms/show/ExtraMenu.vue'
@@ -127,9 +129,11 @@ import SeoMeta from '../../../mixins/seo-meta.js'
 import FormCleanings from '../../../components/pages/forms/show/FormCleanings.vue'
 
 const loadForms = function () {
-  store.commit('open/forms/startLoading')
-  store.dispatch('open/workspaces/loadIfEmpty').then(() => {
-    store.dispatch('open/forms/loadIfEmpty', store.state['open/workspaces'].currentId)
+  const formsStore = useFormsStore()
+  const workspacesStore = useWorkspacesStore()
+  formsStore.startLoading()
+  workspacesStore.loadIfEmpty().then(() => {
+    formsStore.loadIfEmpty(workspacesStore.currentId)
   })
 }
 
@@ -154,6 +158,21 @@ export default {
   },
   middleware: 'auth',
 
+  setup () {
+    const authStore = useAuthStore()
+    const formsStore = useFormsStore()
+    const workingFormStore = useWorkingFormStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      formsStore,
+      workingFormStore,
+      workspacesStore,
+      user : computed(() => authStore.user),
+      formsLoading : computed(() => formsStore.loading),
+      workspacesLoading : computed(() => workspacesStore.loading)
+    }
+  },
+
   data() {
     return {
       metaTitle: 'Home',
@@ -175,27 +194,21 @@ export default {
   },
 
   computed: {
-    ...mapGetters({
-      user: 'auth/user'
-    }),
-    ...mapState({
-      formsLoading: state => state['open/forms'].loading,
-      workspacesLoading: state => state['open/workspaces'].loading
-    }),
     workingForm: {
-      get() {
-        return this.$store.state['open/working_form'].content
+      get () {
+        return this.workingFormStore.content
       },
-      set(value) {
-        this.$store.commit('open/working_form/set', value)
+      /* We add a setter */
+      set (value) {
+        this.workingFormStore.set(value)
       }
     },
     workspace() {
       if (!this.form) return null
-      return this.$store.getters['open/workspaces/getById'](this.form.workspace_id)
+      return this.workspacesStore.getById(this.form.workspace_id)
     },
     form() {
-      return this.$store.getters['open/forms/getBySlug'](this.$route.params.slug)
+      return this.formsStore.getBySlug(this.$route.params.slug)
     },
     formEndpoint: () => '/api/open/forms/{id}',
     loading() {
diff --git a/resources/js/pages/home.vue b/resources/js/pages/home.vue
index d87826250..2779761c2 100644
--- a/resources/js/pages/home.vue
+++ b/resources/js/pages/home.vue
@@ -104,8 +104,10 @@
 </template>
 
 <script>
-import store from '~/store'
-import { mapGetters, mapState } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../stores/auth';
+import { useFormsStore } from '../stores/forms';
+import { useWorkspacesStore } from '../stores/workspaces';
 import Fuse from 'fuse.js'
 import Form from 'vform'
 import TextInput from '../components/forms/TextInput.vue'
@@ -113,9 +115,11 @@ import OpenFormFooter from '../components/pages/OpenFormFooter.vue'
 import ExtraMenu from '../components/pages/forms/show/ExtraMenu.vue'
 
 const loadForms = function () {
-  store.commit('open/forms/startLoading')
-  store.dispatch('open/workspaces/loadIfEmpty').then(() => {
-    store.dispatch('open/forms/loadIfEmpty', store.state['open/workspaces'].currentId)
+  const formsStore = useFormsStore()
+  const workspacesStore = useWorkspacesStore()
+  formsStore.startLoading()
+  workspacesStore.loadIfEmpty().then(() => {
+    formsStore.loadIfEmpty(workspacesStore.currentId)
   })
 }
 
@@ -133,6 +137,19 @@ export default {
     metaDescription: { type: String, default: 'All of your OpnForm are here. Create new forms, or update your existing one!' }
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    const formsStore = useFormsStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      formsStore,
+      workspacesStore,
+      user : computed(() => authStore.user),
+      forms : computed(() => formsStore.content),
+      formsLoading : computed(() => formsStore.loading)
+    }
+  },
+
   data () {
     return {
       showEditFormModal: false,
@@ -165,19 +182,12 @@ export default {
   },
 
   computed: {
-    ...mapGetters({
-      user: 'auth/user'
-    }),
-    ...mapState({
-      forms: state => state['open/forms'].content,
-      formsLoading: state => state['open/forms'].loading
-    }),
     isFilteringForms () {
       return (this.searchForm.search !== '' && this.searchForm.search !== null) || this.selectedTags.length > 0
     },
     enrichedForms () {
       let enrichedForms = this.forms.map((form) => {
-        form.workspace = this.$store.getters['open/workspaces/getById'](form.workspace_id)
+        form.workspace = this.workspacesStore.getById(form.workspace_id)
         return form
       })
 
@@ -206,7 +216,7 @@ export default {
       })
     },
     allTags () {
-      return this.$store.getters['open/forms/getAllTags']
+      return this.formsStore.getAllTags
     }
   }
 }
diff --git a/resources/js/pages/pricing.vue b/resources/js/pages/pricing.vue
index a83b22c92..7c371d013 100644
--- a/resources/js/pages/pricing.vue
+++ b/resources/js/pages/pricing.vue
@@ -236,14 +236,14 @@
 </template>
 
 <script>
-import {mapGetters} from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../stores/auth';
 import OpenFormFooter from '../components/pages/OpenFormFooter.vue'
 import PricingTable from '../components/pages/pricing/PricingTable.vue'
 import SeoMeta from '../mixins/seo-meta.js'
 
 export default {
   components: {OpenFormFooter, PricingTable},
-
   mixins: [SeoMeta],
   layout: 'default',
 
@@ -257,20 +257,23 @@ export default {
     next()
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      user : computed(() => authStore.user),
+      authenticated : computed(() => authStore.check)
+    }
+  },
+
   data: () => ({
     metaTitle: 'Pricing',
     metaDescription: 'All of our core features are free, and there is no quantity limit. You can also created more advanced and customized forms with OpnForms Pro.',
   }),
 
-  mounted() {
-  },
+  mounted() {},
+
+  computed: {},
 
-  computed: {
-    ...mapGetters({
-      authenticated: 'auth/check',
-      user: 'auth/user'
-    })
-  },
   methods: {
     contactUs() {
       window.$crisp.push(['do', 'chat:show'])
diff --git a/resources/js/pages/settings/account.vue b/resources/js/pages/settings/account.vue
index 7c23d355a..6cb4f690e 100644
--- a/resources/js/pages/settings/account.vue
+++ b/resources/js/pages/settings/account.vue
@@ -18,12 +18,20 @@
 <script>
 import Form from 'vform'
 import axios from 'axios'
+import { useAuthStore } from '../../stores/auth'
 import SeoMeta from '../../mixins/seo-meta.js'
 
 export default {
   scrollToTop: false,
   mixins: [SeoMeta],
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authStore
+    }
+  },
+
   data: () => ({
     metaTitle: 'Account',
     form: new Form({
@@ -39,7 +47,7 @@ export default {
         this.loading = false
         this.alertSuccess(response.data.message)
         // Log out the user.
-        await this.$store.dispatch('auth/logout')
+        await this.authStore.logout()
 
         // Redirect to login.
         this.$router.push({ name: 'login' })
diff --git a/resources/js/pages/settings/admin.vue b/resources/js/pages/settings/admin.vue
index 17afc959f..0781f64db 100644
--- a/resources/js/pages/settings/admin.vue
+++ b/resources/js/pages/settings/admin.vue
@@ -37,6 +37,8 @@
 <script>
 import Form from 'vform'
 import axios from 'axios'
+import { useAuthStore } from '../../stores/auth'
+import { useWorkspacesStore } from '../../stores/workspaces'
 import SeoMeta from '../../mixins/seo-meta.js'
 
 export default {
@@ -45,6 +47,15 @@ export default {
   scrollToTop: false,
   mixins: [SeoMeta],
 
+  setup () {
+    const authStore = useAuthStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      authStore,
+      workspacesStore
+    }
+  },
+
   data: () => ({
     metaTitle: 'Admin',
     form: new Form({
@@ -56,21 +67,18 @@ export default {
   methods: {
     async impersonate () {
       this.loading = true
-      this.$store.commit('auth/startImpersonating')
+      this.authStore.startImpersonating()
       axios.get('/api/admin/impersonate/' + encodeURI(this.form.identifier)).then(async (response) => {
         this.loading = false
 
         // Save the token.
-        this.$store.dispatch('auth/saveToken', {
-          token: response.data.token,
-          remember: false
-        })
+        this.authStore.saveToken(response.data.token, false)
 
         // Fetch the user.
-        await this.$store.dispatch('auth/fetchUser')
+        await this.authStore.fetchUser()
 
         // Redirect to the dashboard.
-        this.$store.commit('open/workspaces/set', [])
+        this.workspacesStore.set([])
         this.$router.push({ name: 'home' })
       }).catch((error) => {
         this.alertError(error.response.data.message)
diff --git a/resources/js/pages/settings/billing.vue b/resources/js/pages/settings/billing.vue
index 47a497f2c..1ba8ef795 100644
--- a/resources/js/pages/settings/billing.vue
+++ b/resources/js/pages/settings/billing.vue
@@ -21,9 +21,10 @@
 
 <script>
 import axios from 'axios'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
 import VButton from '../../components/common/Button.vue'
 import SeoMeta from '../../mixins/seo-meta.js'
-import { mapGetters } from 'vuex'
 import AppSumoBilling from '../../components/vendor/appsumo/AppSumoBilling.vue'
 
 export default {
@@ -31,6 +32,13 @@ export default {
   mixins: [SeoMeta],
   scrollToTop: false,
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      user : computed(() => authStore.user)
+    }
+  },
+
   data: () => ({
     metaTitle: 'Billing',
     billingLoading: false
@@ -50,10 +58,6 @@ export default {
     }
   },
 
-  computed: {
-    ...mapGetters({
-      user: 'auth/user'
-    })
-  }
+  computed: {}
 }
 </script>
diff --git a/resources/js/pages/settings/index.vue b/resources/js/pages/settings/index.vue
index b371a513d..457d9983e 100644
--- a/resources/js/pages/settings/index.vue
+++ b/resources/js/pages/settings/index.vue
@@ -38,20 +38,25 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
 
 export default {
   middleware: 'auth',
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      user : computed(() => authStore.user)
+    }
+  },
+
   data () {
     return {
     }
   },
 
   computed: {
-    ...mapGetters({
-      user: 'auth/user'
-    }),
     tabsList () {
       const tabs = [
         {
diff --git a/resources/js/pages/settings/profile.vue b/resources/js/pages/settings/profile.vue
index a7287511a..efb114b6d 100644
--- a/resources/js/pages/settings/profile.vue
+++ b/resources/js/pages/settings/profile.vue
@@ -24,13 +24,22 @@
 
 <script>
 import Form from 'vform'
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
 import SeoMeta from '../../mixins/seo-meta.js'
 
 export default {
   mixins: [SeoMeta],
   scrollToTop: false,
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authStore,
+      user : computed(() => authStore.user)
+    }
+  },
+
   data: () => ({
     metaTitle: 'Profile',
     form: new Form({
@@ -39,10 +48,6 @@ export default {
     })
   }),
 
-  computed: mapGetters({
-    user: 'auth/user'
-  }),
-
   created () {
     // Fill the form with user data.
     this.form.keys().forEach(key => {
@@ -54,7 +59,7 @@ export default {
     async update () {
       const { data } = await this.form.patch('/api/settings/profile')
 
-      this.$store.dispatch('auth/updateUser', { user: data })
+      this.authStore.updateUser(data)
     }
   }
 }
diff --git a/resources/js/pages/settings/workspace.vue b/resources/js/pages/settings/workspace.vue
index d0094deea..231763a59 100644
--- a/resources/js/pages/settings/workspace.vue
+++ b/resources/js/pages/settings/workspace.vue
@@ -73,8 +73,10 @@
 </template>
 
 <script>
+import { computed } from 'vue'
 import Form from 'vform'
-import {mapActions, mapState} from 'vuex'
+import { useFormsStore } from '../../stores/forms'
+import { useWorkspacesStore } from '../../stores/workspaces'
 import SeoMeta from '../../mixins/seo-meta.js'
 
 export default {
@@ -82,6 +84,17 @@ export default {
   scrollToTop: false,
   mixins: [SeoMeta],
 
+  setup () {
+    const formsStore = useFormsStore()
+    const workspacesStore = useWorkspacesStore()
+    return {
+      formsStore,
+      workspacesStore,
+      workspaces: computed(() => workspacesStore.content),
+      loading: computed(() => workspacesStore.loading)
+    }
+  },
+
   data: () => ({
     metaTitle: 'Workspaces',
     form: new Form({
@@ -92,28 +105,20 @@ export default {
   }),
 
   mounted() {
-    this.loadWorkspaces()
+    this.workspacesStore.loadIfEmpty()
   },
 
-  computed: {
-    ...mapState({
-      workspaces: state => state['open/workspaces'].content,
-      loading: state => state['open/workspaces'].loading
-    })
-  },
+  computed: {},
 
   methods: {
-    ...mapActions({
-      loadWorkspaces: 'open/workspaces/loadIfEmpty'
-    }),
     switchWorkspace(workspace) {
-      this.$store.commit('open/workspaces/setCurrentId', workspace.id)
+      this.workspacesStore.setCurrentId(workspace.id)
       this.$router.push({name: 'home'})
-      this.$store.dispatch('open/forms/load', workspace.id)
+      this.formsStore.load(workspace.id)
     },
     deleteWorkspace(workspace) {
       this.alertConfirm('Do you really want to delete this workspace? All forms created in this workspace will be removed.', () => {
-        this.$store.dispatch('open/workspaces/delete', workspace.id).then(() => {
+        this.workspacesStore.delete(workspace.id).then(() => {
           this.alertSuccess('Workspace successfully removed.')
         })
       })
@@ -129,7 +134,7 @@ export default {
     },
     async createWorkspace() {
       const {data} = await this.form.post('/api/open/workspaces/create')
-      this.$store.dispatch('open/workspaces/load')
+      this.workspacesStore.load()
       this.workspaceModal = false
     }
   }
diff --git a/resources/js/pages/subscriptions/error.vue b/resources/js/pages/subscriptions/error.vue
index 894ad634b..fc33a4227 100644
--- a/resources/js/pages/subscriptions/error.vue
+++ b/resources/js/pages/subscriptions/error.vue
@@ -1,7 +1,8 @@
 <template />
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
 import SeoMeta from '../../mixins/seo-meta.js'
 
 export default {
@@ -10,6 +11,13 @@ export default {
   middleware: 'auth',
   mixins: [SeoMeta],
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authenticated : computed(() => authStore.check),
+    }
+  },
+
   data: () => ({
     metaTitle: 'Error',
   }),
@@ -19,10 +27,6 @@ export default {
     this.alertError('Unfortunately we could not confirm your subscription. Please try again and contact us if the issue persists.')
   },
 
-  computed: {
-    ...mapGetters({
-      authenticated: 'auth/check'
-    })
-  }
+  computed: {}
 }
 </script>
diff --git a/resources/js/pages/subscriptions/success.vue b/resources/js/pages/subscriptions/success.vue
index b70467a3b..e8d976f64 100644
--- a/resources/js/pages/subscriptions/success.vue
+++ b/resources/js/pages/subscriptions/success.vue
@@ -16,7 +16,8 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
 import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
 import SeoMeta from '../../mixins/seo-meta.js'
 
@@ -26,6 +27,15 @@ export default {
   layout: 'default',
   middleware: 'auth',
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authStore,
+      authenticated : computed(() => authStore.check),
+      user : computed(() => authStore.user)
+    }
+  },
+
   data: () => ({
     metaTitle: 'Subscription Success',
     interval: null
@@ -43,7 +53,7 @@ export default {
   methods: {
     async checkSubscription () {
       // Fetch the user.
-      await this.$store.dispatch('auth/fetchUser')
+      await this.authStore.fetchUser()
       this.redirectIfSubscribed()
     },
     redirectIfSubscribed () {
@@ -63,11 +73,6 @@ export default {
     }
   },
 
-  computed: {
-    ...mapGetters({
-      authenticated: 'auth/check',
-      user: 'auth/user'
-    })
-  }
+  computed: {}
 }
 </script>
diff --git a/resources/js/pages/templates/industries-show.vue b/resources/js/pages/templates/industries-show.vue
index cee4b6394..ecfff178e 100644
--- a/resources/js/pages/templates/industries-show.vue
+++ b/resources/js/pages/templates/industries-show.vue
@@ -93,19 +93,21 @@
 </template>
 
 <script>
-import store from '~/store'
 import Form from 'vform'
 import Fuse from 'fuse.js'
-import { mapGetters, mapState } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
+import { useTemplatesStore } from '../../stores/templates'
 import SeoMeta from '../../mixins/seo-meta.js'
 import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
 import Breadcrumb from '../../components/common/Breadcrumb.vue'
 import SingleTemplate from '../../components/pages/templates/SingleTemplate.vue'
 
 const loadTemplates = function () {
-  store.commit('open/templates/startLoading')
-  store.dispatch('open/templates/loadIfEmpty').then(() => {
-    store.commit('open/templates/stopLoading')
+  const templatesStore = useTemplatesStore()
+  templatesStore.startLoading()
+  templatesStore.loadIfEmpty().then(() => {
+    templatesStore.stopLoading()
   })
 }
 
@@ -118,6 +120,20 @@ export default {
     next()
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    const templatesStore = useTemplatesStore()
+    return {
+      authStore,
+      authenticated : computed(() => authStore.check),
+      user : computed(() => authStore.user),
+      templates : computed(() => templatesStore.content),
+      templatesLoading : computed(() => templatesStore.loading),
+      industries : computed(() => templatesStore.industries),
+      types : computed(() => templatesStore.types)
+    }
+  },
+
   data () {
     return {
       selectedType: 'all',
@@ -130,16 +146,6 @@ export default {
   mounted () {},
 
   computed: {
-    ...mapGetters({
-      authenticated: 'auth/check',
-      user: 'auth/user'
-    }),
-    ...mapState({
-      templates: state => state['open/templates'].content,
-      templatesLoading: state => state['open/templates'].loading,
-      industries: state => state['open/templates'].industries,
-      types: state => state['open/templates'].types
-    }),
     breadcrumbs () {
       if (!this.industry) {
         return [{ route: { name: 'templates' }, label: 'Templates' }]
diff --git a/resources/js/pages/templates/show.vue b/resources/js/pages/templates/show.vue
index 204c79ac4..c1fed685b 100644
--- a/resources/js/pages/templates/show.vue
+++ b/resources/js/pages/templates/show.vue
@@ -196,9 +196,10 @@
 </template>
 
 <script>
-import store from '~/store'
 import Form from 'vform'
-import { mapGetters, mapState } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
+import { useTemplatesStore } from '../../stores/templates'
 import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
 import OpenCompleteForm from '../../components/open/forms/OpenCompleteForm.vue'
 import Breadcrumb from '../../components/common/Breadcrumb.vue'
@@ -213,21 +214,32 @@ export default {
   mixins: [SeoMeta],
 
   beforeRouteEnter (to, from, next) {
+    const templatesStore = useTemplatesStore()
     if (to.params?.slug) {
-      store.dispatch('open/templates/loadTemplate', to.params?.slug)
-      store.dispatch('open/templates/loadTypesAndIndustries')
+      templatesStore.loadTemplate(to.params?.slug)
+      templatesStore.loadTypesAndIndustries()
     }
     next()
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    const templatesStore = useTemplatesStore()
+    return {
+      templatesStore,
+      authenticated : computed(() => authStore.check),
+      user : computed(() => authStore.user),
+      templatesLoading : computed(() => templatesStore.loading)
+    }
+  },
+
   data () {
     return {
       showFormTemplateModal: false
     }
   },
 
-  mounted () {
-  },
+  mounted () {},
 
   methods: {
     cleanQuotes (str) {
@@ -247,13 +259,6 @@ export default {
   },
 
   computed: {
-    ...mapGetters({
-      authenticated: 'auth/check',
-      user: 'auth/user'
-    }),
-    ...mapState({
-      templatesLoading: state => state['open/templates'].loading
-    }),
     breadcrumbs () {
       if (!this.template) {
         return [{ route: { name: 'templates' }, label: 'Templates' }]
@@ -261,7 +266,7 @@ export default {
       return [{ route: { name: 'templates' }, label: 'Templates' }, { label: this.template.name }]
     },
     template () {
-      return this.$store.getters['open/templates/getBySlug'](this.$route.params.slug)
+      return this.templatesStore.getBySlug(this.$route.params.slug)
     },
     form () {
       return this.template ? new Form(this.template.structure) : null
diff --git a/resources/js/pages/templates/types-show.vue b/resources/js/pages/templates/types-show.vue
index b91ef873d..805633c29 100644
--- a/resources/js/pages/templates/types-show.vue
+++ b/resources/js/pages/templates/types-show.vue
@@ -93,19 +93,21 @@
 </template>
 
 <script>
-import store from '~/store'
 import Form from 'vform'
 import Fuse from 'fuse.js'
-import { mapGetters, mapState } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../../stores/auth'
+import { useTemplatesStore } from '../../stores/templates'
 import SeoMeta from '../../mixins/seo-meta.js'
 import OpenFormFooter from '../../components/pages/OpenFormFooter.vue'
 import Breadcrumb from '../../components/common/Breadcrumb.vue'
 import SingleTemplate from '../../components/pages/templates/SingleTemplate.vue'
 
 const loadTemplates = function () {
-  store.commit('open/templates/startLoading')
-  store.dispatch('open/templates/loadIfEmpty').then(() => {
-    store.commit('open/templates/stopLoading')
+  const templatesStore = useTemplatesStore()
+  templatesStore.startLoading()
+  templatesStore.loadIfEmpty().then(() => {
+    templatesStore.stopLoading()
   })
 }
 
@@ -118,6 +120,19 @@ export default {
     next()
   },
 
+  setup () {
+    const authStore = useAuthStore()
+    const templatesStore = useTemplatesStore()
+    return {
+      authenticated : computed(() => authStore.check),
+      user : computed(() => authStore.user),
+      templates : computed(() => templatesStore.content),
+      templatesLoading : computed(() => templatesStore.loading),
+      industries : computed(() => templatesStore.industries),
+      types : computed(() => templatesStore.types)
+    }
+  },
+
   data () {
     return {
       selectedIndustry: 'all',
@@ -130,16 +145,6 @@ export default {
   mounted () {},
 
   computed: {
-    ...mapGetters({
-      authenticated: 'auth/check',
-      user: 'auth/user'
-    }),
-    ...mapState({
-      templates: state => state['open/templates'].content,
-      templatesLoading: state => state['open/templates'].loading,
-      industries: state => state['open/templates'].industries,
-      types: state => state['open/templates'].types
-    }),
     breadcrumbs () {
       if (!this.type) {
         return [{ route: { name: 'templates' }, label: 'Templates' }]
diff --git a/resources/js/pages/welcome.vue b/resources/js/pages/welcome.vue
index 58bce1119..fbc76f026 100644
--- a/resources/js/pages/welcome.vue
+++ b/resources/js/pages/welcome.vue
@@ -181,7 +181,8 @@
 </template>
 
 <script>
-import { mapGetters } from 'vuex'
+import { computed } from 'vue'
+import { useAuthStore } from '../stores/auth'
 import Features from '~/components/pages/welcome/Features.vue'
 import MoreFeatures from '~/components/pages/welcome/MoreFeatures.vue'
 import PricingTable from '../components/pages/pricing/PricingTable.vue'
@@ -193,11 +194,16 @@ import SeoMeta from '../mixins/seo-meta.js'
 
 export default {
   components: { Testimonials, OpenFormFooter, Features, MoreFeatures, PricingTable, AiFeature, TemplatesSlider },
-
   mixins: [SeoMeta],
-
   layout: 'default',
 
+  setup () {
+    const authStore = useAuthStore()
+    return {
+      authenticated : computed(() => authStore.check)
+    }
+  },
+
   data: () => ({
     title: window.config.appName,
     metaTitle: 'Create beautiful & open-source forms for free'
@@ -215,9 +221,6 @@ export default {
   },
 
   computed: {
-    ...mapGetters({
-      authenticated: 'auth/check'
-    }),
     configLinks: () => window.config.links,
     paidPlansEnabled () {
       return window.config.paid_plans_enabled
diff --git a/resources/js/plugins/axios.js b/resources/js/plugins/axios.js
index 7cab8dfab..f5f525fc2 100644
--- a/resources/js/plugins/axios.js
+++ b/resources/js/plugins/axios.js
@@ -1,5 +1,5 @@
 import axios from 'axios'
-import store from '~/store'
+import { useAuthStore } from '../stores/auth';
 import router from '~/router'
 import Cookies from 'js-cookie'
 
@@ -17,16 +17,13 @@ function addPasswordToFormRequest (request) {
 
 // Request interceptor
 axios.interceptors.request.use(request => {
-  const token = store.getters['auth/token']
+  const authStore = useAuthStore()
+  const token = authStore.token
   if (token) {
     request.headers.common.Authorization = `Bearer ${token}`
   }
 
-  const locale = store.getters['lang/locale']
-  if (locale) {
-    request.headers.common['Accept-Language'] = locale
-  }
-
+  request.headers.common['Accept-Language'] = 'en-US'
   // request.headers['X-Socket-Id'] = Echo.socketId()
 
   request = addPasswordToFormRequest(request)
@@ -36,14 +33,14 @@ axios.interceptors.request.use(request => {
 
 // Response interceptor
 axios.interceptors.response.use(response => response, error => {
+  const authStore = useAuthStore()
   const { status } = error.response
   if (status >= 500) {
     console.log(status)
   }
 
-  if (status === 401 && store.getters['auth/check']) {
-    store.commit('auth/LOGOUT')
-
+  if (status === 401 && authStore.check) {
+    authStore.logout()
     router.push({ name: 'login' })
   }
 
diff --git a/resources/js/router/index.js b/resources/js/router/index.js
index a9c8ffc3c..b9dec2a21 100644
--- a/resources/js/router/index.js
+++ b/resources/js/router/index.js
@@ -1,7 +1,7 @@
 import routes from './routes'
 import { createWebHistory, createRouter } from 'vue-router'
 import * as Sentry from '@sentry/vue'
-import store from '../store'
+import { useAppStore } from '../stores/app'
 import { defineComponent, nextTick } from 'vue'
 
 // The middleware for every page of the application.
@@ -45,6 +45,8 @@ async function getMatchedComponents (to) {
  * @param {Function} next
  */
 async function beforeEach (to, from, next) {
+  const appStore = useAppStore()
+
   // Sentry tracking
   if (window.config.sentry_dsn) {
     Sentry.configureScope((scope) => scope.setTransactionName(to?.name || 'Unknown route name'))
@@ -75,7 +77,7 @@ async function beforeEach (to, from, next) {
 
   // Start the loading bar.
   if (components[components.length - 1].loading !== false) {
-    nextTick(() => store.commit('app/loaderStart'))
+    nextTick(() => appStore.loaderStart())
   }
 
   // Get the middleware for all the matched components.
@@ -86,11 +88,11 @@ async function beforeEach (to, from, next) {
     // Set the application layout only if "next()" was called with no args.
     if (args.length === 0) {
       if (components[0].layout) {
-        store.commit('app/setLayout', components[0].layout)
+        appStore.setLayout(components[0].layout)
       } else if (components[0].default && components[0].default.layout) {
-        store.commit('app/setLayout', components[0].default.layout)
+        appStore.setLayout(components[0].default.layout)
       } else {
-        store.commit('app/setLayout', null)
+        appStore.setLayout(null)
       }
     }
 
@@ -106,7 +108,8 @@ async function beforeEach (to, from, next) {
  * @param {Function} next
  */
 async function afterEach (to, from, next) {
-  nextTick(() => store.commit('app/loaderFinish'))
+  const appStore = useAppStore()
+  nextTick(() => appStore.loaderFinish())
 }
 
 /**
@@ -118,13 +121,14 @@ async function afterEach (to, from, next) {
  * @param {Function} next
  */
 function callMiddleware (middleware, to, from, next) {
+  const appStore = useAppStore()
   const stack = middleware.reverse()
 
   const _next = (...args) => {
     // Stop if "_next" was called with an argument or the stack is empty.
     if (args.length > 0 || stack.length === 0) {
       if (args.length > 0) {
-        store.commit('app/loaderFinish')
+        appStore.loaderFinish()
       }
 
       return next(...args)
diff --git a/resources/js/store/index.js b/resources/js/store/index.js
deleted file mode 100644
index baa637ffd..000000000
--- a/resources/js/store/index.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import Vue from 'vue'
-import Vuex from 'vuex'
-
-Vue.use(Vuex)
-
-// Load store modules dynamically.
-const requireContext = import.meta.glob('./modules/**/*.js', {eager: true})
-const modules = Object.keys(requireContext)
-
-  .map(file =>
-    [file.replace(/(^.\/)|(\.js$)/g, '').replace('modules/',''), requireContext[file]]
-  )
-  .reduce((modules, [name, module]) => {
-    if (module.namespaced === undefined) {
-      module = {...module, namespaced: true}
-    }
-
-    return { ...modules, [name]: module }
-  }, {})
-export default new Vuex.Store({
-  modules
-})
diff --git a/resources/js/store/modules/app.js b/resources/js/store/modules/app.js
deleted file mode 100644
index 5a459331d..000000000
--- a/resources/js/store/modules/app.js
+++ /dev/null
@@ -1,73 +0,0 @@
-import { nextTick } from 'vue'
-
-export const state = {
-  layout: 'default',
-
-  // App Loader
-  loader: {
-    percent: 0,
-    show: false,
-    canSuccess: true,
-    duration: 3000,
-    _timer: null,
-    _cut: null
-  }
-}
-
-export const mutations = {
-  setLayout (state, layout) {
-    state.layout = layout ?? 'default'
-  },
-  loaderStart (state) {
-    state.loader.show = true
-    state.loader.canSuccess = true
-    if (state.loader._timer) {
-      clearInterval(state.loader._timer)
-      state.loader.percent = 0
-    }
-    state.loader._cut = 10000 / Math.floor(state.loader.duration)
-  },
-  loaderIncrease (state, num) {
-    state.loader.percent = state.loader.percent + Math.floor(num)
-  },
-  loaderDecrease (state, num) {
-    state.loader.percent = state.loader.percent - Math.floor(num)
-  },
-  loaderFinish (state) {
-    state.loader.percent = 100
-    mutations.loaderHide(state)
-  },
-  loaderSetTimer (state, timerVal) {
-    state._timer = timerVal
-  },
-  loaderPause (state) {
-    clearInterval(state.loader._timer)
-  },
-  loaderHide (state) {
-    clearInterval(state.loader._timer)
-    state.loader._timer = null
-    setTimeout(() => {
-      state.loader.show = false
-      nextTick(() => {
-        setTimeout(() => {
-          state.loader.percent = 0
-        }, 200)
-      })
-    }, 500)
-  },
-  loaderFail () {
-    state.loader.canSuccess = false
-  }
-}
-
-export const actions = {
-  loaderStart ({ commit, dispatch }) {
-    mutations.loaderStart()
-    mutations.loaderSetTimer(setInterval(() => {
-      mutations.loaderIncrease(state.loader._cut * Math.random())
-      if (state.loader.percent > 95) {
-        mutations.loaderFinish()
-      }
-    }, 100))
-  }
-}
diff --git a/resources/js/store/modules/auth.js b/resources/js/store/modules/auth.js
deleted file mode 100644
index f76cf4a57..000000000
--- a/resources/js/store/modules/auth.js
+++ /dev/null
@@ -1,104 +0,0 @@
-import axios from 'axios'
-import Cookies from 'js-cookie'
-import * as types from '../mutation-types'
-
-// state
-export const state = {
-  user: null,
-  token: Cookies.get('token'),
-
-  // For admin impersonation
-  admin_token: Cookies.get('admin_token') ?? null
-}
-
-// getters
-export const getters = {
-  user: state => state.user,
-  token: state => state.token,
-  check: state => state.user !== null,
-  isImpersonating: state => state.admin_token !== null
-}
-
-// mutations
-export const mutations = {
-  [types.SAVE_TOKEN] (state, { token, remember }) {
-    state.token = token
-    Cookies.set('token', token, { expires: remember ? 365 : null })
-  },
-
-  [types.FETCH_USER_SUCCESS] (state, { user }) {
-    state.user = user
-  },
-
-  [types.FETCH_USER_FAILURE] (state) {
-    state.token = null
-    Cookies.remove('token')
-  },
-
-  [types.LOGOUT] (state) {
-    state.user = null
-    state.token = null
-
-    Cookies.remove('token')
-  },
-
-  [types.UPDATE_USER] (state, { user }) {
-    state.user = user
-  },
-
-  // Stores admin token temporarily for impersonation
-  startImpersonating (state) {
-    state.admin_token = state.token
-    Cookies.set('admin_token', state.token, { expires: 365 })
-  },
-
-  // Stores admin token temporarily for impersonation
-  stopImpersonating (state) {
-    state.token = state.admin_token
-    state.admin_token = null
-    Cookies.set('token', state.token, { expires: 365 })
-    Cookies.remove('admin_token')
-  }
-}
-
-// actions
-export const actions = {
-  saveToken ({ commit, dispatch }, payload) {
-    commit(types.SAVE_TOKEN, payload)
-  },
-
-  async fetchUser ({ commit }) {
-    try {
-      const { data } = await axios.get('/api/user')
-
-      commit(types.FETCH_USER_SUCCESS, { user: data })
-      return data
-    } catch (e) {
-      commit(types.FETCH_USER_FAILURE)
-    }
-  },
-
-  updateUser ({ commit }, payload) {
-    commit(types.UPDATE_USER, payload)
-  },
-
-  async logout ({ commit }) {
-    try {
-      await axios.post('/api/logout')
-    } catch (e) { }
-
-    commit(types.LOGOUT)
-  },
-
-  async fetchOauthUrl (ctx, { provider }) {
-    const { data } = await axios.post(`/api/oauth/${provider}`)
-
-    return data.url
-  },
-
-  // Reverse admin impersonation
-  stopImpersonating ({ commit, dispatch }, payload) {
-    commit('stopImpersonating')
-    return dispatch('fetchUser')
-  }
-}
diff --git a/resources/js/store/modules/blog/guides.js b/resources/js/store/modules/blog/guides.js
deleted file mode 100644
index fad7068d9..000000000
--- a/resources/js/store/modules/blog/guides.js
+++ /dev/null
@@ -1,35 +0,0 @@
-import Vue from 'vue'
-
-export const namespaced = true
-
-// state
-export const state = {
-  content: []
-}
-
-// getters
-export const getters = {
-  getById: (state) => (id) => {
-    if (state.content.length === 0) return null
-    return state.content.find(item => item.id === id)
-  }
-}
-
-// mutations
-export const mutations = {
-  set (state, items) {
-    state.content = items
-  },
-  addOrUpdate (state, item) {
-    state.content = state.content.filter((val) => val.id !== item.id)
-    state.content.push(item)
-  },
-  remove (state, item) {
-    state.content = state.content.filter((val) => val.id !== item.id)
-  }
-}
-
-// actions
-export const actions = {
-
-}
diff --git a/resources/js/store/modules/open/errors.js b/resources/js/store/modules/open/errors.js
deleted file mode 100644
index 45226a3d4..000000000
--- a/resources/js/store/modules/open/errors.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import Vue from 'vue'
-
-export const namespaced = true
-
-// state
-export const state = {
-  content: null
-}
-
-// getters
-export const getters = {
-}
-
-// mutations
-export const mutations = {
-  set (state, error) {
-    state.content = error
-  },
-  clear (state) {
-    state.content = null
-  }
-}
-
-// actions
-export const actions = {
-
-}
diff --git a/resources/js/store/modules/open/forms.js b/resources/js/store/modules/open/forms.js
deleted file mode 100644
index ae9b237d0..000000000
--- a/resources/js/store/modules/open/forms.js
+++ /dev/null
@@ -1,85 +0,0 @@
-import axios from 'axios'
-
-export const formsEndpoint = '/api/open/workspaces/{workspaceId}/forms'
-export const namespaced = true
-export let currentPage = 1
-
-// state
-export const state = {
-  content: [],
-  loading: false
-}
-
-// getters
-export const getters = {
-  getById: (state) => (id) => {
-    if (state.content.length === 0) return null
-    return state.content.find(item => item.id === id)
-  },
-  getBySlug: (state) => (slug) => {
-    if (state.content.length === 0) return null
-    return state.content.find(item => item.slug === slug)
-  },
-  getAllTags: (state) => {
-    if (state.content.length === 0) return []
-    let allTags = []
-    state.content.forEach(form => {
-      if(form.tags && form.tags.length > 0){
-        allTags = allTags.concat(form.tags)
-      }
-    })
-    return allTags.filter((item, i, ar) => ar.indexOf(item) === i)
-  }
-}
-
-// mutations
-export const mutations = {
-  set (state, items) {
-    state.content = items
-  },
-  append (state, items) {
-    state.content = state.content.concat(items)
-  },
-  addOrUpdate (state, item) {
-    state.content = state.content.filter((val) => val.id !== item.id)
-    state.content.push(item)
-  },
-  remove (state, item) {
-    state.content = state.content.filter((val) => val.id !== item.id)
-  },
-  startLoading (state) {
-    state.loading = true
-  },
-  stopLoading (state) {
-    state.loading = false
-  }
-}
-
-// actions
-export const actions = {
-  resetState (context) {
-    context.commit('set', [])
-    context.commit('stopLoading')
-    currentPage = 1
-  },
-  load (context, workspaceId) {
-    context.commit('startLoading')
-    return axios.get(formsEndpoint.replace('{workspaceId}', workspaceId)+'?page='+currentPage).then((response) => {
-      context.commit((currentPage == 1) ? 'set' : 'append', response.data.data)
-      if (currentPage < response.data.meta.last_page) {
-        currentPage += 1
-        context.dispatch('load', workspaceId)
-      } else {
-        context.commit('stopLoading')
-        currentPage = 1
-      }
-    })
-  },
-  loadIfEmpty (context, workspaceId) {
-    if (context.state.content.length === 0) {
-      return context.dispatch('load', workspaceId)
-    }
-    context.commit('stopLoading')
-    return Promise.resolve()
-  }
-}
diff --git a/resources/js/store/modules/open/records.js b/resources/js/store/modules/open/records.js
deleted file mode 100644
index 8bb0e8844..000000000
--- a/resources/js/store/modules/open/records.js
+++ /dev/null
@@ -1,58 +0,0 @@
-import axios from 'axios'
-
-export const namespaced = true
-export const workspaceEndpoint = '/api/open/records/'
-
-/**
- * Loads records from database
- */
-
-// state
-export const state = {
-  content: [],
-  loading: false
-}
-
-// getters
-export const getters = {
-  getById: (state) => (id) => {
-    if (state.content.length === 0) return null
-    return state.content.find(item => item.submission_id === id)
-  }
-}
-
-// mutations
-export const mutations = {
-  set (state, items) {
-    state.content = items
-  },
-  addOrUpdate (state, item) {
-    state.content = state.content.filter((val) => val.id !== item.id)
-    state.content.push(item)
-  },
-  remove (state, itemId) {
-    state.content = state.content.filter((val) => val.id !== itemId)
-  },
-  startLoading () {
-    state.loading = true
-  },
-  stopLoading () {
-    state.loading = false
-  }
-}
-
-// actions
-export const actions = {
-  resetState (context) {
-    context.commit('set', [])
-    context.commit('stopLoading')
-  },
-  loadRecord (context, request) {
-    context.commit('set', [])
-    context.commit('startLoading')
-    return request.then((data) => {
-      context.commit('addOrUpdate', data)
-      context.commit('stopLoading')
-    })
-  }
-}
\ No newline at end of file
diff --git a/resources/js/store/modules/open/templates.js b/resources/js/store/modules/open/templates.js
deleted file mode 100644
index 15f96de67..000000000
--- a/resources/js/store/modules/open/templates.js
+++ /dev/null
@@ -1,126 +0,0 @@
-import axios from 'axios'
-
-export const templatesEndpoint = '/api/templates'
-export const namespaced = true
-
-// state
-export const state = {
-  content: [],
-  industries: {},
-  types: {},
-  allLoaded: false,
-  loading: false
-}
-
-// getters
-export const getters = {
-  getBySlug: (state) => (slug) => {
-    if (state.content.length === 0) return null
-    return state.content.find(item => item.slug === slug)
-  },
-  getTemplateTypes: (state) => (slugs) => {
-    if (state.types.length === 0) return null
-    return Object.values(state.types).filter((val) => slugs.includes(val.slug)).map((item) => { return item.name })
-  },
-  getTemplateIndustries: (state) => (slugs) => {
-    if (state.industries.length === 0) return null
-    return Object.values(state.industries).filter((val) => slugs.includes(val.slug)).map((item) => { return item.name })
-  }
-}
-
-// mutations
-export const mutations = {
-  set (state, items) {
-    state.content = items
-    state.allLoaded = true
-  },
-  append (state, items) {
-    const ids = items.map((item) => { return item.id })
-    state.content = state.content.filter((val) => !ids.includes(val.id))
-    state.content = state.content.concat(items)
-  },
-  addOrUpdate (state, item) {
-    state.content = state.content.filter((val) => val.id !== item.id)
-    state.content.push(item)
-  },
-  remove (state, item) {
-    state.content = state.content.filter((val) => val.id !== item.id)
-  },
-  startLoading (state) {
-    state.loading = true
-  },
-  stopLoading (state) {
-    state.loading = false
-  },
-  setAllLoaded (state, val) {
-    state.allLoaded = val
-  }
-}
-
-// actions
-export const actions = {
-  resetState (context) {
-    context.commit('set', [])
-    context.commit('stopLoading')
-  },
-  loadTypesAndIndustries (context) {
-    if (Object.keys(context.state.industries).length === 0) {
-      import('@/data/forms/templates/industries.json').then((module) => {
-        context.state.industries = module.default
-      })
-    }
-    if (Object.keys(context.state.types).length === 0) {
-      import('@/data/forms/templates/types.json').then((module) => {
-        context.state.types = module.default
-      })
-    }
-  },
-  loadTemplate (context, slug) {
-    context.commit('startLoading')
-    context.dispatch('loadTypesAndIndustries')
-
-    if (context.getters.getBySlug(slug)) {
-      context.commit('stopLoading')
-      return Promise.resolve()
-    }
-
-    return axios.get(templatesEndpoint + '/' + slug).then((response) => {
-      context.commit('addOrUpdate', response.data)
-      context.commit('stopLoading')
-    }).catch((error) => {
-      context.commit('stopLoading')
-    })
-  },
-  loadAll (context, options=null) {
-    context.commit('startLoading')
-    context.dispatch('loadTypesAndIndustries')
-
-    // Prepare with options
-    let queryStr = ''
-    if(options !== null){
-      for (const [key, value] of Object.entries(options)) {
-        queryStr += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(value)
-      }
-      queryStr = queryStr.slice(1)
-    }
-    return axios.get((queryStr) ? templatesEndpoint + '?' + queryStr : templatesEndpoint).then((response) => {
-      if(options !== null){
-        context.commit('set', response.data)
-        context.commit('setAllLoaded', false)
-      } else {
-        context.commit('append', response.data)
-        context.commit('setAllLoaded', true)
-      }
-      context.commit('stopLoading')
-    }).catch((error) => {
-      context.commit('stopLoading')
-    })
-  },
-  loadIfEmpty (context) {
-    if (!context.state.allLoaded) {
-      return context.dispatch('loadAll')
-    }
-    context.commit('stopLoading')
-    return Promise.resolve()
-  }
-}
diff --git a/resources/js/store/modules/open/working_form.js b/resources/js/store/modules/open/working_form.js
deleted file mode 100644
index 045b2e948..000000000
--- a/resources/js/store/modules/open/working_form.js
+++ /dev/null
@@ -1,49 +0,0 @@
-export const namespaced = true
-
-// state
-export const state = {
-  content: null,
-
-  // Field being edited
-  selectedFieldIndex: null,
-  showEditFieldSidebar: null,
-  showAddFieldSidebar: null
-}
-
-// mutations
-export const mutations = {
-  set (state, form) {
-    state.content = form
-  },
-  setProperties (state, properties) {
-    state.content.properties = properties
-  },
-  openSettingsForField (state, index) {
-    // If field is passed, compute index
-    if (typeof index === 'object') {
-      index = state.content.properties.findIndex(prop => prop.id === index.id)
-    }
-    state.selectedFieldIndex = index
-    state.showEditFieldSidebar = true
-    state.showAddFieldSidebar = false
-  },   
-  closeEditFieldSidebar (state) {
-    state.selectedFieldIndex = null
-    state.showEditFieldSidebar = false
-    state.showAddFieldSidebar = false
-  },
-  openAddFieldSidebar (state, index) {
-    // If field is passed, compute index
-    if (index !== null && typeof index === 'object') {
-      index = state.content.properties.findIndex(prop => prop.id === index.id)
-    }
-    state.selectedFieldIndex = index
-    state.showAddFieldSidebar = true
-    state.showEditFieldSidebar = false
-  },
-  closeAddFieldSidebar (state) {
-    state.selectedFieldIndex = null
-    state.showAddFieldSidebar = false
-    state.showEditFieldSidebar = false
-  },
-}
diff --git a/resources/js/store/modules/open/workspaces.js b/resources/js/store/modules/open/workspaces.js
deleted file mode 100644
index c14becf19..000000000
--- a/resources/js/store/modules/open/workspaces.js
+++ /dev/null
@@ -1,100 +0,0 @@
-import Vue from 'vue'
-import axios from 'axios'
-
-export const namespaced = true
-export const workspaceEndpoint = '/api/open/workspaces/'
-
-const localStorageCurrentWorkspaceKey = 'currentWorkspace'
-
-// state
-export const state = {
-  content: [],
-  currentId: null,
-  loading: false
-}
-
-// getters
-export const getters = {
-  getById: (state) => (id) => {
-    if (state.content.length === 0) return null
-    return state.content.find(item => item.id === id)
-  },
-  getCurrent: (state) => () => {
-    if (state.content.length === 0 || state.currentId === null) return null
-    return state.content.find(item => item.id === state.currentId)
-  }
-}
-
-// mutations
-export const mutations = {
-  set (state, items) {
-    state.content = items
-    if (state.currentId == null && state.content.length > 0) {
-      // If one only, set it
-      if (state.content.length === 1) {
-        state.currentId = items[0].id
-        localStorage.setItem(localStorageCurrentWorkspaceKey, state.currentId)
-      } else if (localStorage.getItem(localStorageCurrentWorkspaceKey) && state.content.find(item => item.id === parseInt(localStorage.getItem(localStorageCurrentWorkspaceKey)))) {
-        // Check local storage for current workspace, or take first
-        state.currentId = parseInt(localStorage.getItem(localStorageCurrentWorkspaceKey))
-        localStorage.setItem(localStorageCurrentWorkspaceKey, state.currentId)
-      } else {
-        // Else, take first
-        state.currentId = items[0].id
-        localStorage.setItem(localStorageCurrentWorkspaceKey, state.currentId)
-      }
-    } else {
-      localStorage.removeItem(localStorageCurrentWorkspaceKey)
-    }
-  },
-  setCurrentId (state, id) {
-    state.currentId = id
-    localStorage.setItem(localStorageCurrentWorkspaceKey, id)
-  },
-  addOrUpdate (state, item) {
-    state.content = state.content.filter((val) => val.id !== item.id)
-    state.content.push(item)
-    if (state.currentId == null) {
-      state.currentId = item.id
-      localStorage.setItem(localStorageCurrentWorkspaceKey, state.currentId)
-    }
-  },
-  remove (state, itemId) {
-    state.content = state.content.filter((val) => val.id !== itemId)
-  },
-  startLoading () {
-    state.loading = true
-  },
-  stopLoading () {
-    state.loading = false
-  }
-}
-
-// actions
-export const actions = {
-  resetState (context) {
-    context.commit('set', [])
-    context.commit('stopLoading')
-  },
-  load (context) {
-    context.commit('set', [])
-    context.commit('startLoading')
-    return axios.get(workspaceEndpoint).then((response) => {
-      context.commit('set', response.data)
-      context.commit('stopLoading')
-    })
-  },
-  loadIfEmpty ({ context, dispatch, state }) {
-    if (state.content.length === 0) {
-      return dispatch('load')
-    }
-    return Promise.resolve()
-  },
-  delete ({ commit, dispatch, state }, id) {
-    commit('startLoading')
-    return axios.delete(workspaceEndpoint + id).then((response) => {
-      commit('remove', response.data.workspace_id)
-      commit('stopLoading')
-    })
-  }
-}
diff --git a/resources/js/store/mutation-types.js b/resources/js/store/mutation-types.js
deleted file mode 100644
index 23ccf7b83..000000000
--- a/resources/js/store/mutation-types.js
+++ /dev/null
@@ -1,10 +0,0 @@
-// auth.js
-export const LOGOUT = 'LOGOUT'
-export const SAVE_TOKEN = 'SAVE_TOKEN'
-export const FETCH_USER = 'FETCH_USER'
-export const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS'
-export const FETCH_USER_FAILURE = 'FETCH_USER_FAILURE'
-export const UPDATE_USER = 'UPDATE_USER'
-
-// lang.js
-export const SET_LOCALE = 'SET_LOCALE'
diff --git a/resources/js/stores/app.js b/resources/js/stores/app.js
new file mode 100644
index 000000000..c4bce816f
--- /dev/null
+++ b/resources/js/stores/app.js
@@ -0,0 +1,71 @@
+
+import { defineStore } from 'pinia'
+import { nextTick } from 'vue'
+
+export const useAppStore = defineStore('app', {
+  state: () => ({
+    layout: 'default',
+
+    // App Loader
+    loader: {
+      percent: 0,
+      show: false,
+      canSuccess: true,
+      duration: 3000,
+      _timer: null,
+      _cut: null
+    }
+  }),
+  actions: {
+    setLayout (layout) {
+      this.layout = layout ?? 'default'
+    },
+    loaderIncrease (num) {
+      this.loader.percent = this.loader.percent + Math.floor(num)
+    },
+    loaderDecrease (num) {
+      this.loader.percent = this.loader.percent - Math.floor(num)
+    },
+    loaderFinish () {
+      this.loader.percent = 100
+      this.loaderHide()
+    },
+    loaderSetTimer (timerVal) {
+      this._timer = timerVal
+    },
+    loaderPause () {
+      clearInterval(this.loader._timer)
+    },
+    loaderHide () {
+      clearInterval(this.loader._timer)
+      this.loader._timer = null
+      setTimeout(() => {
+        this.loader.show = false
+        nextTick(() => {
+          setTimeout(() => {
+            this.loader.percent = 0
+          }, 200)
+        })
+      }, 500)
+    },
+    loaderFail () {
+      this.loader.canSuccess = false
+    },
+    loaderStart () {
+      this.loader.show = true
+      this.loader.canSuccess = true
+      if (this.loader._timer) {
+        clearInterval(this.loader._timer)
+        this.loader.percent = 0
+      }
+      this.loader._cut = 10000 / Math.floor(this.loader.duration)
+
+      this.loaderSetTimer(setInterval(() => {
+        this.loaderIncrease(this.loader._cut * Math.random())
+        if (this.loader.percent > 95) {
+          this.loaderFinish()
+        }
+      }, 100))
+    }
+  }
+})
\ No newline at end of file
diff --git a/resources/js/stores/auth.js b/resources/js/stores/auth.js
new file mode 100644
index 000000000..48c16363c
--- /dev/null
+++ b/resources/js/stores/auth.js
@@ -0,0 +1,67 @@
+import { defineStore } from 'pinia'
+import axios from 'axios'
+import Cookies from 'js-cookie'
+
+export const useAuthStore = defineStore('auth', {
+  state: () => ({
+    user: null,
+    token: Cookies.get('token'),
+
+    // For admin impersonation
+    admin_token: Cookies.get('admin_token') ?? null
+  }),
+  getters: {
+    check: (state) => (state.user !== null && state.user !== undefined),
+    isImpersonating: (state) => (state.admin_token !== null && state.admin_token !== undefined)
+  },
+  actions: {
+    // Stores admin token temporarily for impersonation
+    startImpersonating () {
+      this.admin_token = this.token
+      Cookies.set('admin_token', this.token, { expires: 365 })
+    },
+    // Stop admin impersonation
+    stopImpersonating () {
+      this.token = this.admin_token
+      this.admin_token = null
+      Cookies.set('token', this.token, { expires: 365 })
+      Cookies.remove('admin_token')
+      this.fetchUser()
+    },
+
+    saveToken (token, remember) {
+      this.token = token
+      Cookies.set('token', token, { expires: remember ? 365 : null })
+    },
+
+    async fetchUser () {
+      try {
+        const { data } = await axios.get('/api/user')
+        this.user = data
+        return data
+      } catch (e) {
+        this.token = null
+        Cookies.remove('token')
+      }
+    },
+  
+    updateUser (payload) {
+      this.user = payload
+    },
+  
+    async logout () {
+      try {
+        await axios.post('/api/logout')
+      } catch (e) { }
+  
+      this.user = null
+      this.token = null
+      Cookies.remove('token')
+    },
+  
+    async fetchOauthUrl (provider) {
+      const { data } = await axios.post(`/api/oauth/${provider}`)
+      return data.url
+    }
+  }
+})
\ No newline at end of file
diff --git a/resources/js/stores/errors.js b/resources/js/stores/errors.js
new file mode 100644
index 000000000..6b22a90e1
--- /dev/null
+++ b/resources/js/stores/errors.js
@@ -0,0 +1,17 @@
+import { defineStore } from 'pinia'
+
+export const namespaced = true
+
+export const useErrorsStore = defineStore('errors', {
+  state: () => ({
+    content: null
+  }),
+  actions: {
+    set (error) {
+      this.content = error
+    },
+    clear () {
+      this.content = null
+    }
+  }
+})
\ No newline at end of file
diff --git a/resources/js/stores/forms.js b/resources/js/stores/forms.js
new file mode 100644
index 000000000..62ec89182
--- /dev/null
+++ b/resources/js/stores/forms.js
@@ -0,0 +1,83 @@
+import { defineStore } from 'pinia'
+import axios from 'axios'
+
+export const formsEndpoint = '/api/open/workspaces/{workspaceId}/forms'
+export const namespaced = true
+export let currentPage = 1
+
+export const useFormsStore = defineStore('forms', {
+  state: () => ({
+    content: [],
+    loading: false
+  }),
+  getters: {
+    getById: (state) => (id) => {
+      if (state.content.length === 0) return null
+      return state.content.find(item => item.id === id)
+    },
+    getBySlug: (state) => (slug) => {
+      if (state.content.length === 0) return null
+      return state.content.find(item => item.slug === slug)
+    },
+    getAllTags: (state) => {
+      if (state.content.length === 0) return []
+      let allTags = []
+      state.content.forEach(form => {
+        if(form.tags && form.tags.length > 0){
+          allTags = allTags.concat(form.tags)
+        }
+      })
+      return allTags.filter((item, i, ar) => ar.indexOf(item) === i)
+    }
+  },
+  actions: {
+    set (items) {
+      this.content = items
+    },
+    append (items) {
+      this.content = this.content.concat(items)
+    },
+    addOrUpdate (item) {
+      this.content = this.content.filter((val) => val.id !== item.id)
+      this.content.push(item)
+    },
+    remove (item) {
+      this.content = this.content.filter((val) => val.id !== item.id)
+    },
+    startLoading () {
+      this.loading = true
+    },
+    stopLoading () {
+      this.loading = false
+    },
+    resetState () {
+      this.set([])
+      this.stopLoading()
+      currentPage = 1
+    },
+    load (workspaceId) {
+      this.startLoading()
+      return axios.get(formsEndpoint.replace('{workspaceId}', workspaceId)+'?page='+currentPage).then((response) => {
+        if (currentPage == 1) {
+          this.set(response.data.data)
+        } else {
+          this.append(response.data.data)
+        }
+        if (currentPage < response.data.meta.last_page) {
+          currentPage += 1
+          this.load(workspaceId)
+        } else {
+          this.stopLoading()
+          currentPage = 1
+        }
+      })
+    },
+    loadIfEmpty (workspaceId) {
+      if (this.content.length === 0) {
+        return this.load(workspaceId)
+      }
+      this.stopLoading()
+      return Promise.resolve()
+    }
+  }
+})
\ No newline at end of file
diff --git a/resources/js/stores/records.js b/resources/js/stores/records.js
new file mode 100644
index 000000000..b5d7c1f93
--- /dev/null
+++ b/resources/js/stores/records.js
@@ -0,0 +1,49 @@
+import { defineStore } from 'pinia'
+
+export const namespaced = true
+
+/**
+ * Loads records from database
+ */
+export const useRecordsStore = defineStore('records', {
+  state: () => ({
+    content: [],
+    loading: false
+  }),
+  getters: {
+    getById: (state) => (id) => {
+      if (state.content.length === 0) return null
+      return state.content.find(item => item.submission_id === id)
+    }
+  },
+  actions: {
+    set (items) {
+      this.content = items
+    },
+    addOrUpdate (item) {
+      this.content = this.content.filter((val) => val.id !== item.id)
+      this.content.push(item)
+    },
+    remove (itemId) {
+      this.content = this.content.filter((val) => val.id !== itemId)
+    },
+    startLoading () {
+      this.loading = true
+    },
+    stopLoading () {
+      this.loading = false
+    },
+    resetState () {
+      this.set([])
+      this.stopLoading()
+    },
+    loadRecord (request) {
+      this.set([])
+      this.startLoading()
+      return request.then((data) => {
+        this.addOrUpdate(data)
+        this.stopLoading()
+      })
+    }
+  }
+})
\ No newline at end of file
diff --git a/resources/js/stores/templates.js b/resources/js/stores/templates.js
new file mode 100644
index 000000000..922f31f97
--- /dev/null
+++ b/resources/js/stores/templates.js
@@ -0,0 +1,120 @@
+import axios from 'axios'
+import { defineStore } from 'pinia'
+
+export const templatesEndpoint = '/api/templates'
+export const namespaced = true
+
+export const useTemplatesStore = defineStore('templates', {
+  state: () => ({
+    content: [],
+    industries: {},
+    types: {},
+    allLoaded: false,
+    loading: false
+  }),
+  getters: {
+    getBySlug: (state) => (slug) => {
+      if (state.content.length === 0) return null
+      return state.content.find(item => item.slug === slug)
+    },
+    getTemplateTypes: (state) => (slugs) => {
+      if (state.types.length === 0) return null
+      return Object.values(state.types).filter((val) => slugs.includes(val.slug)).map((item) => { return item.name })
+    },
+    getTemplateIndustries: (state) => (slugs) => {
+      if (state.industries.length === 0) return null
+      return Object.values(state.industries).filter((val) => slugs.includes(val.slug)).map((item) => { return item.name })
+    }
+  },
+  actions: {
+    set (items) {
+      this.content = items
+      this.allLoaded = true
+    },
+    append (items) {
+      const ids = items.map((item) => { return item.id })
+      this.content = this.content.filter((val) => !ids.includes(val.id))
+      this.content = this.content.concat(items)
+    },
+    addOrUpdate (item) {
+      this.content = this.content.filter((val) => val.id !== item.id)
+      this.content.push(item)
+    },
+    remove (item) {
+      this.content = this.content.filter((val) => val.id !== item.id)
+    },
+    startLoading () {
+      this.loading = true
+    },
+    stopLoading () {
+      this.loading = false
+    },
+    setAllLoaded (val) {
+      this.allLoaded = val
+    },
+    resetState () {
+      this.set([])
+      this.stopLoading()
+    },
+    loadTypesAndIndustries () {
+      if (Object.keys(this.industries).length === 0) {
+        import('@/data/forms/templates/industries.json').then((module) => {
+          this.industries = module.default
+        })
+      }
+      if (Object.keys(this.types).length === 0) {
+        import('@/data/forms/templates/types.json').then((module) => {
+          this.types = module.default
+        })
+      }
+    },
+    loadTemplate (slug) {
+      this.startLoading()
+      this.loadTypesAndIndustries()
+  
+      if (this.getBySlug(slug)) {
+        this.stopLoading()
+        return Promise.resolve()
+      }
+  
+      return axios.get(templatesEndpoint + '/' + slug).then((response) => {
+        this.addOrUpdate(response.data)
+        this.stopLoading()
+      }).catch((error) => {
+        this.stopLoading()
+      })
+    },
+    loadAll (options=null) {
+      this.startLoading()
+      this.loadTypesAndIndustries()
+  
+      // Prepare with options
+      let queryStr = ''
+      if(options !== null){
+        for (const [key, value] of Object.entries(options)) {
+          queryStr += '&' + encodeURIComponent(key) + '=' + encodeURIComponent(value)
+        }
+        queryStr = queryStr.slice(1)
+      }
+      return axios.get((queryStr) ? templatesEndpoint + '?' + queryStr : templatesEndpoint).then((response) => {
+        if(options !== null){
+          this.set(response.data)
+          this.setAllLoaded(false)
+        } else {
+          this.append(response.data)
+          this.setAllLoaded(true)
+        }
+        this.stopLoading()
+      }).catch((error) => {
+        this.stopLoading()
+      })
+    },
+    loadIfEmpty () {
+      if (!this.allLoaded) {
+        return this.loadAll()
+      }
+      this.stopLoading()
+      return Promise.resolve()
+    }
+  }
+})
diff --git a/resources/js/stores/working_form.js b/resources/js/stores/working_form.js
new file mode 100644
index 000000000..181180ce0
--- /dev/null
+++ b/resources/js/stores/working_form.js
@@ -0,0 +1,50 @@
+import { defineStore } from 'pinia'
+
+export const namespaced = true
+
+export const useWorkingFormStore = defineStore('working_form', {
+  state: () => ({
+    content: null,
+
+    // Field being edited
+    selectedFieldIndex: null,
+    showEditFieldSidebar: null,
+    showAddFieldSidebar: null
+  }),
+  actions: {
+    set (form) {
+      this.content = form
+    },
+    setProperties (properties) {
+      this.content.properties = properties
+    },
+    openSettingsForField (index) {
+      // If field is passed, compute index
+      if (typeof index === 'object') {
+        index = this.content.properties.findIndex(prop => prop.id === index.id)
+      }
+      this.selectedFieldIndex = index
+      this.showEditFieldSidebar = true
+      this.showAddFieldSidebar = false
+    },   
+    closeEditFieldSidebar () {
+      this.selectedFieldIndex = null
+      this.showEditFieldSidebar = false
+      this.showAddFieldSidebar = false
+    },
+    openAddFieldSidebar (index) {
+      // If field is passed, compute index
+      if (index !== null && typeof index === 'object') {
+        index = this.content.properties.findIndex(prop => prop.id === index.id)
+      }
+      this.selectedFieldIndex = index
+      this.showAddFieldSidebar = true
+      this.showEditFieldSidebar = false
+    },
+    closeAddFieldSidebar () {
+      this.selectedFieldIndex = null
+      this.showAddFieldSidebar = false
+      this.showEditFieldSidebar = false
+    }
+  }
+})
\ No newline at end of file
diff --git a/resources/js/stores/workspaces.js b/resources/js/stores/workspaces.js
new file mode 100644
index 000000000..96c4df6e8
--- /dev/null
+++ b/resources/js/stores/workspaces.js
@@ -0,0 +1,93 @@
+import axios from 'axios'
+import { defineStore } from 'pinia'
+
+export const namespaced = true
+export const workspaceEndpoint = '/api/open/workspaces/'
+
+const localStorageCurrentWorkspaceKey = 'currentWorkspace'
+
+export const useWorkspacesStore = defineStore('workspaces', {
+  state: () => ({
+    content: [],
+    currentId: null,
+    loading: false
+  }),
+  getters: {
+    getById: (state) => (id) => {
+      if (state.content.length === 0) return null
+      return state.content.find(item => item.id === id)
+    },
+    getCurrent: (state) => () => {
+      if (state.content.length === 0 || state.currentId === null) return null
+      return state.content.find(item => item.id === state.currentId)
+    }
+  },
+  actions: {
+    set (items) {
+      this.content = items
+      if (this.currentId == null && this.content.length > 0) {
+        // If one only, set it
+        if (this.content.length === 1) {
+          this.currentId = items[0].id
+          localStorage.setItem(localStorageCurrentWorkspaceKey, this.currentId)
+        } else if (localStorage.getItem(localStorageCurrentWorkspaceKey) && this.content.find(item => item.id === parseInt(localStorage.getItem(localStorageCurrentWorkspaceKey)))) {
+          // Check local storage for current workspace, or take first
+          this.currentId = parseInt(localStorage.getItem(localStorageCurrentWorkspaceKey))
+          localStorage.setItem(localStorageCurrentWorkspaceKey, this.currentId)
+        } else {
+          // Else, take first
+          this.currentId = items[0].id
+          localStorage.setItem(localStorageCurrentWorkspaceKey, this.currentId)
+        }
+      } else {
+        localStorage.removeItem(localStorageCurrentWorkspaceKey)
+      }
+    },
+    setCurrentId (id) {
+      this.currentId = id
+      localStorage.setItem(localStorageCurrentWorkspaceKey, id)
+    },
+    addOrUpdate (item) {
+      this.content = this.content.filter((val) => val.id !== item.id)
+      this.content.push(item)
+      if (this.currentId == null) {
+        this.currentId = item.id
+        localStorage.setItem(localStorageCurrentWorkspaceKey, this.currentId)
+      }
+    },
+    remove (itemId) {
+      this.content = this.content.filter((val) => val.id !== itemId)
+    },
+    startLoading () {
+      this.loading = true
+    },
+    stopLoading () {
+      this.loading = false
+    },
+    resetState () {
+      this.set([])
+      this.stopLoading()
+    },
+    load () {
+      this.set([])
+      this.startLoading()
+      return axios.get(workspaceEndpoint).then((response) => {
+        this.set(response.data)
+        this.stopLoading()
+      })
+    },
+    loadIfEmpty () {
+      if (this.content.length === 0) {
+        return this.load()
+      }
+      return Promise.resolve()
+    },
+    delete (id) {
+      this.startLoading()
+      return axios.delete(workspaceEndpoint + id).then((response) => {
+        this.remove(response.data.workspace_id)
+        this.stopLoading()
+      })
+    }
+  }
+})
\ No newline at end of file