diff --git a/package-lock.json b/package-lock.json
index d2a7c64..76ad679 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1753,63 +1753,6 @@
"integrity": "sha1-/q7SVZc9LndVW4PbwIhRpsY1IPo=",
"dev": true
},
- "ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "dev": true,
- "optional": true,
- "requires": {
- "color-convert": "^2.0.1"
- }
- },
- "chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "optional": true,
- "requires": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- }
- },
- "color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "color-name": "~1.1.4"
- }
- },
- "color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "dev": true,
- "optional": true
- },
- "has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "optional": true
- },
- "loader-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
- "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
- "dev": true,
- "optional": true,
- "requires": {
- "big.js": "^5.2.2",
- "emojis-list": "^3.0.0",
- "json5": "^2.1.2"
- }
- },
"ssri": {
"version": "8.0.1",
"resolved": "https://registry.nlark.com/ssri/download/ssri-8.0.1.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fssri%2Fdownload%2Fssri-8.0.1.tgz",
@@ -1818,28 +1761,6 @@
"requires": {
"minipass": "^3.1.1"
}
- },
- "supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "optional": true,
- "requires": {
- "has-flag": "^4.0.0"
- }
- },
- "vue-loader-v16": {
- "version": "npm:vue-loader@16.5.0",
- "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.5.0.tgz",
- "integrity": "sha512-WXh+7AgFxGTgb5QAkQtFeUcHNIEq3PGVQ8WskY5ZiFbWBkOwcCPRs4w/2tVyTbh2q6TVRlO3xfvIukUtjsu62A==",
- "dev": true,
- "optional": true,
- "requires": {
- "chalk": "^4.1.0",
- "hash-sum": "^2.0.0",
- "loader-utils": "^2.0.0"
- }
}
}
},
@@ -2432,6 +2353,14 @@
"integrity": "sha1-1h9G2DslGSUOJ4Ta9bCUeai0HFk=",
"dev": true
},
+ "axios": {
+ "version": "0.21.4",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz",
+ "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==",
+ "requires": {
+ "follow-redirects": "^1.14.0"
+ }
+ },
"babel-eslint": {
"version": "10.1.0",
"resolved": "https://registry.npm.taobao.org/babel-eslint/download/babel-eslint-10.1.0.tgz",
@@ -5537,8 +5466,7 @@
"follow-redirects": {
"version": "1.14.3",
"resolved": "https://registry.nlark.com/follow-redirects/download/follow-redirects-1.14.3.tgz",
- "integrity": "sha1-atp4EY2NJMruWVWVrM3ArGq9Ai4=",
- "dev": true
+ "integrity": "sha1-atp4EY2NJMruWVWVrM3ArGq9Ai4="
},
"for-in": {
"version": "1.0.2",
@@ -11411,6 +11339,87 @@
}
}
},
+ "vue-loader-v16": {
+ "version": "npm:vue-loader@16.7.0",
+ "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.7.0.tgz",
+ "integrity": "sha512-43I0grWtwSCE8fiH/hAwFK+6sNlmvDuHhXScYH8HVSVAMS81IM66tgUOcxbPCeqhhz/1BE51YPxX59eZKGallQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "chalk": "^4.1.0",
+ "hash-sum": "^2.0.0",
+ "loader-utils": "^2.0.0"
+ },
+ "dependencies": {
+ "ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "color-convert": "^2.0.1"
+ }
+ },
+ "chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ }
+ },
+ "color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "color-name": "~1.1.4"
+ }
+ },
+ "color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true,
+ "optional": true
+ },
+ "has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "optional": true
+ },
+ "loader-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
+ "integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ }
+ },
+ "supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "optional": true,
+ "requires": {
+ "has-flag": "^4.0.0"
+ }
+ }
+ }
+ },
"vue-meta": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/vue-meta/-/vue-meta-2.4.0.tgz",
diff --git a/package.json b/package.json
index aa05475..69fd989 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,7 @@
"lint": "vue-cli-service lint"
},
"dependencies": {
+ "axios": "^0.21.4",
"bootstrap": "^4.6.0",
"core-js": "^3.6.5",
"jquery": "^3.6.0",
diff --git a/src/abstraction/repository/authRepository.js b/src/abstraction/repository/authRepository.js
new file mode 100644
index 0000000..b0f728e
--- /dev/null
+++ b/src/abstraction/repository/authRepository.js
@@ -0,0 +1,36 @@
+import axios from "axios";
+import url from "@/router/url";
+import { setData } from "../resources/authResource";
+
+export default class AuthRepository {
+ async login(data) {
+ let json = setData(data);
+ let response = await axios.post(url("login"), json);
+ if (response.status === 200) {
+ return response.data.data;
+ }
+ }
+
+ async logout() {
+ let response = await axios.post(url("logout"));
+ if (response.status === 200) {
+ return true;
+ }
+ }
+
+ async register(data) {
+ let json = setData(data);
+ let response = await axios.post(url("register"), json);
+ if (response.status === 200) {
+ return response.data.data;
+ }
+ }
+
+ async resetPassword(data) {
+ let json = setData(data);
+ let response = await axios.post(url("resetPassword"), json);
+ if (response.status === 200) {
+ return response.data.data;
+ }
+ }
+}
diff --git a/src/abstraction/resources/authResource.js b/src/abstraction/resources/authResource.js
new file mode 100644
index 0000000..860befe
--- /dev/null
+++ b/src/abstraction/resources/authResource.js
@@ -0,0 +1,9 @@
+export const setData = (data) => ({
+ first_name: data.first_name,
+ last_name: data.last_name,
+ email: data.email,
+ username: data.username,
+ password: data.password,
+ password_confirmation: data.password_confirmation,
+ });
+
\ No newline at end of file
diff --git a/src/components/Global/Section/SideBar.vue b/src/components/Global/Section/SideBar.vue
new file mode 100644
index 0000000..f04df47
--- /dev/null
+++ b/src/components/Global/Section/SideBar.vue
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/main.js b/src/main.js
index 1e1db99..422662d 100644
--- a/src/main.js
+++ b/src/main.js
@@ -5,12 +5,15 @@ import vuetify from './plugins/vuetify';
import router from './router';
import './utils/GlobalComponents';
import "./styles/global.scss";
-import './mixins/Global.js'
+import './mixins/Global.js';
+import ApiService from '@/utils/axios/api';
+ApiService.init('https://www.champya-dev.ir');
+import '@/utils/axios/errorHandler';
Vue.config.productionTip = false
new Vue({
vuetify,
- store,
+ store,
router,
render: h => h(App)
}).$mount('#app')
diff --git a/src/router/url.js b/src/router/url.js
new file mode 100644
index 0000000..c6e05d8
--- /dev/null
+++ b/src/router/url.js
@@ -0,0 +1,7 @@
+import { urlGenerator } from "@/utils/urlGenerator";
+
+const urls = {
+ login: "auth/login"
+};
+
+export default urlGenerator(urls);
diff --git a/src/store/modules/auth/actions.js b/src/store/modules/auth/actions.js
new file mode 100644
index 0000000..32e9980
--- /dev/null
+++ b/src/store/modules/auth/actions.js
@@ -0,0 +1,33 @@
+import AuthRepository from "../../../abstraction/repository/authRepository";
+import {TokenStorage, UserStorage} from "@/utils/storage";
+import ApiService from "@/utils/axios/api";
+
+function setTokenHeader(commit, response) {
+ TokenStorage.saveToken(response.token);
+ UserStorage.save(response.user);
+ commit("SET_AUTH_USER", response.user);
+ ApiService.setAuthHeader();
+}
+
+export default {
+ async login({commit}, data) {
+ let repository = new AuthRepository();
+ const response = await repository.login(data);
+ if (response) {
+ setTokenHeader(commit, response);
+ return response;
+ }
+ },
+ async logout() {
+ let repository = new AuthRepository();
+ await repository.logout();
+ ApiService.removeAuthHeader();
+ TokenStorage.removeToken();
+ return true;
+ },
+ async register({commit}, data) {
+ let repository = new AuthRepository();
+ const response = await repository.register(data);
+ setTokenHeader(commit, response);
+ },
+};
diff --git a/src/store/modules/auth/getters.js b/src/store/modules/auth/getters.js
new file mode 100644
index 0000000..a3e43a1
--- /dev/null
+++ b/src/store/modules/auth/getters.js
@@ -0,0 +1,3 @@
+export default {
+ getAuthUser: (state) => state.user,
+};
diff --git a/src/store/modules/auth/mutations.js b/src/store/modules/auth/mutations.js
new file mode 100644
index 0000000..cbcf3cb
--- /dev/null
+++ b/src/store/modules/auth/mutations.js
@@ -0,0 +1,6 @@
+import Vue from "vue";
+export default {
+ SET_AUTH_USER(state, data) {
+ Vue.set(state, "user", data);
+ },
+};
diff --git a/src/store/modules/auth/state.js b/src/store/modules/auth/state.js
new file mode 100644
index 0000000..27e1e40
--- /dev/null
+++ b/src/store/modules/auth/state.js
@@ -0,0 +1,3 @@
+export default {
+ user: {},
+};
diff --git a/src/utils/axios/api.js b/src/utils/axios/api.js
new file mode 100644
index 0000000..9e7606d
--- /dev/null
+++ b/src/utils/axios/api.js
@@ -0,0 +1,28 @@
+import axios from 'axios'
+import {TokenStorage} from '../storage'
+
+const ApiService = {
+
+ init(baseURL = null) {
+ if (baseURL) {
+ axios.defaults.baseURL = baseURL;
+ } else if (process.env.MIX_PUSHER_APP_API) {
+ axios.defaults.baseURL = process.env.MIX_PUSHER_APP_API;
+ }
+
+ if (TokenStorage.getToken()) {
+ this.setAuthHeader();
+ }
+ },
+
+ setAuthHeader() {
+ axios.defaults.headers.common["Authorization"] = `Bearer ${TokenStorage.getToken()}`;
+ },
+
+ removeAuthHeader() {
+ axios.defaults.headers.common["Authorization"] = null;
+ },
+
+};
+
+export default ApiService;
diff --git a/src/utils/axios/errorHandler.js b/src/utils/axios/errorHandler.js
new file mode 100644
index 0000000..f97ab89
--- /dev/null
+++ b/src/utils/axios/errorHandler.js
@@ -0,0 +1,49 @@
+import axios from "axios";
+import store from "@/store";
+// import toast from "../toast";
+import Vue from "vue";
+import { TokenStorage } from "../storage";
+import ApiService from "./api";
+
+function errorResponseHandler(error) {
+ // check for errorHandle config
+ if (
+ Object.prototype.hasOwnProperty.call(error.config, "errorHandle") &&
+ error.config.errorHandle === false
+ ) {
+ return Promise.reject(error);
+ }
+ // if has response show the error
+ if (error.response) {
+ if (error.response.status === 401) {
+ TokenStorage.removeToken();
+ ApiService.removeAuthHeader();
+ store.commit('auth/logout', {}, { root: true });
+ window.location.href = '/';
+ // toast.error('Wrong username or password.', 'Error');
+ } else if (error.response.status === 422) {
+ if (typeof error.response.data.errors !== 'undefined') {
+ for (const key in error.response.data.errors) {
+ if (Object.prototype.hasOwnProperty.call(error.response.data.errors, key)) {
+ // toast.error(error.response.data.errors[key], 'Error');
+ }
+ }
+ }
+ } else if (error.response.status === 500) {
+ // toast.error('Server Error', 'Error');
+ }
+ }
+ return Promise.reject(error);
+}
+function successHandler(response) {
+ if (response.status === 200 || response.status === 201) {
+ if (typeof response.data.message !== 'undefined' && typeof response.data.message.content !== 'undefined') {
+ // toast.success(response.data.message.content, response.data.message.title || 'Success');
+ }
+ }
+ return response;
+}
+
+// apply interceptor on response
+axios.interceptors.response.use(successHandler, errorResponseHandler);
+Vue.prototype.$axios = axios;
diff --git a/src/utils/createFilterObject.js b/src/utils/createFilterObject.js
new file mode 100644
index 0000000..133d21a
--- /dev/null
+++ b/src/utils/createFilterObject.js
@@ -0,0 +1,70 @@
+const createFilterObject = filters => {
+ let filterObject = {};
+ for (const key in filters) {
+ if (Object.hasOwnProperty.call(filters, key)) {
+ if (filters[key] && typeof filters[key]["type"] !== "undefined") {
+ let filterValue = window[filters[key]["type"]](filters[key]);
+ if (filterValue) {
+ filterObject[key] = filterValue;
+ }
+ } else if (typeof filters[key] !== 'object' ) {
+ filterObject[key] = filters[key];
+ }
+ }
+ }
+ filters = {};
+ for (var filter in filterObject) {
+ if (Object.hasOwnProperty.call(filterObject, filter)) {
+ filters[`filters[${filter}]`] = filterObject[filter];
+ }
+ }
+ return filters;
+};
+window["between"] = function(filter) {
+ var value = null;
+ if (filter.val1 && filter.val2) {
+ value = `<${filter.val1},${filter.val2}>`;
+ } else if (filter.val1) {
+ filter.val = filter.val1;
+ value = window["greater"](filter);
+ } else if (filter.val2) {
+ filter.val = filter.val2;
+ value = window["less"](filter);
+ }
+ return value;
+};
+window["greater"] = function(filter) {
+ var value = null;
+ if (filter.val) {
+ value = `(ge)${filter.val}`;
+ }
+ return value;
+};
+window["less"] = function(filter) {
+ var value = null;
+ if (filter.val) {
+ value = `(le)${filter.val}`;
+ }
+ return value;
+};
+
+window["like"] = function(filter) {
+ var value = null;
+ if (filter.val !== null) {
+ value = `%${filter.val}%`;
+ }
+ return value;
+};
+window["in"] = function(filter) {
+ var value = null;
+ if (filter.val) {
+ if (Array.isArray(filter.val)) {
+ value = filter.val.join(",");
+ } else {
+ value = `${filter.val}`;
+ }
+ }
+ return value;
+};
+
+export default createFilterObject;
diff --git a/src/utils/objectToFormData.js b/src/utils/objectToFormData.js
new file mode 100644
index 0000000..388d08a
--- /dev/null
+++ b/src/utils/objectToFormData.js
@@ -0,0 +1,89 @@
+const isUndefined = (value) => value === undefined;
+
+const isNull = (value) => value === null;
+
+const isBoolean = (value) => typeof value === "boolean";
+
+const isObject = (value) => value === Object(value);
+
+const isArray = (value) => Array.isArray(value);
+
+const isDate = (value) => value instanceof Date;
+
+const isBlob = (value) =>
+ value &&
+ typeof value.size === "number" &&
+ typeof value.type === "string" &&
+ typeof value.slice === "function";
+
+const isFile = (value) =>
+ isBlob(value) &&
+ typeof value.name === "string" &&
+ (typeof value.lastModifiedDate === "object" ||
+ typeof value.lastModified === "number");
+
+const objectToFormData = (obj, cfg, fd, pre) => {
+ cfg = cfg || {};
+
+ cfg.indices = isUndefined(cfg.indices) ? true : cfg.indices;
+
+ cfg.nullsAsUndefineds = isUndefined(cfg.nullsAsUndefineds)
+ ? false
+ : cfg.nullsAsUndefineds;
+
+ cfg.booleansAsIntegers = isUndefined(cfg.booleansAsIntegers)
+ ? false
+ : cfg.booleansAsIntegers;
+
+ cfg.allowEmptyArrays = isUndefined(cfg.allowEmptyArrays)
+ ? true
+ : cfg.allowEmptyArrays;
+
+ fd = fd || new FormData();
+
+ if (isUndefined(obj)) {
+ return fd;
+ } else if (isNull(obj)) {
+ if (!cfg.nullsAsUndefineds) {
+ fd.append(pre, "");
+ }
+ } else if (isBoolean(obj)) {
+ if (cfg.booleansAsIntegers) {
+ fd.append(pre, obj ? 1 : 0);
+ } else {
+ fd.append(pre, obj);
+ }
+ } else if (isArray(obj)) {
+ if (obj.length) {
+ obj.forEach((value, index) => {
+ const key = pre + "[" + (cfg.indices ? index : "") + "]";
+
+ objectToFormData(value, cfg, fd, key);
+ });
+ } else if (cfg.allowEmptyArrays) {
+ fd.append(pre, []);
+ }
+ } else if (isDate(obj)) {
+ fd.append(pre, obj.toISOString());
+ } else if (isObject(obj) && !isFile(obj) && !isBlob(obj)) {
+ Object.keys(obj).forEach((prop) => {
+ const value = obj[prop];
+
+ if (isArray(value)) {
+ while (prop.length > 2 && prop.lastIndexOf("[]") === prop.length - 2) {
+ prop = prop.substring(0, prop.length - 2);
+ }
+ }
+
+ const key = pre ? pre + "[" + prop + "]" : prop;
+
+ objectToFormData(value, cfg, fd, key);
+ });
+ } else {
+ fd.append(pre, obj);
+ }
+
+ return fd;
+};
+
+export { objectToFormData };
diff --git a/src/utils/setQueriesObject.js b/src/utils/setQueriesObject.js
new file mode 100644
index 0000000..a4dc5bc
--- /dev/null
+++ b/src/utils/setQueriesObject.js
@@ -0,0 +1,35 @@
+import createFilterObject from "./createFilterObject";
+export const SetQueriesObject = ({ filters, sorts, pagination }) => {
+
+ let Query = {};
+
+ if (typeof filters === 'object') {
+ filters = createFilterObject(filters);
+ Query = {...Query, ...filters };
+ }
+
+ if (typeof sorts === 'string') {
+ sorts = sorts ? { 'sorts[]': sorts } : {};
+ Query = {...Query, ...sorts };
+ }
+
+ if (typeof pagination === 'object') {
+ pagination = {
+ per_page: pagination.itemsPerPage,
+ page: pagination.page
+ };
+ Query = {...Query, ...pagination };
+ }
+ return Query;
+};
+
+export const SetPagination = (paginate) => {
+ return {
+ page: paginate.current_page,
+ pageStop: paginate.to,
+ pageStart: paginate.from,
+ pageCount: paginate.last_page,
+ itemsLength: paginate.total,
+ itemsPerPage: paginate.per_page,
+ }
+};
diff --git a/src/utils/storage.js b/src/utils/storage.js
new file mode 100644
index 0000000..f204d5d
--- /dev/null
+++ b/src/utils/storage.js
@@ -0,0 +1,47 @@
+import qs from "qs";
+
+const TOKEN_KEY = "access_token";
+const USER = "user";
+/**
+ * Manage the how Access Tokens are being stored and retreived from storage.
+ *
+ * Current implementation stores to localStorage. Local Storage should always be
+ * accessed through this instace.
+ **/
+const TokenStorage = {
+ getToken() {
+ return localStorage.getItem(TOKEN_KEY);
+ },
+
+ saveToken(accessToken = null) {
+ localStorage.setItem(TOKEN_KEY, accessToken);
+ },
+
+ removeToken() {
+ localStorage.removeItem(TOKEN_KEY);
+ },
+
+ hasToken() {
+ return localStorage.getItem(TOKEN_KEY) ? true : false;
+ },
+};
+
+const UserStorage = {
+ get() {
+ if (localStorage.getItem(USER)) {
+ return qs.parse(localStorage.getItem(USER));
+ }
+ return null;
+ },
+
+ save(user = null) {
+ user = qs.stringify(user);
+ localStorage.setItem(USER, user);
+ },
+
+ remove() {
+ localStorage.removeItem(USER);
+ },
+};
+
+export { TokenStorage, UserStorage };
diff --git a/src/utils/urlGenerator.js b/src/utils/urlGenerator.js
new file mode 100644
index 0000000..1c83ee8
--- /dev/null
+++ b/src/utils/urlGenerator.js
@@ -0,0 +1,24 @@
+const urlGenerator = (urls) => {
+ return function(routeAddress, parameters) {
+ let urlPath = urls[routeAddress].split("/");
+ let newPath = [];
+ for (const iterator of urlPath) {
+ if (iterator.startsWith(":")) {
+ if (iterator.endsWith("?")) {
+ if (Object.prototype.hasOwnProperty.call(parameters, iterator.slice(1, -1))) {
+ newPath.push(parameters[iterator.slice(1, -1)]);
+ }
+ } else {
+ newPath.push(parameters[iterator.slice(1)]);
+ }
+ } else {
+ newPath.push(iterator);
+ }
+ }
+ return '/api/' + newPath.join("/");
+ }
+};
+
+export {
+ urlGenerator
+}
diff --git a/src/views/Login.vue b/src/views/Login.vue
index 5988111..6ebc911 100644
--- a/src/views/Login.vue
+++ b/src/views/Login.vue
@@ -20,7 +20,8 @@
placeholder="your email address"
label="your email address"
class="no-error-msg"
-
+ v-model="form.email"
+ dark
>
@@ -33,7 +34,8 @@
:type="showPassword ? 'text' : 'password'"
@click:append="showPassword = !showPassword"
:append-icon="showPassword ? 'WMi-eye-off' : 'WMi-eye'"
-
+ v-model="form.password"
+ dark
>
@@ -45,7 +47,8 @@
class="custom-btn w-100"
height="25"
:text-mode="true"
- text="sign in as "
+ text="sign in"
+ @click.native="login"
/>
@@ -90,12 +93,23 @@
\ No newline at end of file
diff --git a/vue.config.js b/vue.config.js
index 2ae460b..061635e 100644
--- a/vue.config.js
+++ b/vue.config.js
@@ -1,5 +1,14 @@
module.exports = {
transpileDependencies: [
'vuetify'
- ]
+ ],
+ configureWebpack: {
+ resolve: {
+ alias: {
+ '@Assets': path.resolve(__dirname, 'src/assets'),
+ '@Styles': path.resolve(__dirname, 'src/styles'),
+ '@': path.resolve(__dirname, 'src/')
+ },
+ },
+ }
}