sajjad_talkhabi 3 years ago
parent 6c5eacd88d
commit a842fa3ad7

171
package-lock.json generated

@ -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",

@ -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",

@ -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;
}
}
}

@ -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,
});

@ -0,0 +1,40 @@
<template>
<div class="h-100">
<main-back height="100%">
<div class="mt-16">
<ul class="pl-0 ml-0">
<template>
<MenuItem :active="true" text="Home" link="dashboard" />
<MenuItem text="my profile" link="profile" />
<MenuItem text="my bookmarks" link="dashboard" />
<MenuItem text="programs" link="programs" />
<MenuItem text="users" link="users" />
<MenuItem text="products" link="products" />
<MenuItem text="workouts" link="workouts" />
</template>
<template>
<MenuItem :active="true" text="Home" link="dashboardTrainee" />
<MenuItem text="my profile" link="profile" />
<MenuItem text="my programs" link="trainPrograms" />
<MenuItem text="my bookmarks" link="bookmarks" />
</template>
<template>
<MenuItem :active="true" text="Home" link="dashboardTrainer" />
<MenuItem text="my profile" link="profile" />
<MenuItem text="my programs" link="trainPrograms" />
<MenuItem text="my trainees" link="users" />
<MenuItem text="my bookmarks" link="bookmarks" />
</template>
</ul>
</div>
</main-back>
</div>
</template>
<script>
import MenuItem from "../Global/Section/MenuItem.vue";
export default {
components: {
MenuItem,
},
};
</script>

@ -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')

@ -0,0 +1,7 @@
import { urlGenerator } from "@/utils/urlGenerator";
const urls = {
login: "auth/login"
};
export default urlGenerator(urls);

@ -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);
},
};

@ -0,0 +1,3 @@
export default {
getAuthUser: (state) => state.user,
};

@ -0,0 +1,6 @@
import Vue from "vue";
export default {
SET_AUTH_USER(state, data) {
Vue.set(state, "user", data);
},
};

@ -0,0 +1,3 @@
export default {
user: {},
};

@ -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;

@ -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;

@ -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;

@ -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 };

@ -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,
}
};

@ -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 };

@ -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
}

@ -20,7 +20,8 @@
placeholder="your email address"
label="your email address"
class="no-error-msg"
v-model="form.email"
dark
></v-text-field>
</v-col>
</v-row>
@ -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
></v-text-field>
</v-col>
</v-row>
@ -45,7 +47,8 @@
class="custom-btn w-100"
height="25"
:text-mode="true"
text="sign in as "
text="sign in"
@click.native="login"
/></router-link>
</div>
</v-col>
@ -90,12 +93,23 @@
</template>
<script>
import AuthBasic from "../components/Global/Section/AuthBasic.vue";
import { mapActions } from "vuex";
export default {
components: {
AuthBasic,
},
data: () => ({
showPassword: false,
form: {},
}),
methods: {
...mapActions("auth", ["login"]),
async doLogin() {
const response = await this.login(this.form);
if (response) {
this.$router.push(this.$route.query.redirect || "/");
}
},
},
};
</script>

@ -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/')
},
},
}
}

Loading…
Cancel
Save