diff --git a/quasar.config.js b/quasar.config.js
index b9d75477f..19e81bc13 100644
--- a/quasar.config.js
+++ b/quasar.config.js
@@ -78,6 +78,14 @@ module.exports = configure(function (ctx) {
},
port: 8080,
open: true, // opens browser window automatically
+ proxy: {
+ '/api': {
+ target: 'http://localhost:3000',
+ logLevel: 'debug',
+ changeOrigin: true,
+ secure: false,
+ },
+ },
},
// https://v2.quasar.dev/quasar-cli-webpack/quasar-config-js#Property%3A-framework
@@ -95,7 +103,7 @@ module.exports = configure(function (ctx) {
// directives: [],
// Quasar plugins
- plugins: [],
+ plugins: ['Notify', 'Dialog'],
},
// animations: 'all', // --- includes all animations
diff --git a/src/assets/logo.svg b/src/assets/logo.svg
new file mode 100644
index 000000000..1fae1108f
--- /dev/null
+++ b/src/assets/logo.svg
@@ -0,0 +1,70 @@
+
+
+
diff --git a/src/assets/logo_icon.svg b/src/assets/logo_icon.svg
new file mode 100644
index 000000000..b6fdcca4e
--- /dev/null
+++ b/src/assets/logo_icon.svg
@@ -0,0 +1,22 @@
+
+
+
\ No newline at end of file
diff --git a/src/assets/quasar-logo-vertical.svg b/src/assets/quasar-logo-vertical.svg
deleted file mode 100644
index 821083104..000000000
--- a/src/assets/quasar-logo-vertical.svg
+++ /dev/null
@@ -1,15 +0,0 @@
-
\ No newline at end of file
diff --git a/src/boot/axios.js b/src/boot/axios.js
index 7c9b94a7b..1962a452c 100644
--- a/src/boot/axios.js
+++ b/src/boot/axios.js
@@ -1,5 +1,7 @@
import { boot } from 'quasar/wrappers';
import axios from 'axios';
+import { useSession } from 'src/composables/useSession';
+
// Be careful when using SSR for cross-request state pollution
// due to creating a Singleton instance here;
@@ -8,6 +10,22 @@ import axios from 'axios';
// "export default () => {}" function below (which runs individually
// for each client)
const api = axios.create({ baseURL: 'https://api.example.com' });
+const { getToken } = useSession();
+
+axios.interceptors.request.use(
+ function (context) {
+ const token = getToken();
+
+ if (token.length && context.headers) {
+ context.headers.Authorization = token;
+ }
+
+ return context;
+ },
+ function (error) {
+ return Promise.reject(error);
+ }
+);
export default boot(({ app }) => {
// for use inside Vue files (Options API) through this.$axios and this.$api
diff --git a/src/boot/i18n.js b/src/boot/i18n.js
index ab6d345b5..aa450c279 100644
--- a/src/boot/i18n.js
+++ b/src/boot/i18n.js
@@ -4,7 +4,7 @@ import messages from 'src/i18n';
export default boot(({ app }) => {
const i18n = createI18n({
- locale: 'en-US',
+ locale: 'en',
messages,
});
diff --git a/src/components/EssentialLink.vue b/src/components/EssentialLink.vue
deleted file mode 100644
index 49aee346c..000000000
--- a/src/components/EssentialLink.vue
+++ /dev/null
@@ -1,41 +0,0 @@
-
-
-
-
-
-
-
- {{ title }}
- {{ caption }}
-
-
-
-
-
diff --git a/src/components/Navbar.vue b/src/components/Navbar.vue
new file mode 100644
index 000000000..d5382b264
--- /dev/null
+++ b/src/components/Navbar.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Salix
+
+
+
+
+
+
+
+ New customer
+
+
+ New ticket
+
+
+
+
+
+
+
+
+
+ Account
+
+
+
+
+
+
+
diff --git a/src/components/QuasarButton.vue b/src/components/QuasarButton.vue
deleted file mode 100644
index 8e2e33ce8..000000000
--- a/src/components/QuasarButton.vue
+++ /dev/null
@@ -1,12 +0,0 @@
-
-
-
-
-
diff --git a/src/components/QuasarDialog.vue b/src/components/QuasarDialog.vue
deleted file mode 100644
index 770dc3789..000000000
--- a/src/components/QuasarDialog.vue
+++ /dev/null
@@ -1,65 +0,0 @@
-
-
-
-
- {{ message }}
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/components/QuasarDrawer.vue b/src/components/QuasarDrawer.vue
deleted file mode 100644
index 5d85f72b4..000000000
--- a/src/components/QuasarDrawer.vue
+++ /dev/null
@@ -1,33 +0,0 @@
-
-
-
-
- Am I on screen?
-
-
-
-
-
diff --git a/src/components/QuasarPageSticky.vue b/src/components/QuasarPageSticky.vue
deleted file mode 100644
index f281a973a..000000000
--- a/src/components/QuasarPageSticky.vue
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
-
- {{ title }}
-
-
-
-
-
diff --git a/src/components/QuasarTooltip.vue b/src/components/QuasarTooltip.vue
deleted file mode 100644
index c4905667c..000000000
--- a/src/components/QuasarTooltip.vue
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
- Button
- Here I am!
-
-
-
-
diff --git a/src/components/UserPanel.vue b/src/components/UserPanel.vue
new file mode 100644
index 000000000..2e357698c
--- /dev/null
+++ b/src/components/UserPanel.vue
@@ -0,0 +1,104 @@
+
+
+
+
+
{{ t('components.userPanel.settings') }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ user.nickname }}
+
+
@{{ user.username }}
+
+
+
+
+
+
+
+
diff --git a/src/components/__tests__/QuasarButton.spec.js b/src/components/__tests__/QuasarButton.spec.js
deleted file mode 100644
index aabc1cf61..000000000
--- a/src/components/__tests__/QuasarButton.spec.js
+++ /dev/null
@@ -1,42 +0,0 @@
-import { mount } from '@cypress/vue';
-import QuasarButton from '../QuasarButton.vue';
-
-describe('QuasarButton', () => {
- it('renders a message', () => {
- const label = 'Hello there';
- mount(QuasarButton, {
- props: {
- label,
- },
- });
-
- cy.dataCy('button').should('contain', label);
- });
-
- it('renders another message', () => {
- const label = 'Will this work?';
- mount(QuasarButton, {
- props: {
- label,
- },
- });
-
- cy.dataCy('button').should('contain', label);
- });
-
- it('should have a `positive` color', () => {
- mount(QuasarButton);
-
- cy.dataCy('button').should('have.backgroundColor', 'var(--q-positive)').should('have.color', 'white');
- });
-
- it('should emit `test` upon click', () => {
- mount(QuasarButton);
-
- cy.dataCy('button')
- .click()
- .should(() => {
- expect(Cypress.vueWrapper.emitted('test')).to.have.length(1);
- });
- });
-});
diff --git a/src/components/__tests__/QuasarDialog.spec.js b/src/components/__tests__/QuasarDialog.spec.js
deleted file mode 100644
index 931e2916c..000000000
--- a/src/components/__tests__/QuasarDialog.spec.js
+++ /dev/null
@@ -1,24 +0,0 @@
-import { mount } from '@cypress/vue';
-import DialogWrapper from 'app/test/cypress/wrappers/DialogWrapper.vue';
-import QuasarDialog from '../QuasarDialog.vue';
-
-describe('QuasarDialog', () => {
- it('should show a dialog with a message', () => {
- const message = 'Hello, I am a dialog';
- mount(DialogWrapper, {
- props: {
- component: QuasarDialog,
- componentProps: {
- message,
- },
- },
- });
- cy.dataCy('dialog').should('exist').should('contain', message);
- });
-
- it('should close a dialog when clikcing ok', () => {
- // The dialog is still visible from the previous test
- cy.dataCy('dialog').should('exist').dataCy('ok-button').click();
- cy.dataCy('dialog').should('not.exist');
- });
-});
diff --git a/src/components/__tests__/QuasarDrawer.spec.js b/src/components/__tests__/QuasarDrawer.spec.js
deleted file mode 100644
index e6bbcc984..000000000
--- a/src/components/__tests__/QuasarDrawer.spec.js
+++ /dev/null
@@ -1,15 +0,0 @@
-import { mount } from '@cypress/vue';
-import LayoutContainer from 'app/test/cypress/wrappers/LayoutContainer.vue';
-import QuasarDrawer from '../QuasarDrawer.vue';
-
-describe('QuasarDrawer', () => {
- it('should show a drawer', () => {
- mount(LayoutContainer, {
- props: {
- component: QuasarDrawer,
- },
- });
- cy.dataCy('drawer').should('exist').dataCy('button').should('not.be.visible');
- cy.get('.q-scrollarea .scroll').scrollTo('bottom', { duration: 500 }).dataCy('button').should('be.visible');
- });
-});
diff --git a/src/components/__tests__/QuasarPageSticky.spec.js b/src/components/__tests__/QuasarPageSticky.spec.js
deleted file mode 100644
index 2e989a597..000000000
--- a/src/components/__tests__/QuasarPageSticky.spec.js
+++ /dev/null
@@ -1,22 +0,0 @@
-import { mount } from '@cypress/vue';
-import LayoutContainer from 'app/test/cypress/wrappers/LayoutContainer.vue';
-import QuasarPageSticky from '../QuasarPageSticky.vue';
-
-describe('QuasarPageSticky', () => {
- it('should show a sticky at the bottom-right of the page', () => {
- mount(LayoutContainer, {
- props: {
- component: QuasarPageSticky,
- title: 'Test',
- },
- });
-
- cy.dataCy('button')
- .should('be.visible')
- .should(($el) => {
- const rect = $el[0].getBoundingClientRect();
- expect(rect.bottom).to.equal(window.innerHeight - 18);
- expect(rect.right).to.equal(window.innerWidth - 18);
- });
- });
-});
diff --git a/src/components/__tests__/QuasarTooltip.spec.js b/src/components/__tests__/QuasarTooltip.spec.js
deleted file mode 100644
index f5941a31e..000000000
--- a/src/components/__tests__/QuasarTooltip.spec.js
+++ /dev/null
@@ -1,11 +0,0 @@
-import { mount } from '@cypress/vue';
-import QuasarTooltip from '../QuasarTooltip.vue';
-
-describe('QuasarTooltip', () => {
- it('should show a tooltip', () => {
- mount(QuasarTooltip);
-
- cy.dataCy('button').trigger('mouseover');
- cy.dataCy('tooltip').contains('Here I am!');
- });
-});
diff --git a/src/components/__tests__/UserPanel.spec.js b/src/components/__tests__/UserPanel.spec.js
new file mode 100644
index 000000000..de2962985
--- /dev/null
+++ b/src/components/__tests__/UserPanel.spec.js
@@ -0,0 +1,28 @@
+import { describe, expect, it, jest } from '@jest/globals';
+import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-unit-jest';
+import { mount } from '@vue/test-utils';
+import { i18n } from 'src/boot/i18n';
+import UserPanel from '../UserPanel.vue';
+
+// Specify here Quasar config you'll need to test your component
+installQuasarPlugin();
+const routerPushMock = jest.fn();
+
+jest.mock('vue-router', () => ({
+ useRouter: () => ({
+ push: routerPushMock,
+ }),
+}));
+
+describe('UserPanel', () => {
+ it('should have the function logout defined', () => {
+ const wrapper = mount(UserPanel, {
+ global: {
+ plugins: [i18n]
+ }
+ });
+ const { vm } = wrapper;
+
+ expect(vm.logout).toBeDefined();
+ });
+});
diff --git a/src/composables/useRole.js b/src/composables/useRole.js
new file mode 100644
index 000000000..e44827be1
--- /dev/null
+++ b/src/composables/useRole.js
@@ -0,0 +1,18 @@
+/* import store from '@/store';
+
+export function useRole() {
+ function hasAny(roles: string[]): boolean {
+ const roleStore: string[] = store.state.roles;
+
+ for (const role of roles) {
+ if (roleStore.indexOf(role) !== -1) return true;
+ }
+
+ return false;
+ }
+
+ return {
+ hasAny,
+ };
+}
+ */
diff --git a/src/composables/useSession.js b/src/composables/useSession.js
new file mode 100644
index 000000000..3a60c33b9
--- /dev/null
+++ b/src/composables/useSession.js
@@ -0,0 +1,45 @@
+import { useState } from './useState';
+
+export function useSession() {
+ function getToken() {
+ const localToken = localStorage.getItem('token');
+ const sessionToken = sessionStorage.getItem('token');
+
+ return localToken || sessionToken || '';
+ }
+
+ function setToken(data) {
+ if (data.keepLogin) {
+ localStorage.setItem('token', data.token);
+ } else {
+ sessionStorage.setItem('token', data.token);
+ }
+ }
+
+ function destroy() {
+ localStorage.removeItem('token');
+ sessionStorage.getItem('token');
+
+ const { setUser } = useState();
+
+ setUser({
+ id: 0,
+ username: '',
+ nickname: '',
+ });
+ }
+
+ function isLoggedIn() {
+ const localToken = localStorage.getItem('token');
+ const sessionToken = sessionStorage.getItem('token');
+
+ return !!(localToken || sessionToken);
+ }
+
+ return {
+ getToken,
+ setToken,
+ destroy,
+ isLoggedIn,
+ };
+}
diff --git a/src/composables/useState.js b/src/composables/useState.js
new file mode 100644
index 000000000..df121398e
--- /dev/null
+++ b/src/composables/useState.js
@@ -0,0 +1,46 @@
+import { ref, computed } from 'vue';
+
+const user = ref({
+ id: 0,
+ username: '',
+ nickname: '',
+});
+
+const roles = ref([]);
+
+export function useState() {
+ function getUser() {
+ return computed(() => {
+ return {
+ id: user.value.id,
+ username: user.value.username,
+ nickname: user.value.nickname,
+ };
+ });
+ }
+
+ function setUser(data) {
+ user.value = {
+ id: data.id,
+ username: data.username,
+ nickname: data.nickname,
+ };
+ }
+
+ function getRoles() {
+ return computed(() => {
+ return roles.value;
+ });
+ }
+
+ function setRoles(data) {
+ roles.value = data;
+ }
+
+ return {
+ getUser,
+ setUser,
+ getRoles,
+ setRoles,
+ };
+}
diff --git a/src/filters/index.js b/src/filters/index.js
new file mode 100644
index 000000000..24a25ad68
--- /dev/null
+++ b/src/filters/index.js
@@ -0,0 +1,5 @@
+import toLowerCase from './toLowerCase';
+
+export default {
+ toLowerCase,
+};
diff --git a/src/filters/toLowerCase.js b/src/filters/toLowerCase.js
new file mode 100644
index 000000000..c81b39423
--- /dev/null
+++ b/src/filters/toLowerCase.js
@@ -0,0 +1,3 @@
+export default function toLowerCase(value) {
+ return value.toLowerCase();
+}
diff --git a/src/i18n/en-US/index.js b/src/i18n/en-US/index.js
deleted file mode 100644
index 3601f69bc..000000000
--- a/src/i18n/en-US/index.js
+++ /dev/null
@@ -1,7 +0,0 @@
-// This is just an example,
-// so you can safely delete all default props below
-
-export default {
- failed: 'Action failed',
- success: 'Action was successful',
-};
diff --git a/src/i18n/en/index.js b/src/i18n/en/index.js
new file mode 100644
index 000000000..9df5cbf17
--- /dev/null
+++ b/src/i18n/en/index.js
@@ -0,0 +1,35 @@
+export default {
+ globals: {
+ lang: {
+ es: 'Spanish',
+ en: 'English',
+ },
+ },
+ errors: {
+ statusUnauthorized: 'Access denied',
+ statusInternalServerError: 'An internal server error has ocurred',
+ },
+ login: {
+ title: 'Login',
+ username: 'Username',
+ password: 'Password',
+ submit: 'Log in',
+ keepLogin: 'Keep me logged in',
+ loginSuccess: 'You have successfully logged in',
+ loginError: 'Invalid username or password',
+ },
+ customer: {},
+ components: {
+ topbar: {},
+ userPanel: {
+ settings: 'Settings',
+ logOut: 'Log Out',
+ },
+ },
+ pages: {
+ logIn: 'Log In',
+ dashboard: 'Dashboard',
+ customers: 'Customers',
+ list: 'List',
+ },
+};
diff --git a/src/i18n/es/index.js b/src/i18n/es/index.js
new file mode 100644
index 000000000..e0be0d849
--- /dev/null
+++ b/src/i18n/es/index.js
@@ -0,0 +1,29 @@
+export default {
+ globals: {
+ lang: {
+ es: 'Español',
+ en: 'Inglés',
+ },
+ },
+ errors: {
+ statusUnauthorized: 'Acceso denegado',
+ statusInternalServerError: 'Ha ocurrido un error interno del servidor',
+ },
+ login: {
+ title: 'Iniciar sesión',
+ username: 'Nombre de usuario',
+ password: 'Contraseña',
+ submit: 'Iniciar sesión',
+ keepLogin: 'Mantener sesión iniciada',
+ loginSuccess: 'Inicio de sesión correcto',
+ loginError: 'Nombre de usuario o contraseña incorrectos',
+ },
+ customer: {},
+ components: {
+ topbar: {},
+ userPanel: {
+ settings: 'Configuración',
+ logOut: 'Cerrar sesión',
+ },
+ },
+};
diff --git a/src/i18n/index.js b/src/i18n/index.js
index 3d51c7a85..7344be49a 100644
--- a/src/i18n/index.js
+++ b/src/i18n/index.js
@@ -1,5 +1,7 @@
-import enUS from './en-US';
+import en from './en';
+import es from './es';
export default {
- 'en-US': enUS,
+ en: en,
+ es: es,
};
diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue
index 48fb17ca0..e56ddc1ac 100644
--- a/src/layouts/MainLayout.vue
+++ b/src/layouts/MainLayout.vue
@@ -1,95 +1,89 @@
+
+
-
-
-
-
+
+
+
+
+
+
+
+
+
+ Dashboard
+
+
+
+
+
+ Customers
+
+
+
+
+
+ Tickets
+
+
+
+
+
- Quasar App
+ Invoice Out
+
- Quasar v{{ $q.version }}
-
-
+
+
+
+
-
-
- Essential Links
+ Catalog
+
-
-
+
+
+
+
+
+
+
+ Drafts
+
+
+
-
-
+
-
+
\ No newline at end of file
diff --git a/src/pages/Customer/Card/CustomerCard.vue b/src/pages/Customer/Card/CustomerCard.vue
new file mode 100644
index 000000000..6517a1f85
--- /dev/null
+++ b/src/pages/Customer/Card/CustomerCard.vue
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+ asd
+
+
+
diff --git a/src/pages/Customer/CustomerLayout.vue b/src/pages/Customer/CustomerLayout.vue
new file mode 100644
index 000000000..2785996d8
--- /dev/null
+++ b/src/pages/Customer/CustomerLayout.vue
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/pages/Customer/List.vue b/src/pages/Customer/List.vue
new file mode 100644
index 000000000..47960b007
--- /dev/null
+++ b/src/pages/Customer/List.vue
@@ -0,0 +1,143 @@
+
+
+
+
+
+
+
+
+
+ {{ customer.name }}
+ @{{ customer.username }}
+
+
+
+
+ Email
+ {{ customer.email }}
+
+
+
+
+ Phone
+ {{ customer.phone }}
+
+
+
+
+
+
+
+
+
+ Action 1
+
+
+ Action 2
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Address
+ Avenue 11
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/Dashboard/Dashboard.vue b/src/pages/Dashboard/Dashboard.vue
new file mode 100644
index 000000000..f47438953
--- /dev/null
+++ b/src/pages/Dashboard/Dashboard.vue
@@ -0,0 +1,85 @@
+
+
+
+
+
+ You have lost connection to the internet. This app is offline.
+
+
+
+
+
+
+
+
+
Responsive monitor
+
+
+
+ {{ slideText }}
+
+
+
+ {{ slideText }}
+
+
+
+ {{ slideText }}
+
+
+
+ {{ slideText }}
+
+
+
+
+
Responsive monitor
+
Dashboard page..
+
+
+
Responsive monitor
+
Dashboard page..
+
+
+
+
+
Responsive monitor
+
Dashboard page..
+
+
+
Responsive monitor
+
Dashboard page..
+
+
+
+
+
+
Responsive monitor
+
Dashboard page..
+
+
+
+
+
+
diff --git a/src/pages/IndexPage.vue b/src/pages/IndexPage.vue
deleted file mode 100644
index d1beaae57..000000000
--- a/src/pages/IndexPage.vue
+++ /dev/null
@@ -1,13 +0,0 @@
-
-
-
-
-
-
-
diff --git a/src/pages/Login/Login.vue b/src/pages/Login/Login.vue
new file mode 100644
index 000000000..9cd5f94c7
--- /dev/null
+++ b/src/pages/Login/Login.vue
@@ -0,0 +1,147 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/pages/Login/__tests__/Login.spec.js b/src/pages/Login/__tests__/Login.spec.js
new file mode 100644
index 000000000..7baf937d7
--- /dev/null
+++ b/src/pages/Login/__tests__/Login.spec.js
@@ -0,0 +1,66 @@
+import { jest, describe, expect, it } from '@jest/globals';
+import { mount } from '@vue/test-utils';
+import { installQuasarPlugin } from '@quasar/quasar-app-extension-testing-unit-jest';
+import { i18n } from 'src/boot/i18n';
+import { Notify } from 'quasar';
+import axios from 'axios';
+import Login from '../Login.vue';
+
+// Specify here Quasar config you'll need to test your component
+installQuasarPlugin({
+ plugins: {
+ Notify
+ }
+});
+const routerPushMock = jest.fn();
+
+jest.mock('vue-router', () => ({
+ useRouter: () => ({
+ push: routerPushMock,
+ }),
+}));
+
+
+describe('Login', () => {
+ it('should successfully set the token into session', async () => {
+ const wrapper = mount(Login, {
+ global: {
+ plugins: [i18n]
+ }
+ });
+ const { vm } = wrapper;
+
+ jest.spyOn(axios, 'post').mockResolvedValue({ data: { token: 'token' } });
+ jest.spyOn(vm.quasar, 'notify')
+
+ expect(vm.session.getToken()).toEqual('');
+
+ await vm.onSubmit();
+
+ expect(vm.session.getToken()).toEqual('token');
+ expect(vm.quasar.notify).toHaveBeenCalledWith(expect.objectContaining(
+ { 'type': 'positive' }
+ ));
+ vm.session.destroy();
+ });
+
+ it('should not set the token into session if any error occurred', async () => {
+ const wrapper = mount(Login, {
+ global: {
+ plugins: [i18n]
+ }
+ });
+ const { vm } = wrapper;
+
+ jest.spyOn(axios, 'post').mockRejectedValue(new Error('error'));
+ jest.spyOn(vm.quasar, 'notify')
+
+ expect(vm.session.getToken()).toEqual('');
+
+ await vm.onSubmit();
+
+ expect(vm.quasar.notify).toHaveBeenCalledWith(expect.objectContaining(
+ { 'type': 'negative' }
+ ));
+ });
+});
diff --git a/src/pages/ErrorNotFound.vue b/src/pages/NotFound.vue
similarity index 54%
rename from src/pages/ErrorNotFound.vue
rename to src/pages/NotFound.vue
index a1f75611d..65b91a3b8 100644
--- a/src/pages/ErrorNotFound.vue
+++ b/src/pages/NotFound.vue
@@ -5,15 +5,16 @@
Oops. Nothing here...
-
+
-
diff --git a/src/router/routes.js b/src/router/routes.js
index fe1db6000..f0d941d69 100644
--- a/src/router/routes.js
+++ b/src/router/routes.js
@@ -1,16 +1,49 @@
const routes = [
{
- path: '/',
- component: () => import('layouts/MainLayout.vue'),
- children: [{ path: '', component: () => import('pages/IndexPage.vue') }],
+ path: '/login',
+ name: 'Login',
+ meta: { title: 'logIn' },
+ component: () => import('../pages/Login/Login.vue'),
},
-
- // Always leave this as last one,
- // but you can also remove it
{
- path: '/:catchAll(.*)*',
- component: () => import('pages/ErrorNotFound.vue'),
+ path: '/',
+ name: 'Main',
+ component: () => import('../layouts/MainLayout.vue'),
+ redirect: { name: 'Dashboard' },
+ children: [
+ {
+ path: '/dashboard',
+ name: 'Dashboard',
+ meta: { title: 'dashboard' },
+ component: () => import('../pages/Dashboard/Dashboard.vue'),
+ },
+ {
+ path: '/customer',
+ name: 'Customer',
+ meta: { title: 'customers' },
+ component: () => import('../pages/Customer/CustomerLayout.vue'),
+ redirect: { name: 'List' },
+ children: [
+ {
+ path: 'list',
+ name: 'List',
+ meta: { title: 'list' },
+ component: () => import('../pages/Customer/List.vue'),
+ },
+ {
+ path: ':id',
+ name: 'Card',
+ component: () => import('../pages/Customer/Card/CustomerCard.vue'),
+ },
+ ],
+ },
+ {
+ path: '/:pathMatch(.*)*',
+ name: 'NotFound',
+ component: () => import('../pages/NotFound.vue'),
+ },
+ ],
},
];
-export default routes;
+export default routes;
\ No newline at end of file