docs: configurando deploy via ssh para angular
This commit is contained in:
16
.editorconfig
Normal file
16
.editorconfig
Normal file
@@ -0,0 +1,16 @@
|
||||
# Editor configuration, see https://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.ts]
|
||||
quote_type = single
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
49
.gitignore
vendored
Normal file
49
.gitignore
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
/dist
|
||||
/tmp
|
||||
/out-tsc
|
||||
# Only exists if Bazel was run
|
||||
/bazel-out
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
|
||||
# profiling files
|
||||
chrome-profiler-events*.json
|
||||
speed-measure-plugin*.json
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
.history/*
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
*.rar
|
||||
|
||||
.vercel
|
||||
148
angular.json
Normal file
148
angular.json
Normal file
@@ -0,0 +1,148 @@
|
||||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"sales": {
|
||||
"projectType": "application",
|
||||
"schematics": {"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
}},
|
||||
"root": "",
|
||||
"sourceRoot": "src",
|
||||
"prefix": "app",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-devkit/build-angular:browser",
|
||||
"options": {
|
||||
"outputPath": "dist/sales",
|
||||
"index": "src/index.html",
|
||||
"main": "src/main.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"aot": true,
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets",
|
||||
"src/assets/web.config",
|
||||
"src/assets/banners",
|
||||
"src/assets/icones",
|
||||
"src/assets/img"
|
||||
],
|
||||
"styles": [
|
||||
{
|
||||
"input": "node_modules/bootstrap/dist/css/bootstrap.min.css"
|
||||
},
|
||||
"node_modules/bootstrap-icons/font/bootstrap-icons.css",
|
||||
"node_modules/@progress/kendo-theme-bootstrap/dist/all.css",
|
||||
"src/styles.css",
|
||||
"src/styles-menu.css"
|
||||
],
|
||||
"scripts": [
|
||||
"node_modules/bootstrap/dist/js/bootstrap.bundle.min.js",
|
||||
"node_modules/jquery/dist/jquery.min.js"
|
||||
]
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"fileReplacements": [
|
||||
{
|
||||
"replace": "src/environments/environment.ts",
|
||||
"with": "src/environments/environment.prod.ts"
|
||||
}
|
||||
],
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"extractCss": true,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "10mb",
|
||||
"maximumError": "12mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "10kb",
|
||||
"maximumError": "12kb"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-devkit/build-angular:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "sales:build"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "sales:build:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"extract-i18n": {
|
||||
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||||
"options": {
|
||||
"browserTarget": "sales:build"
|
||||
}
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-devkit/build-angular:karma",
|
||||
"options": {
|
||||
"main": "src/test.ts",
|
||||
"polyfills": "src/polyfills.ts",
|
||||
"tsConfig": "tsconfig.spec.json",
|
||||
"karmaConfig": "karma.conf.js",
|
||||
"assets": [
|
||||
"src/favicon.ico",
|
||||
"src/assets",
|
||||
"src/assets/web.config",
|
||||
"src/assets/banners",
|
||||
"src/assets/icones",
|
||||
"src/assets/img"
|
||||
],
|
||||
"styles": [
|
||||
"node_modules/bootstrap/dist/css/bootstrap.min.css",
|
||||
"node_modules/bootstrap-icons/font/bootstrap-icons.css",
|
||||
"node_modules/line-awesome/dist/line-awesome/css/line-awesome.min.css",
|
||||
"src/styles.css",
|
||||
"src/styles-menu.css"
|
||||
],
|
||||
"scripts": ["node_modules/jquery/dist/jquery.min.js"]
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"builder": "@angular-devkit/build-angular:tslint",
|
||||
"options": {
|
||||
"tsConfig": [
|
||||
"tsconfig.app.json",
|
||||
"tsconfig.spec.json",
|
||||
"e2e/tsconfig.json"
|
||||
],
|
||||
"exclude": [
|
||||
"**/node_modules/**"
|
||||
]
|
||||
}
|
||||
},
|
||||
"e2e": {
|
||||
"builder": "@angular-devkit/build-angular:protractor",
|
||||
"options": {
|
||||
"protractorConfig": "e2e/protractor.conf.js",
|
||||
"devServerTarget": "sales:serve"
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"devServerTarget": "sales:serve:production"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"defaultProject": "sales"
|
||||
}
|
||||
12
browserslist
Normal file
12
browserslist
Normal file
@@ -0,0 +1,12 @@
|
||||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
> 0.5%
|
||||
last 2 versions
|
||||
Firefox ESR
|
||||
not dead
|
||||
not IE 9-11 # For IE 9-11 support, remove 'not'.
|
||||
32
e2e/protractor.conf.js
Normal file
32
e2e/protractor.conf.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// @ts-check
|
||||
// Protractor configuration file, see link for more information
|
||||
// https://github.com/angular/protractor/blob/master/lib/config.ts
|
||||
|
||||
const { SpecReporter } = require('jasmine-spec-reporter');
|
||||
|
||||
/**
|
||||
* @type { import("protractor").Config }
|
||||
*/
|
||||
exports.config = {
|
||||
allScriptsTimeout: 11000,
|
||||
specs: [
|
||||
'./src/**/*.e2e-spec.ts'
|
||||
],
|
||||
capabilities: {
|
||||
browserName: 'chrome'
|
||||
},
|
||||
directConnect: true,
|
||||
baseUrl: 'http://localhost:4200/',
|
||||
framework: 'jasmine',
|
||||
jasmineNodeOpts: {
|
||||
showColors: true,
|
||||
defaultTimeoutInterval: 30000,
|
||||
print: function() {}
|
||||
},
|
||||
onPrepare() {
|
||||
require('ts-node').register({
|
||||
project: require('path').join(__dirname, './tsconfig.json')
|
||||
});
|
||||
jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
|
||||
}
|
||||
};
|
||||
23
e2e/src/app.e2e-spec.ts
Normal file
23
e2e/src/app.e2e-spec.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { AppPage } from './app.po';
|
||||
import { browser, logging } from 'protractor';
|
||||
|
||||
describe('workspace-project App', () => {
|
||||
let page: AppPage;
|
||||
|
||||
beforeEach(() => {
|
||||
page = new AppPage();
|
||||
});
|
||||
|
||||
it('should display welcome message', () => {
|
||||
page.navigateTo();
|
||||
expect(page.getTitleText()).toEqual('sales app is running!');
|
||||
});
|
||||
|
||||
afterEach(async () => {
|
||||
// Assert that there are no errors emitted from the browser
|
||||
const logs = await browser.manage().logs().get(logging.Type.BROWSER);
|
||||
expect(logs).not.toContain(jasmine.objectContaining({
|
||||
level: logging.Level.SEVERE,
|
||||
} as logging.Entry));
|
||||
});
|
||||
});
|
||||
11
e2e/src/app.po.ts
Normal file
11
e2e/src/app.po.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { browser, by, element } from 'protractor';
|
||||
|
||||
export class AppPage {
|
||||
navigateTo(): Promise<unknown> {
|
||||
return browser.get(browser.baseUrl) as Promise<unknown>;
|
||||
}
|
||||
|
||||
getTitleText(): Promise<string> {
|
||||
return element(by.css('app-root .content span')).getText() as Promise<string>;
|
||||
}
|
||||
}
|
||||
13
e2e/tsconfig.json
Normal file
13
e2e/tsconfig.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out-tsc/e2e",
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"types": [
|
||||
"jasmine",
|
||||
"jasminewd2",
|
||||
"node"
|
||||
]
|
||||
}
|
||||
}
|
||||
38
gitea/deploy-ssh.yaml
Normal file
38
gitea/deploy-ssh.yaml
Normal file
@@ -0,0 +1,38 @@
|
||||
name: Deploy Angular via SSH
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup Node 16
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
|
||||
- name: Install and Build
|
||||
run: |
|
||||
npm install --legacy-peer-deps
|
||||
npm run build -- --prod
|
||||
|
||||
- name: Transferir arquivos via SCP
|
||||
uses: https://github.com/appleboy/scp-action@master
|
||||
with:
|
||||
host: ${{ secrets.REMOTE_HOST }}
|
||||
username: ${{ secrets.REMOTE_USER }}
|
||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
source: "dist/"
|
||||
target: "/var/www/html/vendaweb-frontend"
|
||||
strip_components: 1
|
||||
|
||||
- name: Reiniciar Nginx Remoto
|
||||
uses: https://github.com/appleboy/ssh-action@master
|
||||
with:
|
||||
host: ${{ secrets.REMOTE_HOST }}
|
||||
username: ${{ secrets.REMOTE_USER }}
|
||||
key: ${{ secrets.SSH_PRIVATE_KEY }}
|
||||
script: |
|
||||
sudo systemctl reload nginx
|
||||
32
karma.conf.js
Normal file
32
karma.conf.js
Normal file
@@ -0,0 +1,32 @@
|
||||
// Karma configuration file, see link for more information
|
||||
// https://karma-runner.github.io/1.0/config/configuration-file.html
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: '',
|
||||
frameworks: ['jasmine', '@angular-devkit/build-angular'],
|
||||
plugins: [
|
||||
require('karma-jasmine'),
|
||||
require('karma-chrome-launcher'),
|
||||
require('karma-jasmine-html-reporter'),
|
||||
require('karma-coverage-istanbul-reporter'),
|
||||
require('@angular-devkit/build-angular/plugins/karma')
|
||||
],
|
||||
client: {
|
||||
clearContext: false // leave Jasmine Spec Runner output visible in browser
|
||||
},
|
||||
coverageIstanbulReporter: {
|
||||
dir: require('path').join(__dirname, './coverage/sales'),
|
||||
reports: ['html', 'lcovonly', 'text-summary'],
|
||||
fixWebpackSourcePaths: true
|
||||
},
|
||||
reporters: ['progress', 'kjhtml'],
|
||||
port: 9876,
|
||||
colors: true,
|
||||
logLevel: config.LOG_INFO,
|
||||
autoWatch: true,
|
||||
browsers: ['Chrome'],
|
||||
singleRun: false,
|
||||
restartOnFileChange: true
|
||||
});
|
||||
};
|
||||
1
kendo-ui-license.txt
Normal file
1
kendo-ui-license.txt
Normal file
@@ -0,0 +1 @@
|
||||
eyJhbGciOiJSUzI1NiIsInR5cCI6IkxJQyJ9.eyJwcm9kdWN0cyI6W3sidHJpYWwiOnRydWUsImNvZGUiOiJLRU5ET1VJQU5HVUxBUiIsImxpY2Vuc2VFeHBpcmF0aW9uRGF0ZSI6MTYyMjc5NTQwMX1dLCJpbnRlZ3JpdHkiOiJVZ3JzZnhGQ0tjcExXQlY1Wm5UV3RRMXNEc1U9IiwibGljZW5zZUhvbGRlciI6ImVkdWFyZG8uZXN0ZXZhb0BhcHBzb2x1dGkuY29tLmJyIiwiaWF0IjoxNjIwODM0NDQ0LCJhdWQiOiJlZHVhcmRvLmVzdGV2YW9AYXBwc29sdXRpLmNvbS5iciJ9.FkYEcMVlG6LO6oGZiBC6yuHBiVXPm4ebPBeLmZ-r71xIZyGwzf1NIERIbDx9akyQXVSup9vST7nx5SIfIBYopkeWYBHLv6ps7-_omU0PI8T6lRw1QMIhqJ4qMVglUwR7vaQssPYOkJUZXJ6PJxDg-AJSRgc1mpWmErjyqpC0rxMlpAJCJZNP21OSithU4MEwYCBS3O-MaN8JhsMzg6z0cBKHvYsrPFvubUDBWBcwj4wEPPEGv1f7QVpglZME4Z7ZIXvJT9bEQC71OGa9Y7vjyuWBsStl0N3a8GMOhxks2semBHsRv7zb4ZMaRouqK2ZOHT6tdjhD5imWxz1_nIDvPw
|
||||
38395
package-lock.json
generated
Normal file
38395
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
105
package.json
Normal file
105
package.json
Normal file
@@ -0,0 +1,105 @@
|
||||
{
|
||||
"name": "sales",
|
||||
"version": "0.0.0",
|
||||
"scripts": {
|
||||
"ng": "ng",
|
||||
"start": "ng serve --host 0.0.0.0",
|
||||
"build": "ng build --prod && npx kendo-ui-license activate",
|
||||
"test": "ng test",
|
||||
"lint": "ng lint",
|
||||
"e2e": "ng e2e"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@agm/core": "^1.1.0",
|
||||
"@angular/animations": "^9.1.13",
|
||||
"@angular/common": "^9.1.13",
|
||||
"@angular/compiler": "~9.1.13",
|
||||
"@angular/core": "^9.1.13",
|
||||
"@angular/fire": "^6.1.5",
|
||||
"@angular/forms": "^9.1.13",
|
||||
"@angular/localize": "^9.1.13",
|
||||
"@angular/platform-browser": "~9.1.13",
|
||||
"@angular/platform-browser-dynamic": "~9.1.13",
|
||||
"@angular/router": "~9.1.13",
|
||||
"@ngrx/effects": "^9.2.1",
|
||||
"@ngrx/store": "^9.2.1",
|
||||
"@ngrx/store-devtools": "^12.0.0",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@progress/kendo-angular-barcodes": "^1.0.0",
|
||||
"@progress/kendo-angular-buttons": "^7.0.2",
|
||||
"@progress/kendo-angular-charts": "^6.0.1",
|
||||
"@progress/kendo-angular-common": "^2.0.0",
|
||||
"@progress/kendo-angular-dateinputs": "^6.0.0",
|
||||
"@progress/kendo-angular-dialog": "^6.0.1",
|
||||
"@progress/kendo-angular-dropdowns": "^6.0.1",
|
||||
"@progress/kendo-angular-excel-export": "^4.0.3",
|
||||
"@progress/kendo-angular-gauges": "^4.1.3",
|
||||
"@progress/kendo-angular-grid": "^6.0.1",
|
||||
"@progress/kendo-angular-icons": "^0.4.5",
|
||||
"@progress/kendo-angular-indicators": "^1.1.2",
|
||||
"@progress/kendo-angular-inputs": "^8.0.9",
|
||||
"@progress/kendo-angular-intl": "^3.0.0",
|
||||
"@progress/kendo-angular-l10n": "^3.0.0",
|
||||
"@progress/kendo-angular-label": "^3.1.2",
|
||||
"@progress/kendo-angular-layout": "^6.4.2",
|
||||
"@progress/kendo-angular-listview": "^3.0.0",
|
||||
"@progress/kendo-angular-menu": "^3.0.4",
|
||||
"@progress/kendo-angular-navigation": "^1.1.4",
|
||||
"@progress/kendo-angular-notification": "^3.0.5",
|
||||
"@progress/kendo-angular-pager": "^3.0.1",
|
||||
"@progress/kendo-angular-pdf-export": "^3.0.3",
|
||||
"@progress/kendo-angular-popup": "^4.0.0",
|
||||
"@progress/kendo-angular-progressbar": "^2.0.3",
|
||||
"@progress/kendo-angular-scrollview": "^4.1.3",
|
||||
"@progress/kendo-angular-tooltip": "^3.1.5",
|
||||
"@progress/kendo-angular-treeview": "^6.0.0",
|
||||
"@progress/kendo-data-query": "^1.5.5",
|
||||
"@progress/kendo-drawing": "^1.1.2",
|
||||
"@progress/kendo-licensing": "^1.0.2",
|
||||
"@progress/kendo-svg-icons": "^0.1.2",
|
||||
"@progress/kendo-theme-bootstrap": "^5.1.1",
|
||||
"@progress/kendo-theme-default": "^5.1.1",
|
||||
"bootstrap": "^5.0.0-beta3",
|
||||
"bootstrap-icons": "^1.7.2",
|
||||
"chart.js": "^2.9.4",
|
||||
"cldr-data": "^36.0.1",
|
||||
"firebase": "^8.6.2",
|
||||
"hammerjs": "^2.0.0",
|
||||
"jwt-decode": "^3.1.2",
|
||||
"line-awesome": "^1.3.0",
|
||||
"lottie-web": "^5.12.2",
|
||||
"ng2-charts": "^2.3.0",
|
||||
"ngx-bootstrap": "^8.0.0",
|
||||
"ngx-currency": "^2.5.3",
|
||||
"ngx-lottie": "^7.0.3",
|
||||
"rxjs": "^6.5.5",
|
||||
"stimulsoft-viewer-angular": "^2020.5.2",
|
||||
"tslib": "^1.10.0",
|
||||
"zone.js": "~0.10.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "~0.901.15",
|
||||
"@angular/cli": "~9.1.15",
|
||||
"@angular/compiler-cli": "~9.1.13",
|
||||
"@types/jasmine": "~3.5.0",
|
||||
"@types/jasminewd2": "~2.0.3",
|
||||
"@types/jquery": "^3.5.5",
|
||||
"@types/node": "^12.11.1",
|
||||
"codelyzer": "^5.1.2",
|
||||
"install": "^0.13.0",
|
||||
"jasmine-core": "^3.5.0",
|
||||
"jasmine-spec-reporter": "~4.2.1",
|
||||
"jquery": "^3.6.0",
|
||||
"karma": "^5.0.9",
|
||||
"karma-chrome-launcher": "^3.1.1",
|
||||
"karma-coverage-istanbul-reporter": "~2.1.0",
|
||||
"karma-jasmine": "^3.0.3",
|
||||
"karma-jasmine-html-reporter": "^1.7.0",
|
||||
"npm": "^7.13.0",
|
||||
"protractor": "~7.0.0",
|
||||
"ts-node": "~8.3.0",
|
||||
"tslint": "~6.1.0",
|
||||
"typescript": "^3.8.3"
|
||||
}
|
||||
}
|
||||
30
src/app/admin/admin.module.ts
Normal file
30
src/app/admin/admin.module.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { AuthGuard } from '../guards/auth.guard';
|
||||
import { KendoModule } from '../shared/kendo.module';
|
||||
import { LottieModule } from 'ngx-lottie';
|
||||
import player from 'lottie-web';
|
||||
import { PermissionUserComponent } from './permission-user/permission-user.component';
|
||||
import { ComponentModule } from '../components/component.module'; // Importando o módulo correto
|
||||
|
||||
export function playerFactory() {
|
||||
return player;
|
||||
}
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: 'permission-user', component: PermissionUserComponent, canActivate: [AuthGuard] },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild(routes),
|
||||
KendoModule,
|
||||
LottieModule.forRoot({ player: playerFactory }),
|
||||
ComponentModule, // Importa o módulo que contém HeaderAdminComponent
|
||||
],
|
||||
declarations: [PermissionUserComponent], // Apenas componentes exclusivos deste módulo
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA],
|
||||
})
|
||||
export class AdminModule {}
|
||||
63
src/app/admin/permission-user/permission-user.component.html
Normal file
63
src/app/admin/permission-user/permission-user.component.html
Normal file
@@ -0,0 +1,63 @@
|
||||
<app-header-admin></app-header-admin>
|
||||
|
||||
<div class="d-flex flex-column wrapper">
|
||||
<main class="flex-fill main-dashboard">
|
||||
<div class="container">
|
||||
<div class="title-page">
|
||||
<span>Selecione o usuário</span>
|
||||
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-12 col-md-8">
|
||||
<kendo-combobox (selectionChange)="getPermissionUser()" (valueChange)="setUserSelected($event)"
|
||||
[valueNormalizer]="valueNormalizer" [data]="users" [kendoDropDownFilter]="filterSettings" textField="name"
|
||||
valueField="userId" placeholder="Selecione o usuário..." (input)="forceUppercase($event)">
|
||||
</kendo-combobox>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<button kendoButton class="btn-form" [disabled]="!userSelected" [icon]="isLoading ? 'loading' : ''"
|
||||
(click)="getPermissionUser()">Pesquisar Permissões</button>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<button *ngIf="permissions.length > 0" kendoButton class="btn-form" [disabled]="!userSelected"
|
||||
(click)="savePermissions()">Salvar
|
||||
Permissões</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-fill">
|
||||
<div *ngIf="userSelected && permissions.length; else noUserSelected">
|
||||
<kendo-treeview
|
||||
[nodes]="permissions"
|
||||
[children]="children"
|
||||
[hasChildren]="hasChildren"
|
||||
textField="text"
|
||||
kendoTreeViewCheckable
|
||||
[(checkedKeys)]="checkedKeys">
|
||||
</kendo-treeview>
|
||||
</div>
|
||||
<ng-template #noUserSelected>
|
||||
<div class="noData">
|
||||
<ng-lottie *ngIf="lottieOptions" [options]="lottieOptions" [styles]="lottieStyles"></ng-lottie>
|
||||
<p class="text-muted" *ngIf="!isLoading">
|
||||
{{ infoMessage }}
|
||||
</p>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</main>
|
||||
|
||||
<footer>
|
||||
<div class="container-fluid home-footer">
|
||||
<div class="row align-items-center justify-content-center">
|
||||
<div class="col-12">
|
||||
<span class="text-center text-footer">
|
||||
© 2022 App Soluti Soluções em aplicativos moveis
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
363
src/app/admin/permission-user/permission-user.component.scss
Normal file
363
src/app/admin/permission-user/permission-user.component.scss
Normal file
@@ -0,0 +1,363 @@
|
||||
.wrapper {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.logo {
|
||||
background-image: url("../../../assets/img/logo.svg");
|
||||
background-position: center;
|
||||
cursor: pointer;
|
||||
width: 100%;
|
||||
height: 80px !important;
|
||||
overflow: hidden;
|
||||
-webkit-background-size: cover;
|
||||
-moz-background-size: cover;
|
||||
-o-background-size: cover;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.header-productlist {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding: 32px 64px;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
top: 0px;
|
||||
margin: 0px;
|
||||
|
||||
/*background: #2d2e83;*/
|
||||
background: #131d52;
|
||||
}
|
||||
|
||||
.header-menu {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
position: static;
|
||||
height: 48px;
|
||||
|
||||
background: #1d1e67;
|
||||
border-radius: 5px;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 1;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.name-user {
|
||||
position: static;
|
||||
width: 100%;
|
||||
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
line-height: 19px;
|
||||
/* identical to box height */
|
||||
|
||||
color: #ffffff;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 0;
|
||||
flex-grow: 0;
|
||||
margin: 0px 0px;
|
||||
}
|
||||
|
||||
.last-access {
|
||||
position: static;
|
||||
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 10px;
|
||||
line-height: 16px;
|
||||
|
||||
color: #848484;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 1;
|
||||
flex-grow: 0;
|
||||
margin: 0px 0px;
|
||||
}
|
||||
|
||||
.img-config {
|
||||
position: static;
|
||||
background: #ffffff;
|
||||
flex: none;
|
||||
order: 2;
|
||||
flex-grow: 0;
|
||||
margin: 0px 16px;
|
||||
}
|
||||
|
||||
.center {
|
||||
// modificado
|
||||
position: relative;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.img-user {
|
||||
position: static;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
left: 8px;
|
||||
top: 6px;
|
||||
|
||||
background: url("../../../assets/img/img_user.svg");
|
||||
border-radius: 2px;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 0;
|
||||
flex-grow: 0;
|
||||
margin: 0px 16px;
|
||||
}
|
||||
|
||||
.home-footer {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
/*background: #2d2e83;*/
|
||||
background: #131d52;
|
||||
}
|
||||
|
||||
.text-footer {
|
||||
position: static;
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
/* identical to box height */
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
flex: none;
|
||||
order: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.main-dashboard {
|
||||
margin-top: 80px;
|
||||
}
|
||||
|
||||
.new-order {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
position: static;
|
||||
background: #ff9521;
|
||||
border-radius: 5px;
|
||||
/* Inside auto layout */
|
||||
flex: none;
|
||||
order: 1;
|
||||
flex-grow: 0;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.text-button {
|
||||
position: static;
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
/* identical to box height */
|
||||
|
||||
text-align: center;
|
||||
|
||||
color: #ffffff;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.button-flat {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
position: static;
|
||||
background: #ffffff;
|
||||
border: 1px solid #ef7d00;
|
||||
box-sizing: border-box;
|
||||
border-radius: 5px;
|
||||
/* Inside auto layout */
|
||||
flex: none;
|
||||
order: 1;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.side-menu {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
|
||||
position: static;
|
||||
height: 100%;
|
||||
left: 0px;
|
||||
top: 0px;
|
||||
|
||||
background: #ffffff;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 0;
|
||||
align-self: stretch;
|
||||
flex-grow: 0;
|
||||
margin: 0px 0px;
|
||||
}
|
||||
|
||||
.text-button-flat {
|
||||
position: static;
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
/* identical to box height */
|
||||
|
||||
text-align: center;
|
||||
|
||||
color: #ef7d00;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.button-flat-blue {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 0px;
|
||||
|
||||
position: static;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
|
||||
background: #ffffff;
|
||||
border: 1px solid #2d2e83;
|
||||
box-sizing: border-box;
|
||||
border-radius: 5px;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 1;
|
||||
align-self: stretch;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.text-button-flat-blue {
|
||||
position: static;
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
/* identical to box height */
|
||||
|
||||
text-align: center;
|
||||
|
||||
color: #2d2e83;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 0;
|
||||
flex-grow: 0;
|
||||
}
|
||||
|
||||
.noData {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.text-muted{
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
|
||||
/* Responsividade */
|
||||
|
||||
/* Smartphones */
|
||||
@media (max-width: 575.98px) {
|
||||
.btnSbtn-formearch {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.title-page{
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.noData {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.noData p {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablets */
|
||||
@media (max-width: 991.98px) {
|
||||
.btn-form {
|
||||
margin-top: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.title-page{
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktops */
|
||||
@media (min-width: 992px) {
|
||||
.btn-form {
|
||||
max-width: 200px;
|
||||
}
|
||||
|
||||
.title-page{
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
192
src/app/admin/permission-user/permission-user.component.ts
Normal file
192
src/app/admin/permission-user/permission-user.component.ts
Normal file
@@ -0,0 +1,192 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { DropDownFilterSettings } from '@progress/kendo-angular-dropdowns';
|
||||
import { Observable, of } from 'rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { AuthService } from 'src/app/auth/services/auth.service';
|
||||
import { UserService } from 'src/app/services/user.service';
|
||||
import { process } from '@progress/kendo-data-query';
|
||||
import { AnimationOptions } from 'ngx-lottie';
|
||||
|
||||
@Component({
|
||||
selector: 'app-permission-user',
|
||||
templateUrl: './permission-user.component.html',
|
||||
styleUrls: ['./permission-user.component.scss']
|
||||
})
|
||||
|
||||
export class PermissionUserComponent implements OnInit {
|
||||
|
||||
/* Header */
|
||||
public userName: string;
|
||||
public storeName: string;
|
||||
users: any[] = [];
|
||||
public checkedKeys: any[] = [];
|
||||
public data: any[] = [];
|
||||
public userSelected: any;
|
||||
public children = (dataItem: any): Observable<any[]> => of(dataItem.items);
|
||||
public hasChildren = (dataItem: any): boolean => !!dataItem.items;
|
||||
public permissions: any[] = [];
|
||||
public isUserLoading = false;
|
||||
public loadingIcon = '';
|
||||
public isLoading = false;
|
||||
public infoMessage = 'Por favor, selecione um usuário para carregar as permissões.';
|
||||
|
||||
public lottieOptions: AnimationOptions = {
|
||||
path: 'assets/animations/no-data.json',
|
||||
};
|
||||
|
||||
public lottieStyles = {
|
||||
width: '300px',
|
||||
height: '300px',
|
||||
};
|
||||
|
||||
constructor(private readonly authService: AuthService,
|
||||
private readonly userService: UserService) { }
|
||||
|
||||
ngOnInit() {
|
||||
this.userName = this.authService.getUserName();
|
||||
this.storeName = this.authService.getStoreName();
|
||||
this.userService.getUsers()
|
||||
.pipe(
|
||||
map((users) => {
|
||||
this.users = users;
|
||||
}))
|
||||
.subscribe();
|
||||
|
||||
if (!this.userSelected) {
|
||||
this.infoMessage = 'Nenhum usuário está selecionado.';
|
||||
}
|
||||
this.loadUsers();
|
||||
}
|
||||
|
||||
loadUsers() {
|
||||
this.isUserLoading = true;
|
||||
this.userService.getUsers()
|
||||
.pipe(
|
||||
map((users) => {
|
||||
this.users = users;
|
||||
this.isUserLoading = false;
|
||||
}),
|
||||
catchError((error) => {
|
||||
console.error('Erro ao carregar usuários:', error);
|
||||
this.isUserLoading = false;
|
||||
return of([]);
|
||||
})
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.authService.logout();
|
||||
}
|
||||
|
||||
public filterSettings: DropDownFilterSettings = {
|
||||
caseSensitive: false,
|
||||
operator: "contains",
|
||||
};
|
||||
|
||||
public valueNormalizer = (text: Observable<string>) =>
|
||||
text.pipe(
|
||||
map((content: string) => {
|
||||
return {
|
||||
value: this.permissions[this.permissions.length - 1]?.value + 1 || 1,
|
||||
text: content,
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
forceUppercase(event: Event): void {
|
||||
const inputElement = event.target as HTMLInputElement;
|
||||
if (inputElement && inputElement.value) {
|
||||
inputElement.value = inputElement.value.toUpperCase();
|
||||
}
|
||||
}
|
||||
|
||||
setUserSelected(user: any) {
|
||||
console.log(user);
|
||||
this.userSelected = user;
|
||||
|
||||
if (!user) {
|
||||
this.permissions = [];
|
||||
this.checkedKeys = [];
|
||||
this.infoMessage = 'Por favor, selecione um usuário válido.';
|
||||
} else {
|
||||
this.checkedKeys = [];
|
||||
this.infoMessage = '';
|
||||
}
|
||||
}
|
||||
|
||||
getPermissionUser() {
|
||||
if (!this.userSelected) {
|
||||
console.warn('Nenhum usuário selecionado. Não é possível buscar permissões.');
|
||||
this.lottieOptions = { path: 'assets/animations/no-data.json' };
|
||||
return;
|
||||
}
|
||||
|
||||
this.isLoading = true;
|
||||
this.lottieOptions = { path: 'assets/animations/loading.json' };
|
||||
|
||||
this.userService.getPermissionUser(this.userSelected.userId)
|
||||
.pipe(
|
||||
map((permissions) => {
|
||||
this.permissions = permissions;
|
||||
this.loadPermissions(this.permissions);
|
||||
|
||||
// If permissions are found, stop the loading animation
|
||||
this.isLoading = false;
|
||||
this.lottieOptions = permissions.length > 0
|
||||
? { path: 'assets/animations/no-data.json' }
|
||||
: { path: 'assets/animations/no-data.json' };
|
||||
}),
|
||||
catchError((error) => {
|
||||
console.error('Erro ao carregar permissões do usuário:', error);
|
||||
this.isLoading = false; // Stop loading state
|
||||
this.lottieOptions = { path: 'assets/animations/no-data.json' }; // Error or no data animation
|
||||
return of([]); // Default return value in case of error
|
||||
})
|
||||
)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
savePermissions() {
|
||||
const permissionsId: number[] = [];
|
||||
const atividades: any[] = [];
|
||||
const actions: any[] = [];
|
||||
for (const key of this.checkedKeys) {
|
||||
const ids = key.split("_");
|
||||
if (ids.length > 2) {
|
||||
const module = this.permissions[ids[0]];
|
||||
const atividade = module.items[ids[1]];
|
||||
const action = atividade.items[ids[2]];
|
||||
if (action != undefined) {
|
||||
actions.push(action);
|
||||
}
|
||||
} else {
|
||||
const module = this.permissions[ids[0]];
|
||||
const atividade = module.items[ids[1]];
|
||||
if (atividade != undefined) {
|
||||
atividades.push(atividade);
|
||||
}
|
||||
}
|
||||
}
|
||||
const updatePermissions = { atividades: atividades, actions: actions };
|
||||
const userId = this.userSelected.userId;
|
||||
|
||||
this.userService.updatePermissionUser(userId, updatePermissions);
|
||||
}
|
||||
|
||||
loadPermissions(data: any) {
|
||||
this.checkedKeys = [];
|
||||
data.filter(permission => permission.allow == 'S')
|
||||
.forEach(permissionModule => {
|
||||
let indice_modulo = -1;
|
||||
let indice_atividade = -1;
|
||||
permissionModule.items
|
||||
.filter(permissionAtividade => permissionAtividade.allow == 'S')
|
||||
.forEach(permissionAtividade => {
|
||||
indice_modulo++;
|
||||
indice_atividade++;
|
||||
this.checkedKeys.push(`${indice_modulo}_${indice_atividade}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
26
src/app/app-routing.module.ts
Normal file
26
src/app/app-routing.module.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { AuthGuard } from './guards/auth.guard';
|
||||
import { MenuComponent } from './menu/menu.component';
|
||||
import { MenuEcosistemaComponent } from './menu-ecosistema/menu-ecosistema.component';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', redirectTo: 'sales/home', pathMatch: 'full' },
|
||||
// loadChildren: () => import('./sales/sales.module').then(m => m.SalesModule), canActivate: [AuthGuard] },
|
||||
{ path: 'login', loadChildren: () => import('./auth/auth.module').then(m => m.AuthModule)},
|
||||
{ path: 'menu', component: MenuEcosistemaComponent},
|
||||
{ path: 'financial', loadChildren: () => import('./financial/financial.module').then(m => m.FinancialModule), canActivate: [AuthGuard] },
|
||||
{ path: 'sales', loadChildren: () => import('./sales/sales.module').then(m => m.SalesModule), canActivate: [AuthGuard] },
|
||||
{ path: 'crm', loadChildren: () => import('./crm/crm.module').then(m => m.CrmModule), canActivate: [AuthGuard] },
|
||||
{ path: 'partner', loadChildren: () => import('./partners/partners.module').then(m => m.PartnersModule), canActivate: [AuthGuard] },
|
||||
{ path: 'admin', loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule), canActivate: [AuthGuard] },
|
||||
{ path: 'dashboardcompany', loadChildren: () =>
|
||||
import('./sales/pages/dashboard-company/dashboard-company.module').then(m => m.DashboardCompanyModule)},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forRoot(routes, {useHash: true})],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class AppRoutingModule { }
|
||||
0
src/app/app.component.css
Normal file
0
src/app/app.component.css
Normal file
1
src/app/app.component.html
Normal file
1
src/app/app.component.html
Normal file
@@ -0,0 +1 @@
|
||||
<router-outlet></router-outlet>
|
||||
35
src/app/app.component.spec.ts
Normal file
35
src/app/app.component.spec.ts
Normal file
@@ -0,0 +1,35 @@
|
||||
import { TestBed, async } from '@angular/core/testing';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { AppComponent } from './app.component';
|
||||
|
||||
describe('AppComponent', () => {
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [
|
||||
RouterTestingModule
|
||||
],
|
||||
declarations: [
|
||||
AppComponent
|
||||
],
|
||||
}).compileComponents();
|
||||
}));
|
||||
|
||||
it('should create the app', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app).toBeTruthy();
|
||||
});
|
||||
|
||||
it(`should have as title 'sales'`, () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
const app = fixture.componentInstance;
|
||||
expect(app.title).toEqual('sales');
|
||||
});
|
||||
|
||||
it('should render title', () => {
|
||||
const fixture = TestBed.createComponent(AppComponent);
|
||||
fixture.detectChanges();
|
||||
const compiled = fixture.nativeElement;
|
||||
expect(compiled.querySelector('.content span').textContent).toContain('sales app is running!');
|
||||
});
|
||||
});
|
||||
10
src/app/app.component.ts
Normal file
10
src/app/app.component.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
templateUrl: './app.component.html',
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'sales';
|
||||
}
|
||||
103
src/app/app.module.ts
Normal file
103
src/app/app.module.ts
Normal file
@@ -0,0 +1,103 @@
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { DEFAULT_CURRENCY_CODE, LOCALE_ID, NgModule } from '@angular/core';
|
||||
import ptBr from '@angular/common/locales/pt';
|
||||
import { HashLocationStrategy, LocationStrategy } from '@angular/common';
|
||||
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
import { AppComponent } from './app.component';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
|
||||
import { LottieModule } from 'ngx-lottie';
|
||||
import player from 'lottie-web';
|
||||
|
||||
import { SalesModule } from './sales/sales.module';
|
||||
import { FinancialModule } from './financial/financial.module';
|
||||
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
|
||||
import { environment } from '../environments/environment';
|
||||
import { EffectsModule } from '@ngrx/effects';
|
||||
import { ShoppingEffects } from './sales/store/effects/shopping.effects';
|
||||
import { StoreModule } from '@ngrx/store';
|
||||
import { ShoppingReducer } from './sales/store/reducers/shopping.reducer';
|
||||
import { AngularFireModule } from '@angular/fire';
|
||||
import { AngularFirestoreModule } from '@angular/fire/firestore';
|
||||
import { AngularFireAuthModule } from '@angular/fire/auth';
|
||||
import { AuthGuard } from './guards/auth.guard';
|
||||
import { AuthService } from './auth/services/auth.service';
|
||||
import { CustomerModule } from './sales/customer/customer.module';
|
||||
import { KendoModule } from './shared/kendo.module';
|
||||
import { MessageErrorComponent } from './shared/menssages/message-error/message-error.component';
|
||||
import { MenuEcosistemaComponent } from './menu-ecosistema/menu-ecosistema.component';
|
||||
import { ComponentModule } from './components/component.module';
|
||||
import { MessageFailureComponent } from './shared/menssages/message-failure/message-failure.component';
|
||||
import { CustomerSaleEffects } from './sales/store/effects/customer-sale.effects';
|
||||
import { CustomerSaleReducer } from './sales/store/reducers/customer-sale.reducer';
|
||||
import { MenssageInformationComponent } from './shared/menssages/menssage-information/menssage-information.component';
|
||||
import { CrmModule } from './crm/crm.module';
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import { MenuComponent } from './menu/menu.component';
|
||||
import { MenuSalesComponent } from './sales/menu-sales/menu-sales.component';
|
||||
import { StimulsoftViewerModule } from 'stimulsoft-viewer-angular';
|
||||
import { DialogRef } from '@progress/kendo-angular-dialog';
|
||||
import { PartnersModule } from './partners/partners.module';
|
||||
import { AdminModule } from './admin/admin.module';
|
||||
import { DialogsModule } from '@progress/kendo-angular-dialog';
|
||||
import { ChartsModule } from '@progress/kendo-angular-charts';
|
||||
import 'hammerjs';
|
||||
|
||||
|
||||
|
||||
registerLocaleData(ptBr);
|
||||
|
||||
export function playerFactory() {
|
||||
return player;
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
MessageErrorComponent,
|
||||
MessageFailureComponent,
|
||||
MenuEcosistemaComponent,
|
||||
MenssageInformationComponent,
|
||||
MenuComponent,
|
||||
MenuSalesComponent,
|
||||
],
|
||||
imports: [
|
||||
AngularFireModule.initializeApp(environment.firebase),
|
||||
DialogsModule,
|
||||
AngularFirestoreModule, // imports firebase/firestore, only needed for database features
|
||||
AngularFireAuthModule,
|
||||
BrowserModule,
|
||||
HttpClientModule,
|
||||
FinancialModule,
|
||||
AppRoutingModule,
|
||||
BrowserAnimationsModule,
|
||||
SalesModule,
|
||||
CustomerModule,
|
||||
KendoModule,
|
||||
ComponentModule,
|
||||
CrmModule,
|
||||
StoreModule.forRoot({ shopping: ShoppingReducer, customerSale: CustomerSaleReducer }),
|
||||
EffectsModule.forRoot([ShoppingEffects, CustomerSaleEffects]),
|
||||
StoreDevtoolsModule.instrument({ maxAge: 25, logOnly: environment.production }),
|
||||
StimulsoftViewerModule,
|
||||
PartnersModule,
|
||||
AdminModule,
|
||||
// LottieModule.forRoot({ player: playerFactory }),
|
||||
ChartsModule,
|
||||
],
|
||||
exports: [StimulsoftViewerModule],
|
||||
providers: [
|
||||
AuthGuard, AuthService,
|
||||
{ provide: LocationStrategy, useClass: HashLocationStrategy },
|
||||
{ provide: LOCALE_ID, useValue: 'pt-BR' },
|
||||
{ provide: DEFAULT_CURRENCY_CODE, useValue: 'BRL', },
|
||||
DialogRef,
|
||||
/*{
|
||||
provide: ErrorHandler,
|
||||
useClass: ErrorsHandler,
|
||||
},*/
|
||||
],
|
||||
bootstrap: [AppComponent]
|
||||
})
|
||||
export class AppModule { }
|
||||
9
src/app/auth/auth-login/auth-login.component.css
Normal file
9
src/app/auth/auth-login/auth-login.component.css
Normal file
@@ -0,0 +1,9 @@
|
||||
.example {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.k-form kendo-label:not(:last-of-type) {
|
||||
flex-direction: column;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
0
src/app/auth/auth-login/auth-login.component.html
Normal file
0
src/app/auth/auth-login/auth-login.component.html
Normal file
0
src/app/auth/auth-login/auth-login.component.scss
Normal file
0
src/app/auth/auth-login/auth-login.component.scss
Normal file
25
src/app/auth/auth-login/auth-login.component.spec.ts
Normal file
25
src/app/auth/auth-login/auth-login.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AuthLoginComponent } from './auth-login.component';
|
||||
|
||||
describe('AuthLoginComponent', () => {
|
||||
let component: AuthLoginComponent;
|
||||
let fixture: ComponentFixture<AuthLoginComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ AuthLoginComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(AuthLoginComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
65
src/app/auth/auth-login/auth-login.component.ts
Normal file
65
src/app/auth/auth-login/auth-login.component.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-auth-login',
|
||||
templateUrl: './auth-login.component.html',
|
||||
styleUrls: ['./auth-login.component.scss',
|
||||
'./auth-login.component.css']
|
||||
})
|
||||
|
||||
export class AuthLoginComponent implements OnInit {
|
||||
|
||||
public phoneNumberValue = '';
|
||||
public phoneNumberMask = '(999) 000-00-00-00';
|
||||
|
||||
public form: FormGroup;
|
||||
|
||||
public data: any = {
|
||||
fullName: '',
|
||||
email: '',
|
||||
phoneNumber: this.phoneNumberValue,
|
||||
arrivalDate: null,
|
||||
numberOfNights: null,
|
||||
numberOfGuests: null,
|
||||
terms: false,
|
||||
comments: '',
|
||||
};
|
||||
|
||||
constructor() {
|
||||
this.form = new FormGroup({
|
||||
fullName: new FormControl(this.data.fullName, [Validators.required]),
|
||||
email: new FormControl(this.data.email, [
|
||||
Validators.required,
|
||||
Validators.email,
|
||||
]),
|
||||
phoneNumber: new FormControl(this.data.phoneNumber, [
|
||||
Validators.required,
|
||||
]),
|
||||
arrivalDate: new FormControl(this.data.arrivalDate, [
|
||||
Validators.required,
|
||||
]),
|
||||
numberOfNights: new FormControl(this.data.numberOfNights, [
|
||||
Validators.required,
|
||||
]),
|
||||
numberOfGuests: new FormControl(this.data.numberOfGuests, [
|
||||
Validators.required,
|
||||
Validators.max(5),
|
||||
]),
|
||||
terms: new FormControl(this.data.terms, [Validators.requiredTrue]),
|
||||
comments: new FormControl(this.data.comments),
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
public submitForm(): void {
|
||||
this.form.markAllAsTouched();
|
||||
}
|
||||
|
||||
public clearForm(): void {
|
||||
this.form.reset();
|
||||
}
|
||||
|
||||
}
|
||||
25
src/app/auth/auth.module.ts
Normal file
25
src/app/auth/auth.module.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { AuthLoginComponent } from './auth-login/auth-login.component';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { KendoModule } from '../shared/kendo.module';
|
||||
import { LoginComponent } from './login/login.component';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { RegisterComponent } from './register/register.component';
|
||||
import { AuthService } from './services/auth.service';
|
||||
|
||||
const routes: Routes = [{ path: '', component: LoginComponent },
|
||||
{ path: 'register', component: RegisterComponent }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [AuthLoginComponent, LoginComponent, RegisterComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
KendoModule,
|
||||
RouterModule.forChild(routes),
|
||||
],
|
||||
providers: [AuthService]
|
||||
})
|
||||
export class AuthModule { }
|
||||
206
src/app/auth/login/login.component.css
Normal file
206
src/app/auth/login/login.component.css
Normal file
@@ -0,0 +1,206 @@
|
||||
.hs-login {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 32px 64px;
|
||||
position: absolute;
|
||||
background: #fcfcfc;
|
||||
}
|
||||
|
||||
.logo {
|
||||
width: 190px;
|
||||
height: 51.54px;
|
||||
}
|
||||
|
||||
.fs-login {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
/* width: 100%; */
|
||||
}
|
||||
|
||||
.fs-label {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.container-login {
|
||||
background-image: url("../../../assets/img/Background.png");
|
||||
background-size: cover;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.cs-login {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 60px 40px;
|
||||
width: 100%;
|
||||
max-width: 500px;
|
||||
background: #fcfcfc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
/* Textos */
|
||||
.ls-saudacao,
|
||||
.ls-plataforma {
|
||||
font-family: "Fira Sans", sans-serif;
|
||||
text-align: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.ls-saudacao {
|
||||
font-weight: 400;
|
||||
font-size: 40px;
|
||||
color: #ef7d00;
|
||||
}
|
||||
|
||||
.ls-plataforma {
|
||||
font-weight: 700;
|
||||
font-size: 40px;
|
||||
color: #2d2e83;
|
||||
}
|
||||
|
||||
.ls-subtitle {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 20px;
|
||||
color: #ef7d00;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.ls-text {
|
||||
position: static;
|
||||
width: 87px;
|
||||
height: 19px;
|
||||
left: 0px;
|
||||
top: 37px;
|
||||
|
||||
font-family: "Open Sans";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
/* identical to box height */
|
||||
|
||||
color: #848484;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 1;
|
||||
flex-grow: 0;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
.is-text {
|
||||
/* Auto layout */
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
padding: 0px;
|
||||
align-items: center;
|
||||
|
||||
position: static;
|
||||
width: 408px;
|
||||
height: 48px;
|
||||
left: 0px;
|
||||
top: 66px;
|
||||
|
||||
/* Inside auto layout */
|
||||
|
||||
flex: none;
|
||||
order: 2;
|
||||
align-self: stretch;
|
||||
flex-grow: 0;
|
||||
margin: 10px 0px;
|
||||
}
|
||||
|
||||
|
||||
.bs-default {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: white;
|
||||
width: 100%;
|
||||
height: 48px;
|
||||
background: #2d2e83;
|
||||
border-radius: 5px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.ls-forgot-password {
|
||||
text-align: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.ls-link-forgot-password {
|
||||
text-decoration: underline;
|
||||
color: #2d2e83;
|
||||
}
|
||||
|
||||
/* Responsividade */
|
||||
|
||||
/* Smartphones */
|
||||
@media (max-width: 575.98px) {
|
||||
.cs-login {
|
||||
padding: 40px 20px;
|
||||
max-width: 300px;
|
||||
}
|
||||
|
||||
.ls-saudacao {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.ls-plataforma {
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.bs-default {
|
||||
height: 56px;
|
||||
}
|
||||
|
||||
.is-text {
|
||||
width: 300px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.ls-forgot-password {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ls-link-forgot-password {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Tablets */
|
||||
@media (max-width: 991.98px) {
|
||||
.cs-login {
|
||||
max-width: 400px;
|
||||
}
|
||||
|
||||
.ls-saudacao {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.ls-plataforma {
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.is-text {
|
||||
width: 250px;
|
||||
height: 40px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktops */
|
||||
@media (min-width: 992px) {
|
||||
.cs-login {
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
||||
56
src/app/auth/login/login.component.html
Normal file
56
src/app/auth/login/login.component.html
Normal file
@@ -0,0 +1,56 @@
|
||||
<div class="container-fluid container-login">
|
||||
<div class="d-flex flex-column">
|
||||
<div class="row justify-content-center align-items-center" style="height: 100vh;">
|
||||
<div class="col-12 col-sm-8 col-md-6 col-xl-4">
|
||||
<div class="cs-login">
|
||||
<div class="text-center">
|
||||
<span class="ls-saudacao">Bem-vindo(a),</span>
|
||||
<span class="ls-plataforma">à plataforma SMART</span>
|
||||
</div>
|
||||
<form class="fs-login" [formGroup]="form" (keydown.enter)="submitForm()">
|
||||
<span class="ls-subtitle">Acesse sua conta</span>
|
||||
<kendo-formfield>
|
||||
<label>
|
||||
<span class="ls-text">Email</span>
|
||||
<kendo-textbox class="is-text" formControlName="email" placeholder="Informe seu email de acesso" #email
|
||||
required>
|
||||
</kendo-textbox>
|
||||
</label>
|
||||
<!-- <kendo-formerror *ngIf="form.controls.email.errors?.required">
|
||||
Erro: Email é obrigatório!
|
||||
</kendo-formerror>
|
||||
<kendo-formerror *ngIf="form.controls.email.errors?.email">
|
||||
Error: Informe um email com formato válido.
|
||||
</kendo-formerror> -->
|
||||
</kendo-formfield>
|
||||
<kendo-formfield>
|
||||
<label>
|
||||
<span class="ls-text">Senha</span>
|
||||
<kendo-textbox class="k-textbox is-text" type="password" placeholder="Informe sua senha" #password
|
||||
formControlName="password">
|
||||
<ng-template kendoTextBoxSuffixTemplate>
|
||||
<button
|
||||
kendoButton
|
||||
look="clear"
|
||||
[icon]="passwordVisible ? 'eye-slash' : 'eye'"
|
||||
(click)="toggleVisibility()"
|
||||
type="button"
|
||||
></button>
|
||||
</ng-template>
|
||||
</kendo-textbox>
|
||||
</label>
|
||||
<kendo-formerror>Erro: A senha é obrigatória!</kendo-formerror>
|
||||
</kendo-formfield>
|
||||
<span class="ls-forgot-password">
|
||||
Esqueceu a senha? <a class="ls-link-forgot-password">Recupere o acesso</a>
|
||||
</span>
|
||||
<button kendoButton class="bs-default" [disabled]="isLoading" [icon]="loadingIcon" (click)="submitForm()">
|
||||
ENTRAR
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div kendoDialogContainer></div>
|
||||
1
src/app/auth/login/login.component.scss
Normal file
1
src/app/auth/login/login.component.scss
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
25
src/app/auth/login/login.component.spec.ts
Normal file
25
src/app/auth/login/login.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LoginComponent } from './login.component';
|
||||
|
||||
describe('LoginComponent', () => {
|
||||
let component: LoginComponent;
|
||||
let fixture: ComponentFixture<LoginComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ LoginComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LoginComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
151
src/app/auth/login/login.component.ts
Normal file
151
src/app/auth/login/login.component.ts
Normal file
@@ -0,0 +1,151 @@
|
||||
import { AfterViewInit, Component, NgZone, OnInit, ViewChild } from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { Router } from '@angular/router';
|
||||
import { DialogService } from '@progress/kendo-angular-dialog';
|
||||
import { TextBoxComponent } from '@progress/kendo-angular-inputs';
|
||||
import { thumbnailsUpIcon } from '@progress/kendo-svg-icons';
|
||||
import { ResultApi } from 'src/app/models/result-api.model';
|
||||
import { MessageFailureComponent } from 'src/app/shared/menssages/message-failure/message-failure.component';
|
||||
import { AuthService } from '../services/auth.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
templateUrl: './login.component.html',
|
||||
styleUrls: ['./login.component.scss',
|
||||
'./login.component.css']
|
||||
})
|
||||
export class LoginComponent implements OnInit, AfterViewInit {
|
||||
@ViewChild('password') public textbox: TextBoxComponent;
|
||||
public initialPassword = true;
|
||||
public passwordVisible = false;
|
||||
public loadingIcon = '';
|
||||
|
||||
public form: FormGroup;
|
||||
public data: any = {
|
||||
email: '',
|
||||
password: '',
|
||||
};
|
||||
|
||||
constructor(private authService: AuthService,
|
||||
private router: Router,
|
||||
private dialogService: DialogService,
|
||||
private ngZone: NgZone
|
||||
) {
|
||||
this.form = new FormGroup({
|
||||
password: new FormControl(this.data.password, [Validators.required, Validators.minLength(3)]),
|
||||
email: new FormControl(this.data.email, [
|
||||
Validators.required,
|
||||
]),
|
||||
});
|
||||
}
|
||||
|
||||
private dialog: any;
|
||||
|
||||
public onEnter(event: KeyboardEvent): void {
|
||||
event.preventDefault(); // Evita o envio do formulário padrão
|
||||
if (this.form.valid) {
|
||||
this.submitForm(); // Apenas submete se o formulário for válido
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public submitForm(): void {
|
||||
this.form.markAllAsTouched();
|
||||
if (this.form.valid) {
|
||||
this.loadingIcon = 'loading';
|
||||
const domain = '@jurunense.com.br';
|
||||
let email = this.form.value.email;
|
||||
|
||||
// Remover domínio existente se já foi digitado
|
||||
if (email.toLowerCase().endsWith(domain)) {
|
||||
email = email.substring(0, email.length - domain.length);
|
||||
}
|
||||
|
||||
const emailUpperCase = (email + domain).toUpperCase();
|
||||
const passwordUpperCase = this.form.value.password.toUpperCase();
|
||||
|
||||
this.authService.login({
|
||||
email: emailUpperCase,
|
||||
password: passwordUpperCase
|
||||
})
|
||||
.subscribe((res: ResultApi) => {
|
||||
if (res.success) {
|
||||
this.loadingIcon = '';
|
||||
console.log(JSON.stringify(res.data));
|
||||
this.authService.setDataInLocalStorage('user', JSON.stringify(res.data));
|
||||
this.authService.setDataInLocalStorage('token', res.data.token);
|
||||
localStorage.removeItem('cart');
|
||||
this.router.navigate(['/menu']);
|
||||
} else {
|
||||
this.loadingIcon = '';
|
||||
this.showErrorMessage(res.message);
|
||||
}
|
||||
}, err => {
|
||||
this.loadingIcon = '';
|
||||
this.showErrorMessage(`${err.error.message}`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public get isLoading(): boolean {
|
||||
return this.loadingIcon !== '';
|
||||
}
|
||||
|
||||
public clearForm(): void {
|
||||
this.form.reset();
|
||||
}
|
||||
|
||||
public togglePass(): void {
|
||||
const inputEl = this.textbox.input.nativeElement;
|
||||
|
||||
if (this.initialPassword) {
|
||||
inputEl.type = 'password';
|
||||
this.initialPassword = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (inputEl.type === 'password') {
|
||||
inputEl.type = 'text';
|
||||
} else {
|
||||
inputEl.type = 'password';
|
||||
}
|
||||
|
||||
console.log(this.form.controls.password.value);
|
||||
}
|
||||
|
||||
getUserName() {
|
||||
return this.authService.getUserName();
|
||||
}
|
||||
|
||||
showErrorMessage(message: string) {
|
||||
console.log('mensagem de erro', message);
|
||||
const dialogRef = this.dialogService
|
||||
.open({
|
||||
title: 'Error',
|
||||
content: MessageFailureComponent,
|
||||
actions: [{ text: 'OK', primary: true }],
|
||||
width: 400,
|
||||
height: 250,
|
||||
minWidth: 250,
|
||||
});
|
||||
|
||||
const messageInfo = dialogRef.content.instance;
|
||||
messageInfo.message = message;
|
||||
this.ngZone.run(() => {
|
||||
dialogRef.result.subscribe();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
ngOnInit(): void { }
|
||||
|
||||
public ngAfterViewInit(): void {
|
||||
this.textbox.input.nativeElement.type = 'password';
|
||||
}
|
||||
|
||||
public toggleVisibility(): void {
|
||||
const inputEl = this.textbox.input.nativeElement;
|
||||
this.passwordVisible = !this.passwordVisible;
|
||||
inputEl.type = this.passwordVisible ? 'text' : 'password';
|
||||
}
|
||||
}
|
||||
42
src/app/auth/register/register.component.html
Normal file
42
src/app/auth/register/register.component.html
Normal file
@@ -0,0 +1,42 @@
|
||||
<div class="example">
|
||||
<form class="k-form" [formGroup]="form">
|
||||
<h5 class="text-center">CADASTRO DE NOVO USUARIO</h5>
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="email" text="Email"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="email"
|
||||
[clearButton]="true"
|
||||
#email
|
||||
required
|
||||
></kendo-textbox>
|
||||
|
||||
<kendo-formerror *ngIf="form.controls.email.errors?.required"
|
||||
>Error: Email is required</kendo-formerror
|
||||
>
|
||||
<kendo-formerror *ngIf="form.controls.email.errors?.email"
|
||||
>Error: Not valid email format</kendo-formerror
|
||||
>
|
||||
</kendo-formfield>
|
||||
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="password" text="Senha"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="password"
|
||||
|
||||
[clearButton]="true"
|
||||
#password
|
||||
required
|
||||
></kendo-textbox>
|
||||
|
||||
<kendo-formerror>Error: Password is required</kendo-formerror>
|
||||
</kendo-formfield>
|
||||
|
||||
<div class="k-form-buttons">
|
||||
<button class="k-button k-primary" (click)="submitForm()">
|
||||
Send Reservation Request
|
||||
</button>
|
||||
<button class="k-button" (click)="clearForm()">Clear</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
10
src/app/auth/register/register.component.scss
Normal file
10
src/app/auth/register/register.component.scss
Normal file
@@ -0,0 +1,10 @@
|
||||
.example {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.k-form kendo-label:not(:last-of-type) {
|
||||
flex-direction: column;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
25
src/app/auth/register/register.component.spec.ts
Normal file
25
src/app/auth/register/register.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { RegisterComponent } from './register.component';
|
||||
|
||||
describe('RegisterComponent', () => {
|
||||
let component: RegisterComponent;
|
||||
let fixture: ComponentFixture<RegisterComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ RegisterComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(RegisterComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
60
src/app/auth/register/register.component.ts
Normal file
60
src/app/auth/register/register.component.ts
Normal file
@@ -0,0 +1,60 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { AuthService } from '../services/auth.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-register',
|
||||
templateUrl: './register.component.html',
|
||||
styleUrls: ['./register.component.scss']
|
||||
})
|
||||
export class RegisterComponent implements OnInit {
|
||||
|
||||
public form: FormGroup;
|
||||
public errorMessage: string;
|
||||
public successMessage: string;
|
||||
|
||||
public data: any = {
|
||||
email: '',
|
||||
password: '',
|
||||
};
|
||||
|
||||
constructor(private authService: AuthService) {
|
||||
this.form = new FormGroup({
|
||||
password: new FormControl(this.data.password, [Validators.required, Validators.minLength(3)]),
|
||||
email: new FormControl(this.data.email, [
|
||||
Validators.required,
|
||||
Validators.email,
|
||||
]),
|
||||
});
|
||||
}
|
||||
|
||||
public submitForm(): void {
|
||||
this.form.markAllAsTouched();
|
||||
if (this.form.valid){
|
||||
this.tryRegister({email: this.form.value.email, password: this.form.value.password});
|
||||
}
|
||||
}
|
||||
|
||||
public clearForm(): void {
|
||||
this.form.reset();
|
||||
}
|
||||
|
||||
tryRegister(value){
|
||||
/*this.authService.doRegister(value)
|
||||
.then(res => {
|
||||
console.log(res);
|
||||
this.errorMessage = '';
|
||||
this.successMessage = 'Your account has been created';
|
||||
console.log(this.successMessage);
|
||||
}, err => {
|
||||
console.log(err);
|
||||
this.errorMessage = err.message;
|
||||
this.successMessage = '';
|
||||
console.log(err.code + ' - ' + this.errorMessage);
|
||||
});*/
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
16
src/app/auth/services/auth.service.spec.ts
Normal file
16
src/app/auth/services/auth.service.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AuthService } from './auth.service';
|
||||
|
||||
describe('AuthService', () => {
|
||||
let service: AuthService;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(AuthService);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
183
src/app/auth/services/auth.service.ts
Normal file
183
src/app/auth/services/auth.service.ts
Normal file
@@ -0,0 +1,183 @@
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { ResultApi } from 'src/app/models/result-api.model';
|
||||
import { environment } from 'src/environments/environment';
|
||||
import { AuthUser } from '../../models/auth.user.model';
|
||||
import jwt_decode from 'jwt-decode';
|
||||
import { ModuleSystem } from 'src/app/models/module.model';
|
||||
import { PagesUser } from 'src/app/models/pages-user.model';
|
||||
import { ActionsUser } from 'src/app/models/actions-user.model';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuthService {
|
||||
|
||||
private UserAuthenticate = false;
|
||||
public actionsUser: ActionsUser[];
|
||||
|
||||
constructor(public httpClient: HttpClient,
|
||||
public router: Router) { }
|
||||
|
||||
/*doRegister(value){
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
this.afAuth.createUserWithEmailAndPassword(value.email, value.password)
|
||||
.then(res => {
|
||||
resolve(res);
|
||||
}, err => reject(err));
|
||||
});
|
||||
}
|
||||
|
||||
doEmailAndPasswordLogin(value){
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
this.afAuth
|
||||
.signInWithEmailAndPassword(value.email, value.password)
|
||||
.then(res => {
|
||||
console.log(res);
|
||||
resolve(res);
|
||||
}, err => reject(err));
|
||||
});
|
||||
} */
|
||||
|
||||
login(value: AuthUser): Observable<ResultApi> {
|
||||
return this.httpClient.post<ResultApi>(`${environment.url}auth/login`, value);
|
||||
}
|
||||
|
||||
logout() {
|
||||
localStorage.removeItem('user');
|
||||
localStorage.removeItem('token');
|
||||
this.router.navigate(['login']);
|
||||
}
|
||||
|
||||
authenticate(value: AuthUser): Observable<ResultApi> {
|
||||
return this.httpClient.post<ResultApi>(`${environment.url}auth/authenticate`, value);
|
||||
}
|
||||
|
||||
getDiscount(id: number = 0): Observable<ResultApi> {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
const token = this.getToken();
|
||||
const headers = new HttpHeaders().set('Authorization', `Basic ${token}`);
|
||||
let userId = user.id;
|
||||
if (id > 0){
|
||||
userId = id;
|
||||
}
|
||||
return this.httpClient.get<ResultApi>(`${environment.url}auth/discount-user/${userId}`);
|
||||
}
|
||||
|
||||
getModules(id: number) {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
const token = this.getToken();
|
||||
const headers = new HttpHeaders().set('Authorization', `Basic ${token}`);
|
||||
let userId = user.id;
|
||||
if (id > 0){
|
||||
userId = id;
|
||||
}
|
||||
return this.httpClient.get<ModuleSystem[]>(`${environment.url}access-control/modules/${userId}`);
|
||||
}
|
||||
|
||||
getPagesUser(moduleId: number) {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
const token = this.getToken();
|
||||
const headers = new HttpHeaders().set('Authorization', `Basic ${token}`);
|
||||
|
||||
return this.httpClient.get<PagesUser[]>(`${environment.url}access-control/pages/${user.id}/${moduleId}`);
|
||||
}
|
||||
|
||||
getActionsUser(moduleId: number) {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
const token = this.getToken();
|
||||
const headers = new HttpHeaders().set('Authorization', `Basic ${token}`);
|
||||
return this.httpClient.get<ActionsUser[]>(`${environment.url}access-control/actions/${user.id}/${moduleId}`);
|
||||
}
|
||||
|
||||
setDataInLocalStorage(variableName: string, data: any) {
|
||||
localStorage.setItem(variableName, data);
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return localStorage.getItem('token');
|
||||
}
|
||||
|
||||
getPayload() {
|
||||
try {
|
||||
return jwt_decode(this.getToken()) as any;
|
||||
} catch (Error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
isManager() {
|
||||
const data = this.getPayload();
|
||||
console.log(JSON.stringify(data));
|
||||
return data.sectorId.toString() === data.sectorManagerId.toString();
|
||||
}
|
||||
|
||||
getUserName() {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
return user.username;
|
||||
}
|
||||
|
||||
getStoreName() {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
return user.name;
|
||||
}
|
||||
|
||||
getUser() {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
return user.id;
|
||||
}
|
||||
|
||||
getSeller() {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
return user.seller;
|
||||
}
|
||||
|
||||
getSupervisor() {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
return user.supervisorId;
|
||||
}
|
||||
|
||||
getStore() {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
return user.store;
|
||||
}
|
||||
|
||||
getDeliveryTime() {
|
||||
const data = localStorage.getItem('user');
|
||||
const user = JSON.parse(data);
|
||||
return user.deliveryTime;
|
||||
}
|
||||
|
||||
deleteDataLocalStorage(variableName: string) {
|
||||
localStorage.removeItem(variableName);
|
||||
}
|
||||
|
||||
isAuthenticate(){
|
||||
console.log(localStorage.getItem('token'));
|
||||
return localStorage.getItem('token') != null;
|
||||
}
|
||||
|
||||
userAction(processId: number, pageId: number, actionId: number) {
|
||||
const actionUser = this.actionsUser
|
||||
.find(action => action.moduleId == 2 &&
|
||||
action.processId == processId &&
|
||||
action.pageId == pageId &&
|
||||
action.actionId == actionId &&
|
||||
action.access == "S" );
|
||||
console.log(this.actionsUser);
|
||||
return actionUser !== undefined && actionUser!== null;
|
||||
}
|
||||
|
||||
}
|
||||
25
src/app/components/component.module.ts
Normal file
25
src/app/components/component.module.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { HeaderSystemComponent } from './header-system/header-system.component';
|
||||
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
|
||||
import { KendoModule } from '../shared/kendo.module';
|
||||
import { ProductListItemComponent } from './product-list-item/product-list-item.component';
|
||||
import { ProductModalComponent } from '../sales/components/product-modal/product-modal.component';
|
||||
import { HeaderAdminComponent } from './header-admin/header-admin.component';
|
||||
import { HeaderSalesComponent } from './header-sales/header-sales.component';
|
||||
import { HeaderShoppingComponent } from './header-shopping/header-shopping.component';
|
||||
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [HeaderSystemComponent, ProductListItemComponent, HeaderAdminComponent, HeaderSalesComponent, HeaderShoppingComponent, HeaderShoppingComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
KendoModule,
|
||||
ReactiveFormsModule,
|
||||
FormsModule,
|
||||
],
|
||||
exports: [HeaderSystemComponent, ProductListItemComponent, HeaderAdminComponent, HeaderSalesComponent, HeaderShoppingComponent],
|
||||
schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
|
||||
})
|
||||
export class ComponentModule { }
|
||||
39
src/app/components/header-admin/header-admin.component.html
Normal file
39
src/app/components/header-admin/header-admin.component.html
Normal file
@@ -0,0 +1,39 @@
|
||||
<header class="header-productlist fixed-top">
|
||||
<div class="container d-flex justify-content-between align-items-center py-3">
|
||||
<!-- Logo à esquerda -->
|
||||
<div class="logo-jurunense">
|
||||
<a href="/#/menu" title="Jurunenese">
|
||||
<img [src]="imageLogoBase64" alt="Imagem" class="img-fluid" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Informações do usuário à direita -->
|
||||
<div class="d-flex align-items-center">
|
||||
<!-- Dados do usuário -->
|
||||
<div class="me-3 text-end">
|
||||
<span class="name-user d-block">{{ userName }}</span>
|
||||
<span class="last-access d-block">Loja: {{ storeName }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Dropdown de configurações -->
|
||||
<div class="dropdown">
|
||||
<a
|
||||
class="nav-link dropdown-toggle"
|
||||
href="#"
|
||||
id="navbarDropdownMenuLink"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<img src="assets/img/config.svg" alt="Configurações" class="img-config" />
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownMenuLink">
|
||||
<li>
|
||||
<a class="dropdown-item" (click)="logout()">Sair</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
190
src/app/components/header-admin/header-admin.component.scss
Normal file
190
src/app/components/header-admin/header-admin.component.scss
Normal file
@@ -0,0 +1,190 @@
|
||||
.wrapper {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.header-productlist {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 64px;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
top: 0;
|
||||
background: #131d52;
|
||||
color: #fff;
|
||||
|
||||
.logo-jurunense {
|
||||
img {
|
||||
max-height: 50px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.name-user {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.last-access {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: #848484;
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
img {
|
||||
max-height: 24px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
background-color: #2d2e83;
|
||||
border: none;
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: #ef7d00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.home-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
background: #131d52;
|
||||
|
||||
.text-footer {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.new-order {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background: #ff9521;
|
||||
border-radius: 5px;
|
||||
|
||||
.text-button {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.button-flat {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #ef7d00;
|
||||
box-sizing: border-box;
|
||||
border-radius: 5px;
|
||||
|
||||
.text-button-flat {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
color: #ef7d00;
|
||||
}
|
||||
}
|
||||
|
||||
.button-flat-blue {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #2d2e83;
|
||||
box-sizing: border-box;
|
||||
border-radius: 5px;
|
||||
|
||||
.text-button-flat-blue {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
color: #2d2e83;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsividade */
|
||||
|
||||
/* Smartphones */
|
||||
@media (max-width: 575.98px) {
|
||||
.header-productlist {
|
||||
padding: 10px;
|
||||
|
||||
.logo-jurunense img {
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
.name-user {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.last-access {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.new-order .text-button,
|
||||
.button-flat .text-button-flat,
|
||||
.button-flat-blue .text-button-flat-blue {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablets */
|
||||
@media (max-width: 991.98px) {
|
||||
.header-productlist {
|
||||
padding: 10px 20px;
|
||||
|
||||
.logo-jurunense img {
|
||||
max-width: 150px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktops */
|
||||
@media (min-width: 992px) {
|
||||
.logo-jurunense img {
|
||||
max-width: 170px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HeaderAdminComponent } from './header-admin.component';
|
||||
|
||||
describe('HeaderAdminComponent', () => {
|
||||
let component: HeaderAdminComponent;
|
||||
let fixture: ComponentFixture<HeaderAdminComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ HeaderAdminComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HeaderAdminComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
37
src/app/components/header-admin/header-admin.component.ts
Normal file
37
src/app/components/header-admin/header-admin.component.ts
Normal file
File diff suppressed because one or more lines are too long
42
src/app/components/header-sales/header-sales.component.html
Normal file
42
src/app/components/header-sales/header-sales.component.html
Normal file
@@ -0,0 +1,42 @@
|
||||
<header class="header-productlist fixed-top">
|
||||
<div class="container d-flex justify-content-between align-items-center py-3">
|
||||
<!-- Logo -->
|
||||
<div class="logo-jurunense">
|
||||
<a href="/#/menu" title="Jurunense">
|
||||
<img [src]="imageLogoBase64" alt="Logo Jurunense" class="img-fluid" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Informações do usuário -->
|
||||
<div class="user-info d-flex align-items-center">
|
||||
<!-- Nome do usuário e loja -->
|
||||
<div class="user-details me-3 text-end">
|
||||
<span class="name-user d-block">{{ userName }}</span>
|
||||
<span class="last-access d-block">Loja: {{ storeName }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Carrinho -->
|
||||
<div class="cart me-3 text-center">
|
||||
<kendo-badge-container>
|
||||
<img src="assets/img/cart.svg" alt="Carrinho" class="cart-icon" data-bs-toggle="offcanvas"
|
||||
data-bs-target="#offcanvasRight" aria-controls="offcanvasRight" />
|
||||
<kendo-badge [align]="align" [position]="position" [themeColor]="themeBadge">{{ (shoppingItems$ |
|
||||
async)?.length || 0 }}</kendo-badge>
|
||||
</kendo-badge-container>
|
||||
</div>
|
||||
|
||||
<!-- Dropdown de configurações -->
|
||||
<div class="dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button"
|
||||
data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<img src="assets/img/config.svg" alt="Configurações" class="img-config" />
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownMenuLink">
|
||||
<li>
|
||||
<a class="dropdown-item" (click)="logout()">Sair</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
85
src/app/components/header-sales/header-sales.component.scss
Normal file
85
src/app/components/header-sales/header-sales.component.scss
Normal file
@@ -0,0 +1,85 @@
|
||||
.header-productlist {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 64px;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
top: 0;
|
||||
background: #131d52;
|
||||
color: #ffffff;
|
||||
z-index: 1000;
|
||||
|
||||
.logo-jurunense img {
|
||||
max-height: 50px;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.user-details {
|
||||
text-align: right;
|
||||
|
||||
.name-user {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.last-access {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: #848484;
|
||||
}
|
||||
}
|
||||
|
||||
.cart {
|
||||
position: relative;
|
||||
|
||||
.cart-icon {
|
||||
max-height: 24px;
|
||||
width: auto;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
kendo-badge {
|
||||
position: absolute;
|
||||
top: -13px;
|
||||
right: -13px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
img {
|
||||
max-height: 24px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
background-color: #2d2e83;
|
||||
border: none;
|
||||
|
||||
a {
|
||||
color: #ffffff;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: #ef7d00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HeaderSalesComponent } from './header-sales.component';
|
||||
|
||||
describe('HeaderSalesComponent', () => {
|
||||
let component: HeaderSalesComponent;
|
||||
let fixture: ComponentFixture<HeaderSalesComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ HeaderSalesComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HeaderSalesComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
54
src/app/components/header-sales/header-sales.component.ts
Normal file
54
src/app/components/header-sales/header-sales.component.ts
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,205 @@
|
||||
<header class="header-productlist fixed-top">
|
||||
<div class="container">
|
||||
<div class="row g-0 align-items-center">
|
||||
<!-- Logo and Menu -->
|
||||
<div class="col-6 col-md-2 d-flex align-items-center logo-jurunense">
|
||||
<div class="btn-menu">
|
||||
<button class="menu-toggle me-3 d-flex align-items-center" (click)="openMenu()">
|
||||
<img src="assets/img/menu.svg" alt="Menu" width="24" height="24" />
|
||||
</button>
|
||||
</div>
|
||||
<div class="logo-jurunense">
|
||||
<a href="/#/sales/home" title="Jurunenese">
|
||||
<img [src]="imageLogoBase64" alt="Imagem" class="img-fluid" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Search Section para desktops -->
|
||||
<div class="col-md-8 px-5 d-none d-md-flex">
|
||||
<kendo-textbox class="search-product-desktop" [formControl]="searchProduct"
|
||||
placeholder="Pesquise o produto desejado por aqui" (keydown.enter)="onSearch()">
|
||||
<ng-template kendoTextBoxSuffixTemplate>
|
||||
<button kendoButton fillMode="clear" icon="search" (click)="onSearch()"></button>
|
||||
</ng-template>
|
||||
</kendo-textbox>
|
||||
</div>
|
||||
|
||||
<!-- User Info and Cart -->
|
||||
<div class="col-6 col-md-2 d-flex justify-content-end align-items-center">
|
||||
<!-- Carrinho -->
|
||||
<div class="d-flex align-items-center">
|
||||
<kendo-badge-container>
|
||||
<img src="assets/img/cart.svg" alt="Carrinho" data-bs-toggle="offcanvas"
|
||||
data-bs-target="#offcanvasRight" aria-controls="offcanvasRight" />
|
||||
<kendo-badge [align]="align" [position]="position" [themeColor]="themeBadge">
|
||||
{{ (shopping$ | async).length }}
|
||||
</kendo-badge>
|
||||
</kendo-badge-container>
|
||||
</div>
|
||||
|
||||
<!-- Avatar com dropdown para dispositivos móveis -->
|
||||
<!-- <div class="info-user">
|
||||
<div class="dropdown ms-3">
|
||||
<button class="btn dropdown-toggle p-0" id="userMenuDropdown" type="button"
|
||||
data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<kendo-avatar [imageSrc]="'https://i.pravatar.cc/150?img=7'" [size]="'medium'"
|
||||
[shape]="'circle'" title="{{ userName }}"></kendo-avatar>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userMenuDropdown">
|
||||
<li class="dropdown-header">
|
||||
<span class="username"><strong>{{ userName }}</strong></span>
|
||||
<div class="text-muted"><span class="loja">Loja: {{ storeName }}</span></div>
|
||||
</li>
|
||||
<hr>
|
||||
<li><a class="dropdown-item" href="/#/profile">Perfil</a></li>
|
||||
<li><a class="dropdown-item" href="/#/settings">Configurações</a></li>
|
||||
<li><a class="dropdown-item" (click)="logout()">Sair</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div> -->
|
||||
|
||||
|
||||
<!-- Nome do usuário e loja -->
|
||||
<div class="user-details me-3 text-end">
|
||||
<span class="name-user d-block">{{ userName }}</span>
|
||||
<span class="last-access d-block">Loja: {{ storeName }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Dropdown de configurações -->
|
||||
<div class="dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button"
|
||||
data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<img src="assets/img/config.svg" alt="Configurações" class="img-config" />
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownMenuLink">
|
||||
<li>
|
||||
<a class="dropdown-item" (click)="logout()">Sair</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Search Section para dispositivos móveis e tablets -->
|
||||
<div class="col-12 mt-3">
|
||||
<kendo-textbox class="search-product" [formControl]="searchProduct"
|
||||
placeholder="Pesquise o produto desejado por aqui" (keydown.enter)="onSearch()">
|
||||
<ng-template kendoTextBoxSuffixTemplate>
|
||||
<button kendoButton fillMode="clear" icon="search" (click)="onSearch()"></button>
|
||||
</ng-template>
|
||||
</kendo-textbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal de Menu -->
|
||||
<div class="menu-modal" [ngClass]="{'open': isMenuOpen, 'close': !isMenuOpen}">
|
||||
<div class="menu-content">
|
||||
<!-- Cabeçalho do Modal -->
|
||||
<div class="menu-header">
|
||||
<div class="user-info">
|
||||
<img src="https://via.placeholder.com/64" alt="Avatar" class="user-avatar" />
|
||||
<div class="user-text">
|
||||
<span class="bold-text">{{ userName }}</span>
|
||||
<span class="subtitle">Loja: {{ storeName }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<button class="close-btn" (click)="closeMenu()">×</button>
|
||||
</div>
|
||||
|
||||
<!-- Botões de Entrar e Cadastrar -->
|
||||
<div class="menu-buttons">
|
||||
<button class="btn-enter" (click)="logout()">Sair</button>
|
||||
<button class="btn-register" (click)="closeMenu()">Voltar</button>
|
||||
</div>
|
||||
|
||||
<!-- Lista de Links -->
|
||||
<ul class="menu-links">
|
||||
<!-- <li>
|
||||
<a href="#">Nossas lojas</a>
|
||||
<i class="fa-solid fa-chevron-right icon"></i>
|
||||
</li>
|
||||
<hr /> -->
|
||||
|
||||
<li>
|
||||
<a href="/#/product-list" (click)="applyFilter({ urlCategory: [] })"><strong>Todos os
|
||||
departamentos</strong></a>
|
||||
<i class="fa-solid fa-chevron-right icon"></i>
|
||||
</li>
|
||||
<hr />
|
||||
|
||||
<!-- Lista Dinâmica -->
|
||||
<li *ngFor="let department of departments">
|
||||
<a href="/#/product-list" (click)="applyFilter({ urlCategory: department.path })">{{ department.text
|
||||
}}</a>
|
||||
<i class="fa-solid fa-chevron-right icon"></i>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Filtros Adicionais -->
|
||||
<div class="menu-filters">
|
||||
<legend class="k-form-legend mt-3">Marcas</legend>
|
||||
<div *ngIf="brands && brands.length > 0">
|
||||
<kendo-treeview kendoTreeViewHierarchyBinding [nodes]="brands" textField="text"
|
||||
[kendoTreeViewCheckable]="{ mode: 'multiple' }" [(checkedKeys)]="selectedBrandKeys"
|
||||
(checkedChange)="applyFilter({ brands: selectedBrandKeys })">
|
||||
</kendo-treeview>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Filtros Gerais -->
|
||||
<div class="filters-section">
|
||||
<legend class="k-form-legend mt-3">Filtros</legend>
|
||||
|
||||
<label class="k-label d-block">
|
||||
<input type="checkbox" kendoCheckBox [(ngModel)]="onlyWithStock" />
|
||||
<span class="ms-2">Somente produtos com estoque</span>
|
||||
</label>
|
||||
|
||||
<label class="k-label d-block mt-2">
|
||||
<span>Filial de estoque</span>
|
||||
<kendo-combobox [data]="store$ | async" textField="id" valueField="id"
|
||||
(selectionChange)="selectedStore($event)">
|
||||
</kendo-combobox>
|
||||
</label>
|
||||
|
||||
<label class="k-label d-block mt-2">
|
||||
<input type="checkbox" kendoCheckBox [(ngModel)]="productPromotion" />
|
||||
<span class="ms-2">Produtos em promoção</span>
|
||||
</label>
|
||||
|
||||
<label class="k-label d-block mt-2">
|
||||
<span>Faixa de desconto</span>
|
||||
<kendo-rangeslider [(ngModel)]="percentOff" [min]="minPercentOff" [max]="maxPercentOff"
|
||||
[smallStep]="smallStep" [largeStep]="largeStep">
|
||||
</kendo-rangeslider>
|
||||
</label>
|
||||
|
||||
<label class="k-label d-block mt-2">
|
||||
<input type="checkbox" kendoCheckBox [(ngModel)]="markdown" />
|
||||
<span class="ms-2">Produtos que baixaram de preço</span>
|
||||
</label>
|
||||
|
||||
<label class="k-label d-block mt-2">
|
||||
<input type="checkbox" kendoCheckBox [(ngModel)]="oportunity" />
|
||||
<span class="ms-2">Oportunidades</span>
|
||||
</label>
|
||||
|
||||
<label class="k-label d-block mt-2">
|
||||
<input type="checkbox" kendoCheckBox [(ngModel)]="offers" />
|
||||
<span class="ms-2">Ofertas imperdíveis</span>
|
||||
</label>
|
||||
|
||||
<!-- Botão de Aplicar -->
|
||||
<div class="apply-filters mt-4">
|
||||
<button kendoButton class="w-100" (click)="getFilterProducts()">
|
||||
Aplicar Filtros
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
@@ -0,0 +1,490 @@
|
||||
.header-productlist {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 16px;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
top: 0;
|
||||
background: #131d52;
|
||||
color: #ffffff;
|
||||
z-index: 1000;
|
||||
|
||||
.menu-toggle {
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.search-product {
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
border-radius: 5px;
|
||||
padding: 0 10px;
|
||||
background-color: #ffffff;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.name-user {
|
||||
font-size: 12px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
kendo-badge {
|
||||
position: absolute;
|
||||
top: -11px;
|
||||
right: -11px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.last-access {
|
||||
font-size: 10px;
|
||||
color: #848484;
|
||||
}
|
||||
|
||||
.center {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
position: absolute;
|
||||
background: #ffffff;
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
background-color: #2d2e83;
|
||||
border: none;
|
||||
|
||||
.dropdown-item {
|
||||
color: #ffffff;
|
||||
|
||||
&:hover {
|
||||
color: #ef7d00;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-menu {
|
||||
padding: 1px;
|
||||
display: flex;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 30px;
|
||||
}
|
||||
|
||||
.username {
|
||||
font-size: 12px;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.loja {
|
||||
font-size: 11px;
|
||||
color: #f4f4f4;
|
||||
}
|
||||
}
|
||||
|
||||
/* Modal Fullscreen */
|
||||
.menu-modal {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: #fff;
|
||||
z-index: 1050;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
transform: translateX(-100%);
|
||||
transition: transform 0.5s ease;
|
||||
}
|
||||
|
||||
/* Classe para abrir o modal */
|
||||
.menu-modal.open {
|
||||
transform: translateX(0);
|
||||
}
|
||||
|
||||
/* Classe para fechar o modal */
|
||||
.menu-modal.close {
|
||||
transform: translateX(-100%);
|
||||
}
|
||||
|
||||
/* Conteúdo do Menu */
|
||||
.menu-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 20px;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
/* Cabeçalho do Menu */
|
||||
.menu-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
border-radius: 50%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.user-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.bold-text {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* Botões: Entrar e Cadastrar */
|
||||
.menu-buttons {
|
||||
display: flex;
|
||||
/* Flexbox para alinhar os botões */
|
||||
justify-content: space-between;
|
||||
/* Espaço entre os botões */
|
||||
gap: 10px;
|
||||
/* Espaçamento entre os botões */
|
||||
width: 100%;
|
||||
/* Ocupa 100% da largura */
|
||||
margin: 10px 0;
|
||||
/* Espaçamento acima e abaixo */
|
||||
}
|
||||
|
||||
.btn-enter,
|
||||
.btn-register {
|
||||
flex: 1;
|
||||
/* Cada botão ocupa a mesma largura */
|
||||
padding: 10px 0;
|
||||
/* Espaçamento interno vertical */
|
||||
text-align: center;
|
||||
/* Alinhamento do texto */
|
||||
font-size: 16px;
|
||||
/* Tamanho da fonte */
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.btn-enter {
|
||||
background-color: #131d52;
|
||||
color: #fff;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn-register {
|
||||
background: transparent;
|
||||
color: #131d52;
|
||||
border: 2px solid #131d52;
|
||||
}
|
||||
|
||||
.btn-enter:hover,
|
||||
.btn-register:hover {
|
||||
opacity: 0.9;
|
||||
/* Efeito ao passar o mouse */
|
||||
}
|
||||
|
||||
/* Lista de Links */
|
||||
.menu-links {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.menu-item {
|
||||
// flex-direction: row;
|
||||
flex: 1;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.menu-links li {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
/* Texto à esquerda, ícone à direita */
|
||||
align-items: center;
|
||||
padding: 15px 20px;
|
||||
border-bottom: 1px solid #f1f1f1;
|
||||
transition: background-color 0.3s ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu-links li:hover {
|
||||
background-color: #f5f5f5;
|
||||
/* Cor ao passar o mouse */
|
||||
}
|
||||
|
||||
.menu-links a {
|
||||
text-decoration: none;
|
||||
/* Remove sublinhado */
|
||||
color: #333;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
flex-grow: 1;
|
||||
/* Garante que o texto use o espaço restante */
|
||||
}
|
||||
|
||||
.menu-links a:hover {
|
||||
color: #131d52;
|
||||
/* Cor principal ao hover */
|
||||
}
|
||||
|
||||
.menu-links .icon {
|
||||
font-size: 14px;
|
||||
color: #999;
|
||||
/* Cor do ícone */
|
||||
transition: transform 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
.menu-links li:hover .icon {
|
||||
color: #131d52;
|
||||
/* Cor ao hover */
|
||||
transform: translateX(5px);
|
||||
/* Desliza o ícone para direita */
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
hr {
|
||||
border: 0;
|
||||
border-top: 1px solid #ddd;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
/* Botão de Fechar */
|
||||
.close-btn {
|
||||
font-size: 24px;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
|
||||
/* Smartphones */
|
||||
@media (max-width: 575.98px) {
|
||||
.header-productlist {
|
||||
flex-wrap: wrap;
|
||||
|
||||
.menu-toggle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.logo-jurunense img {
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
.search-product {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.search-product-desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.name-user,
|
||||
.last-access {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info-user-desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info-user {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-content {
|
||||
padding: 10px;
|
||||
/* Reduz o padding */
|
||||
font-size: 12px;
|
||||
/* Fonte geral menor */
|
||||
}
|
||||
|
||||
.k-form-legend {
|
||||
font-size: 12px;
|
||||
/* Tamanho menor para legendas */
|
||||
}
|
||||
|
||||
.menu-buttons {
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.btn-enter,
|
||||
.btn-register {
|
||||
font-size: 12px;
|
||||
padding: 6px;
|
||||
}
|
||||
|
||||
/* Lista de marcas */
|
||||
.kendo-treeview {
|
||||
max-height: 200px;
|
||||
/* Reduz altura */
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
/* Inputs e checkboxes menores */
|
||||
label.k-label {
|
||||
font-size: 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
transform: scale(0.8);
|
||||
/* Menor */
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
kendo-combobox,
|
||||
kendo-rangeslider {
|
||||
width: 100%;
|
||||
transform: scale(0.85);
|
||||
/* Reduz tamanho */
|
||||
}
|
||||
|
||||
kendo-rangeslider {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
/* Ajusta espaçamento das legendas */
|
||||
legend {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
/* Botão de aplicar filtros */
|
||||
button[kendoButton] {
|
||||
width: 100%;
|
||||
font-size: 12px;
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablets */
|
||||
@media (max-width: 991.98px) {
|
||||
.header-productlist {
|
||||
flex-wrap: wrap;
|
||||
|
||||
.menu-toggle {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.logo-jurunense img {
|
||||
max-width: 150px;
|
||||
}
|
||||
|
||||
.search-product {
|
||||
margin-top: 5px;
|
||||
margin-bottom: 10px;
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.search-product-desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.name-user,
|
||||
.last-access {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info-user-desktop {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info-user {
|
||||
display: block;
|
||||
}
|
||||
|
||||
}
|
||||
.dropdown-toggle,
|
||||
.user-details {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.dropdown-menu,
|
||||
.user-details {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktops */
|
||||
@media (min-width: 992px) {
|
||||
.header-productlist {
|
||||
flex-wrap: nowrap;
|
||||
|
||||
.menu-toggle {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.logo-jurunense img {
|
||||
max-width: 170px;
|
||||
}
|
||||
|
||||
.search-product {
|
||||
margin: 0 auto;
|
||||
margin-bottom: 0;
|
||||
order: 0;
|
||||
}
|
||||
|
||||
.search-product {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.btn-menu {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.info-user {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.name-user,
|
||||
.last-access {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HeaderShoppingComponent } from './header-shopping.component';
|
||||
|
||||
describe('HeaderShoppingComponent', () => {
|
||||
let component: HeaderShoppingComponent;
|
||||
let fixture: ComponentFixture<HeaderShoppingComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ HeaderShoppingComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HeaderShoppingComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
226
src/app/components/header-shopping/header-shopping.component.ts
Normal file
226
src/app/components/header-shopping/header-shopping.component.ts
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,48 @@
|
||||
<header class="header-productlist fixed-top">
|
||||
<div class="container d-flex justify-content-between align-items-center py-3">
|
||||
<!-- Logo à esquerda -->
|
||||
<div class="logo-jurunense">
|
||||
<a href="/" title="Jurunenese">
|
||||
<img [src]="imageLogoBase64" alt="Imagem" class="img-fluid" />
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<!-- Informações do usuário à direita -->
|
||||
<div class="d-flex align-items-center">
|
||||
<!-- Carrinho -->
|
||||
<div class="d-flex align-items-center">
|
||||
<kendo-badge-container>
|
||||
<img src="assets/img/cart.svg" alt="Carrinho" data-bs-toggle="offcanvas"
|
||||
data-bs-target="#offcanvasRight" aria-controls="offcanvasRight" />
|
||||
<kendo-badge [align]="align" [position]="position" [themeColor]="themeBadge">
|
||||
{{ (shopping$ | async).length }}
|
||||
</kendo-badge>
|
||||
</kendo-badge-container>
|
||||
</div>
|
||||
<!-- Dados do usuário -->
|
||||
<div class="me-3 text-end">
|
||||
<span class="name-user d-block">{{ userName }}</span>
|
||||
<span class="last-access d-block">Loja: {{ storeName }}</span>
|
||||
</div>
|
||||
|
||||
<!-- Dropdown de configurações -->
|
||||
<div class="dropdown">
|
||||
<a
|
||||
class="nav-link dropdown-toggle"
|
||||
href="#"
|
||||
id="navbarDropdownMenuLink"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<img src="assets/img/config.svg" alt="Configurações" class="img-config" />
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownMenuLink">
|
||||
<li>
|
||||
<a class="dropdown-item" (click)="logout()">Sair</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
197
src/app/components/header-system/header-system.component.scss
Normal file
197
src/app/components/header-system/header-system.component.scss
Normal file
@@ -0,0 +1,197 @@
|
||||
.wrapper {
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.header-productlist {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 10px 64px;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
height: 80px;
|
||||
top: 0;
|
||||
background: #131d52;
|
||||
color: #fff;
|
||||
|
||||
.logo-jurunense {
|
||||
img {
|
||||
max-height: 50px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.name-user {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 14px;
|
||||
line-height: 19px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.last-access {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
color: #848484;
|
||||
}
|
||||
|
||||
.dropdown-toggle {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: none;
|
||||
border: none;
|
||||
|
||||
img {
|
||||
max-height: 24px;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
background-color: #2d2e83;
|
||||
border: none;
|
||||
|
||||
a {
|
||||
color: #fff;
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
color: #ef7d00;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.home-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
background: #131d52;
|
||||
|
||||
.text-footer {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-size: 10px;
|
||||
line-height: 14px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
/* Buttons */
|
||||
.new-order {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background: #ff9521;
|
||||
border-radius: 5px;
|
||||
|
||||
.text-button {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.button-flat {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #ef7d00;
|
||||
box-sizing: border-box;
|
||||
border-radius: 5px;
|
||||
|
||||
.text-button-flat {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
color: #ef7d00;
|
||||
}
|
||||
}
|
||||
|
||||
.button-flat-blue {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #2d2e83;
|
||||
box-sizing: border-box;
|
||||
border-radius: 5px;
|
||||
|
||||
.text-button-flat-blue {
|
||||
font-family: "Open Sans", sans-serif;
|
||||
font-weight: 700;
|
||||
font-size: 16px;
|
||||
line-height: 22px;
|
||||
text-align: center;
|
||||
color: #2d2e83;
|
||||
}
|
||||
}
|
||||
|
||||
/* Responsividade */
|
||||
|
||||
/* Smartphones */
|
||||
@media (max-width: 575.98px) {
|
||||
.header-productlist {
|
||||
padding: 10px;
|
||||
|
||||
.logo-jurunense img {
|
||||
max-width: 120px;
|
||||
}
|
||||
|
||||
.name-user {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.last-access {
|
||||
font-size: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.new-order .text-button,
|
||||
.button-flat .text-button-flat,
|
||||
.button-flat-blue .text-button-flat-blue {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
kendo-badge {
|
||||
position: absolute;
|
||||
top: -11px;
|
||||
right: -11px;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
/* Tablets */
|
||||
@media (max-width: 991.98px) {
|
||||
.header-productlist {
|
||||
padding: 10px 20px;
|
||||
|
||||
.logo-jurunense img {
|
||||
max-width: 150px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Desktops */
|
||||
@media (min-width: 992px) {
|
||||
.logo-jurunense img {
|
||||
max-width: 170px;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { HeaderSystemComponent } from './header-system.component';
|
||||
|
||||
describe('HeaderSystemComponent', () => {
|
||||
let component: HeaderSystemComponent;
|
||||
let fixture: ComponentFixture<HeaderSystemComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ HeaderSystemComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(HeaderSystemComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
108
src/app/components/header-system/header-system.component.ts
Normal file
108
src/app/components/header-system/header-system.component.ts
Normal file
File diff suppressed because one or more lines are too long
@@ -0,0 +1,9 @@
|
||||
<div class="product">
|
||||
<div class="description">
|
||||
<div class="product-name">{{ product.description }}</div>
|
||||
<div class="category-name">{{ product.category }}</div>
|
||||
</div>
|
||||
<div class="price">
|
||||
<div>{{ product.salePrice | currency }}</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,27 @@
|
||||
.product {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border-bottom-width: 1px;
|
||||
border-bottom-color: #ebebeb;
|
||||
border-bottom-style: solid;
|
||||
z-index: 9999;
|
||||
}
|
||||
.description {
|
||||
flex: 1;
|
||||
z-index: 9999;
|
||||
}
|
||||
.category-name {
|
||||
font-size: 12px;
|
||||
}
|
||||
.product-name {
|
||||
font-size: 16px;
|
||||
}
|
||||
.product-name,
|
||||
.price {
|
||||
height: auto;
|
||||
font-weight: bold;
|
||||
}
|
||||
.product {
|
||||
padding: 12px;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/* tslint:disable:no-unused-variable */
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
|
||||
import { ProductListItemComponent } from './product-list-item.component';
|
||||
|
||||
describe('ProductListItemComponent', () => {
|
||||
let component: ProductListItemComponent;
|
||||
let fixture: ComponentFixture<ProductListItemComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ ProductListItemComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(ProductListItemComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { SaleProduct } from 'src/app/models/sale-product.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-product-list-item',
|
||||
templateUrl: './product-list-item.component.html',
|
||||
styleUrls: ['./product-list-item.component.scss']
|
||||
})
|
||||
export class ProductListItemComponent implements OnInit {
|
||||
@Input() public product: SaleProduct;
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
22
src/app/crm/crm-routing.module.ts
Normal file
22
src/app/crm/crm-routing.module.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
import { CustomerComponent } from './customer/customer.component';
|
||||
import { EditCustomerComponent } from './edit-customer/edit-customer.component';
|
||||
import { MenuCrmComponent } from './menu-crm/menu-crm.component';
|
||||
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '', component: MenuCrmComponent,
|
||||
children: [
|
||||
{ path: 'customer', component: CustomerComponent },
|
||||
{ path: 'customer/edit', component: EditCustomerComponent },
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class CrmRoutingModule { }
|
||||
23
src/app/crm/crm.module.ts
Normal file
23
src/app/crm/crm.module.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { CrmRoutingModule } from './crm-routing.module';
|
||||
import { MenuCrmComponent } from './menu-crm/menu-crm.component';
|
||||
import { ComponentModule } from '../components/component.module';
|
||||
import { CustomerComponent } from './customer/customer.component';
|
||||
import { KendoModule } from '../shared/kendo.module';
|
||||
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
|
||||
import { EditCustomerComponent } from './edit-customer/edit-customer.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [MenuCrmComponent, CustomerComponent, EditCustomerComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
CrmRoutingModule,
|
||||
ComponentModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
KendoModule,
|
||||
]
|
||||
})
|
||||
export class CrmModule { }
|
||||
94
src/app/crm/customer/customer.component.html
Normal file
94
src/app/crm/customer/customer.component.html
Normal file
@@ -0,0 +1,94 @@
|
||||
<div class="container mt-3 my-5">
|
||||
<div>
|
||||
<span class="title">Lista de clientes</span>
|
||||
</div>
|
||||
|
||||
<div class="mt-2 w-100" class="border-radius: 20px;">
|
||||
<form [formGroup]="searchForm">
|
||||
<kendo-textbox
|
||||
class="w-100 border"
|
||||
placeholder="Informe os dados para localizar os clientes"
|
||||
type="text"
|
||||
formControlName="textSearch"
|
||||
(keydown)="searchCustomer($event)"
|
||||
>
|
||||
<ng-template kendoTextBoxPrefixTemplate>
|
||||
<kendo-icon name="search"></kendo-icon>
|
||||
</ng-template>
|
||||
<ng-template kendoTextBoxSuffixTemplate>
|
||||
<div class="example-wrapper">
|
||||
<kendo-combobox
|
||||
[data]="listItems"
|
||||
style="width: 250px"
|
||||
formControlName="search"
|
||||
>
|
||||
</kendo-combobox>
|
||||
</div>
|
||||
</ng-template>
|
||||
</kendo-textbox>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<div class="mt-2">
|
||||
<ng-container>
|
||||
<kendo-grid
|
||||
style="height: calc(100vh - 280px)"
|
||||
[data]="customer$ | async"
|
||||
[pageSize]="20"
|
||||
[pageable]="true"
|
||||
[sortable]="true"
|
||||
[reorderable]="true"
|
||||
[resizable]="true"
|
||||
[columnMenu]="{ filter: true }"
|
||||
>
|
||||
<kendo-grid-column field="customerId" title="Código" [width]="30">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<div>{{ dataItem.customerId }}</div>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="name" title="Nome" [width]="150">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<div>{{ dataItem.name }}</div>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
|
||||
<kendo-grid-column field="cpfcnpj" title="CPF / CNPJ" [width]="60">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<div>{{ dataItem.cpfCnpj }}</div>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
|
||||
<kendo-grid-column field="phone" title="Telefone" [width]="60">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<div>{{ dataItem.phone }}</div>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
|
||||
<kendo-grid-column field="cellPhone" title="Celular" [width]="60">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<div>{{ dataItem.cellPhone }}</div>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
<kendo-grid-column field="cellPhone" title="Ações" [width]="50">
|
||||
<ng-template kendoGridCellTemplate let-dataItem>
|
||||
<div>
|
||||
<a href="/crm/customer/edit">
|
||||
<kendo-avatar shape="circle" initials="">
|
||||
<kendo-icon name="edit"></kendo-icon>
|
||||
</kendo-avatar>
|
||||
</a>
|
||||
</div>
|
||||
</ng-template>
|
||||
</kendo-grid-column>
|
||||
</kendo-grid>
|
||||
</ng-container>
|
||||
|
||||
<kendo-floatingactionbutton
|
||||
icon="add"
|
||||
text="Novo cliente"
|
||||
[align]="{ horizontal: 'end', vertical: 'bottom' }"
|
||||
positionMode="absolute"
|
||||
>
|
||||
</kendo-floatingactionbutton>
|
||||
</div>
|
||||
</div>
|
||||
13
src/app/crm/customer/customer.component.scss
Normal file
13
src/app/crm/customer/customer.component.scss
Normal file
@@ -0,0 +1,13 @@
|
||||
.title {
|
||||
width: 810px;
|
||||
height: 49px;
|
||||
|
||||
font-family: Montserrat;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-size: 40px;
|
||||
line-height: 49px;
|
||||
color: rgba(107, 110, 190, 1);
|
||||
;
|
||||
}
|
||||
|
||||
25
src/app/crm/customer/customer.component.spec.ts
Normal file
25
src/app/crm/customer/customer.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CustomerComponent } from './customer.component';
|
||||
|
||||
describe('CustomerComponent', () => {
|
||||
let component: CustomerComponent;
|
||||
let fixture: ComponentFixture<CustomerComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CustomerComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CustomerComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
55
src/app/crm/customer/customer.component.ts
Normal file
55
src/app/crm/customer/customer.component.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';
|
||||
import { FabAlign } from '@progress/kendo-angular-buttons';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Customer } from 'src/app/models/customer.model';
|
||||
import { CustomerService } from 'src/app/services/customer.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-customer',
|
||||
templateUrl: './customer.component.html',
|
||||
styleUrls: ['./customer.component.scss']
|
||||
})
|
||||
export class CustomerComponent implements OnInit {
|
||||
public listItems: Array<string> = [
|
||||
'Nome',
|
||||
'CPF',
|
||||
'Telefone',
|
||||
'Celular'
|
||||
];
|
||||
public listFields: Array<string> = [
|
||||
'name',
|
||||
'document',
|
||||
'phone',
|
||||
'cellPhone'
|
||||
];
|
||||
public topEnd: FabAlign = { vertical: 'top', horizontal: 'end' };
|
||||
customer$: Observable<Customer[]>;
|
||||
public errorObject = null;
|
||||
public isloading = false;
|
||||
public searchForm: FormGroup;
|
||||
|
||||
constructor(private customerService: CustomerService) {
|
||||
this.searchForm = new FormGroup({
|
||||
search: new FormControl(),
|
||||
textSearch: new FormControl(),
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
searchCustomer(event){
|
||||
if (event.keyCode === 13) {
|
||||
console.log(this.searchForm.value);
|
||||
const indice = this.listItems.indexOf(this.searchForm.get('search').value);
|
||||
const field = this.listFields[indice];
|
||||
const textSearh = this.searchForm.get('textSearch').value;
|
||||
this.customer$ = this.customerService.getCustomerByQuery(field, textSearh);
|
||||
// const filter: FilterProduct = { brands: [], text: this.searchProduct.value };
|
||||
// this.getSaleProducts(filter);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
200
src/app/crm/edit-customer/edit-customer.component.html
Normal file
200
src/app/crm/edit-customer/edit-customer.component.html
Normal file
@@ -0,0 +1,200 @@
|
||||
<div class="container">
|
||||
<form
|
||||
class="k-form m-3 p-3"
|
||||
style="background-color: white"
|
||||
[formGroup]="form"
|
||||
>
|
||||
<fieldset class="k-form-fieldset">
|
||||
<legend class="k-form-legend">Cadastro de cliente</legend>
|
||||
|
||||
<div class="col-12 col-sm-12 col-md-8">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6 col-md-6">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="cpf" text="CPF / CNPJ"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="username"
|
||||
#cpf
|
||||
required
|
||||
></kendo-textbox>
|
||||
<kendo-formerror
|
||||
>Error: Número do CPF é obrigatório</kendo-formerror
|
||||
>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
<div class="ccol-12 col-sm-6 col-md-6">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="ie" text="Insc Estadual"></kendo-label>
|
||||
<kendo-textbox formControlName="numberState" #ie></kendo-textbox>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-12 col-md-6">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="name" text="Nome"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="name"
|
||||
[clearButton]="true"
|
||||
#name
|
||||
required
|
||||
></kendo-textbox>
|
||||
<kendo-formerror
|
||||
>Error: O nome do cliente é obrigatório</kendo-formerror
|
||||
>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
|
||||
<div class="col-6 col-sm-6 col-md-6">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="phone" text="Telefone"></kendo-label>
|
||||
<kendo-textbox formControlName="cellPhone" #phone></kendo-textbox>
|
||||
</kendo-formfield>
|
||||
|
||||
<kendo-formfield>
|
||||
<div class="k-form-field-checkbox-wrap">
|
||||
<input
|
||||
kendoCheckBox
|
||||
id="whatsapp1"
|
||||
type="checkbox"
|
||||
formControlName="whatsapp"
|
||||
/>
|
||||
<kendo-label
|
||||
class="k-checkbox-label"
|
||||
for="whatsapp1"
|
||||
text="Telefone cadastrado no whatsapp?"
|
||||
></kendo-label>
|
||||
</div>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
|
||||
<div class="col-12 col-sm-12 col-md-8">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="email" text="E-Mail"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="email"
|
||||
[clearButton]="true"
|
||||
#email
|
||||
required
|
||||
></kendo-textbox>
|
||||
<kendo-formerror>Error: Informe um email do cliente</kendo-formerror>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
<legend class="k-form-legend mt-5">Endereço</legend>
|
||||
<div class="col-6 col-sm-3 col-md-2">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="zipcode" text="CEP"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="cep"
|
||||
#zipcode
|
||||
required
|
||||
></kendo-textbox>
|
||||
<kendo-formerror
|
||||
>Error: Informe um CEP para o endereço do cliente</kendo-formerror
|
||||
>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="address" text="Endereço"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="address"
|
||||
#address
|
||||
required
|
||||
></kendo-textbox>
|
||||
<kendo-formerror
|
||||
>Error: Informe o endereço do cliente</kendo-formerror
|
||||
>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="number" text="Número"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="addressNumber"
|
||||
#number
|
||||
required
|
||||
></kendo-textbox>
|
||||
<kendo-formerror
|
||||
>Error: Informe o número do endereço do cliente</kendo-formerror
|
||||
>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="neighborhood" text="Bairro"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="neighborhood"
|
||||
#neighborhood
|
||||
required
|
||||
></kendo-textbox>
|
||||
<kendo-formerror
|
||||
>Error: Informe o bairro do endereço</kendo-formerror
|
||||
>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="complement" text="Complemento"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="complement"
|
||||
#complement
|
||||
></kendo-textbox>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="city" text="Cidade"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="city"
|
||||
#city
|
||||
></kendo-textbox>
|
||||
<kendo-formerror
|
||||
>Error: Informe a cidade do endereço</kendo-formerror
|
||||
>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<kendo-formfield>
|
||||
<kendo-label [for]="state" text="Estado"></kendo-label>
|
||||
<kendo-textbox
|
||||
formControlName="state"
|
||||
#state
|
||||
></kendo-textbox>
|
||||
</kendo-formfield>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<kendo-formfield>
|
||||
<div class="k-form-field-checkbox-wrap">
|
||||
<input
|
||||
kendoCheckBox
|
||||
id="notications"
|
||||
type="checkbox"
|
||||
formControlName="notifications"
|
||||
/>
|
||||
<kendo-label
|
||||
class="k-checkbox-label"
|
||||
for="notications"
|
||||
text="Deseja participar do programa de fidelidade?"
|
||||
></kendo-label>
|
||||
</div>
|
||||
</kendo-formfield>
|
||||
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
25
src/app/crm/edit-customer/edit-customer.component.spec.ts
Normal file
25
src/app/crm/edit-customer/edit-customer.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { EditCustomerComponent } from './edit-customer.component';
|
||||
|
||||
describe('EditCustomerComponent', () => {
|
||||
let component: EditCustomerComponent;
|
||||
let fixture: ComponentFixture<EditCustomerComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ EditCustomerComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(EditCustomerComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
196
src/app/crm/edit-customer/edit-customer.component.ts
Normal file
196
src/app/crm/edit-customer/edit-customer.component.ts
Normal file
@@ -0,0 +1,196 @@
|
||||
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
|
||||
import { FormControl, FormGroup, Validators } from '@angular/forms';
|
||||
import { DialogService } from '@progress/kendo-angular-dialog';
|
||||
import { EMPTY, throwError } from 'rxjs';
|
||||
import { catchError, map, switchMap, take, tap } from 'rxjs/operators';
|
||||
import { Customer } from 'src/app/models/customer.model';
|
||||
import { CustomerService } from 'src/app/services/customer.service';
|
||||
import { MessageService } from 'src/app/services/messages.service';
|
||||
import { ConsultaCepService } from 'src/app/shared/services/consulta-cep.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-edit-customer',
|
||||
templateUrl: './edit-customer.component.html',
|
||||
styleUrls: ['./edit-customer.component.scss']
|
||||
})
|
||||
export class EditCustomerComponent implements OnInit {
|
||||
public phoneNumberValue = '';
|
||||
public phoneNumberMask = '(99) 00000-0000';
|
||||
public cpfMask = '000.000.000-00';
|
||||
public cnpjMask = '00.000.000/0000-00';
|
||||
public customer: Customer;
|
||||
public isloading = false;
|
||||
public errorObject: any;
|
||||
public result;
|
||||
loaderVisible = false;
|
||||
@ViewChild('formCustomer') formCustomer: ElementRef;
|
||||
@ViewChild('inputCpf') inputCpf: ElementRef;
|
||||
|
||||
public form: FormGroup;
|
||||
|
||||
public customerData: any = {
|
||||
company: false,
|
||||
cpfCnpj: '',
|
||||
name: '',
|
||||
numberState: '',
|
||||
cellPhone: '',
|
||||
whatsapp: false,
|
||||
email: '',
|
||||
address: '',
|
||||
addressNumber: '',
|
||||
complement: '',
|
||||
neighborhood: '',
|
||||
city: '',
|
||||
state: '',
|
||||
zipCode: '',
|
||||
notifications: true,
|
||||
};
|
||||
|
||||
constructor(private readonly customerService: CustomerService,
|
||||
private dialogService: DialogService,
|
||||
private dialogsService: MessageService,
|
||||
private cepService: ConsultaCepService) {
|
||||
this.form = new FormGroup({
|
||||
company: new FormControl(this.customerData.company, [
|
||||
Validators.required,
|
||||
]),
|
||||
cpfCnpj: new FormControl(this.customerData.cpfCnpj, [
|
||||
Validators.required,
|
||||
]),
|
||||
name: new FormControl(this.customerData.name, [
|
||||
Validators.required,
|
||||
]),
|
||||
whatsapp: new FormControl(this.customerData.whatsapp, [
|
||||
Validators.required,
|
||||
]),
|
||||
numberState: new FormControl(this.customerData.numberState, []),
|
||||
cellPhone: new FormControl(this.customerData.cellPhone, [
|
||||
Validators.required,
|
||||
]),
|
||||
email: new FormControl(this.customerData.email, [Validators.required]),
|
||||
address: new FormControl(this.customerData.address, [Validators.required]),
|
||||
addressNumber: new FormControl(this.customerData.addressNumber, [Validators.required]),
|
||||
neighborhood: new FormControl(this.customerData.neighborhood),
|
||||
complement: new FormControl(this.customerData.complement),
|
||||
city: new FormControl(this.customerData.city),
|
||||
state: new FormControl(this.customerData.state),
|
||||
zipCode: new FormControl(this.customerData.zipCode),
|
||||
notifications: new FormControl(this.customerData.notifications),
|
||||
comments: new FormControl(this.customerData.comments),
|
||||
});
|
||||
}
|
||||
|
||||
public showConfirmation(mensage: string) {
|
||||
console.log(this.form.value);
|
||||
const result$ = this.dialogsService.confirmResult;
|
||||
result$.asObservable()
|
||||
.pipe(
|
||||
take(1),
|
||||
switchMap(result => result ? this.customerService.createCustomer(this.form.value) : EMPTY)
|
||||
).subscribe(
|
||||
successCreate => {
|
||||
return successCreate;
|
||||
}, err => err
|
||||
);
|
||||
this.dialogsService.showConfirmation('Confirmação', mensage);
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
cpfCadastrado(data: Customer) {
|
||||
const result$ = this.dialogsService.confirmResult;
|
||||
result$.asObservable()
|
||||
.pipe(
|
||||
take(1),
|
||||
map(result => result ? this.populateCustomer(data) : this.setFocus('inputCpf')),
|
||||
// switchMap(result => result ? console.log(result) : EMPTY)
|
||||
).subscribe(
|
||||
successCreate => {
|
||||
return successCreate;
|
||||
}, err => err
|
||||
);
|
||||
this.dialogsService.showConfirmation('Confirmação', 'Cliente já cadastrado, deseja alterar seu cadastro?');
|
||||
}
|
||||
|
||||
populateCustomer(data: Customer) {
|
||||
this.form.patchValue({
|
||||
name: data.name,
|
||||
cellPhone: data.cellPhone,
|
||||
email: data.email,
|
||||
zipCode: data.zipCode,
|
||||
address: data.address,
|
||||
addressNumber: data.addressNumber,
|
||||
complement: data.complement,
|
||||
neighborhood: data.neighborhood,
|
||||
city: data.city,
|
||||
state: data.state,
|
||||
mensage: data.allowMessage,
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
searchCustomerByDocument() {
|
||||
const fieldCpf = 'cpfCnpj';
|
||||
const cpf = this.form.value[fieldCpf];
|
||||
this.isloading = true;
|
||||
this.errorObject = null;
|
||||
this.customerService.getCustomerbyCpf(cpf).pipe(
|
||||
map(result => {
|
||||
if ( result.data != null) {
|
||||
this.customer = result.data;
|
||||
console.log(result);
|
||||
this.cpfCadastrado(result.data);
|
||||
}
|
||||
}),
|
||||
tap(() => {
|
||||
this.isloading = false;
|
||||
}),
|
||||
catchError(err => {
|
||||
this.isloading = false;
|
||||
this.errorObject = err;
|
||||
console.log(err);
|
||||
return throwError(err);
|
||||
})).subscribe();
|
||||
}
|
||||
|
||||
setFocus(name) {
|
||||
this.inputCpf.nativeElement.setFocus();
|
||||
console.log(name);
|
||||
/* const ele =
|
||||
if (ele) {
|
||||
ele.focus();
|
||||
}*/
|
||||
}
|
||||
|
||||
createCustomer() {
|
||||
console.log(this.form.value);
|
||||
const result$ = this.customerService.createCustomer(this.form.value);
|
||||
result$.pipe(
|
||||
map(c => console.log('cliente cadastrado')),
|
||||
).subscribe();
|
||||
}
|
||||
|
||||
consultaCep() {
|
||||
const cep = this.form.get('zipCode').value;
|
||||
if (cep != null && cep !== '') {
|
||||
this.cepService.consultaCep(cep)
|
||||
.subscribe(
|
||||
dados => {
|
||||
this.populateAddress(dados);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
populateAddress(dadosCep: any) {
|
||||
console.log(dadosCep);
|
||||
this.form.patchValue({
|
||||
address: dadosCep.logradouro,
|
||||
complement: dadosCep.complemento,
|
||||
neighborhood: dadosCep.bairro,
|
||||
city: dadosCep.localidade,
|
||||
state: dadosCep.uf
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
627
src/app/crm/menu-crm/menu-crm.component.html
Normal file
627
src/app/crm/menu-crm/menu-crm.component.html
Normal file
@@ -0,0 +1,627 @@
|
||||
|
||||
<!--Navbar -->
|
||||
<nav class="navbar navbar-expand-lg fixed-top">
|
||||
<div class="container-fluid">
|
||||
<!-- offcanvas trigger-->
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="offcanvas"
|
||||
data-bs-target="#offcanvasExample"
|
||||
aria-controls="offcanvasExample"
|
||||
>
|
||||
<span
|
||||
class="navbar-toggler-icon"
|
||||
data-bs-target="#offcanvasExample"
|
||||
></span>
|
||||
</button>
|
||||
<!-- offcanvas trigger-->
|
||||
<a class="navbar-brand" style="height: 40px; width: 120px" href="#">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="230.247"
|
||||
height="40"
|
||||
viewBox="0 0 260.247 70.6"
|
||||
>
|
||||
<g
|
||||
id="Grupo_3105"
|
||||
data-name="Grupo 3105"
|
||||
transform="translate(-720 -509)"
|
||||
>
|
||||
<g id="Grupo_2" data-name="Grupo 2" transform="translate(720 509)">
|
||||
<path
|
||||
id="Caminho_1"
|
||||
data-name="Caminho 1"
|
||||
d="M4.118,62.728A5.958,5.958,0,0,0,6.5,64.917a7.776,7.776,0,0,0,3.683.822,5.47,5.47,0,0,0,2.859-.685,6.025,6.025,0,0,0,1.891-1.777,8.772,8.772,0,0,0,1.142-2.326q.39-1.233.7-2.395L22.981,23.4H39.033L32.845,61.293a44.545,44.545,0,0,1-1.8,5.642,18.634,18.634,0,0,1-3.523,5.678,18.474,18.474,0,0,1-6.242,4.412A24.1,24.1,0,0,1,11.322,78.8a32.319,32.319,0,0,1-5.462-.445,46.443,46.443,0,0,1-5.179-1.2Z"
|
||||
transform="translate(-0.681 -8.203)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_2"
|
||||
data-name="Caminho 2"
|
||||
d="M48.366,31.258,45.807,45.086a14.283,14.283,0,0,0-.349,2.679,2.091,2.091,0,0,0,.349,1.315,1.644,1.644,0,0,0,1.337.438,2.183,2.183,0,0,0,2.094-1.046,12.462,12.462,0,0,0,1.047-3.385l2.558-13.828h11.4L61.39,46.4a12.035,12.035,0,0,1-5.233,8.4A18.931,18.931,0,0,1,45.69,57.5q-5.873,0-8.837-2.265a7.582,7.582,0,0,1-2.967-6.4,11.447,11.447,0,0,1,.059-1.168q.057-.583.174-1.266l2.849-15.143Z"
|
||||
transform="translate(2.993 -7.333)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_3"
|
||||
data-name="Caminho 3"
|
||||
d="M82.473,41.439q-.756-.34-1.57-.633a4.352,4.352,0,0,0-1.454-.292A5.481,5.481,0,0,0,76.8,41.1a5.071,5.071,0,0,0-1.715,1.461,7.524,7.524,0,0,0-1.018,1.948,12.739,12.739,0,0,0-.552,2.094L71.6,57.021H60.2L64.97,31.311H76.425l-1.57,4.918.117.1a11.9,11.9,0,0,1,3.692-3.945A9.418,9.418,0,0,1,84.1,30.776h.349Z"
|
||||
transform="translate(5.905 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_4"
|
||||
data-name="Caminho 4"
|
||||
d="M96.512,31.258,93.955,45.086a14.19,14.19,0,0,0-.349,2.679,2.084,2.084,0,0,0,.349,1.315,1.643,1.643,0,0,0,1.337.438,2.181,2.181,0,0,0,2.092-1.046,12.462,12.462,0,0,0,1.047-3.385l2.559-13.828h11.4L109.538,46.4a12.033,12.033,0,0,1-5.234,8.4,18.927,18.927,0,0,1-10.466,2.7q-5.874,0-8.839-2.265a7.584,7.584,0,0,1-2.965-6.4q0-.583.058-1.168t.174-1.266l2.85-15.143Z"
|
||||
transform="translate(8.321 -7.333)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_5"
|
||||
data-name="Caminho 5"
|
||||
d="M121.978,36.083l.057.1a9.7,9.7,0,0,1,1.542-2,12.635,12.635,0,0,1,2.122-1.728,11.456,11.456,0,0,1,2.5-1.217,8.3,8.3,0,0,1,2.733-.462,8.924,8.924,0,0,1,3.226.511,5.36,5.36,0,0,1,2.094,1.387,5,5,0,0,1,1.105,2.046,9.366,9.366,0,0,1,.32,2.482,11.986,11.986,0,0,1-.087,1.413q-.088.731-.2,1.462l-3.14,16.944h-11.4l2.385-13a10.485,10.485,0,0,0,.174-1.046,8.429,8.429,0,0,0,.059-.95,2.249,2.249,0,0,0-.321-1.291,1.5,1.5,0,0,0-1.307-.463,2.205,2.205,0,0,0-2.239,1.218,15.442,15.442,0,0,0-.96,3.164l-2.268,12.368h-11.4l4.768-25.709h11.4Z"
|
||||
transform="translate(11.081 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_6"
|
||||
data-name="Caminho 6"
|
||||
d="M162.677,48.305a13.84,13.84,0,0,1-5.989,6.865,18.263,18.263,0,0,1-9.305,2.386,17.484,17.484,0,0,1-5.349-.731,10.65,10.65,0,0,1-3.78-2.045,8.059,8.059,0,0,1-2.239-3.14,10.9,10.9,0,0,1-.727-4.067,11.78,11.78,0,0,1,.088-1.412q.087-.73.2-1.509a16.96,16.96,0,0,1,1.948-5.282,16.78,16.78,0,0,1,3.6-4.407,17.261,17.261,0,0,1,11.543-4.187,13.3,13.3,0,0,1,5.873,1.144,9.509,9.509,0,0,1,3.663,3.043,9.254,9.254,0,0,1,1.4,2.97,12.541,12.541,0,0,1,.407,3.165,21.587,21.587,0,0,1-.145,2.507,25.718,25.718,0,0,1-.436,2.557H146.686q-.058.342-.088.682t-.028.73a3.728,3.728,0,0,0,.406,1.754,1.719,1.719,0,0,0,1.686.78,3.091,3.091,0,0,0,2.85-1.8ZM152.965,41a1.343,1.343,0,0,0,.059-.39v-.389a3.273,3.273,0,0,0-.465-1.7,1.863,1.863,0,0,0-1.744-.779,2.629,2.629,0,0,0-1.279.317,3.052,3.052,0,0,0-.961.8,4.361,4.361,0,0,0-.61,1.072A4.291,4.291,0,0,0,147.674,41Z"
|
||||
transform="translate(14.213 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_7"
|
||||
data-name="Caminho 7"
|
||||
d="M175.239,36.083l.057.1a9.67,9.67,0,0,1,1.543-2,12.582,12.582,0,0,1,2.121-1.728,11.441,11.441,0,0,1,2.5-1.217,8.285,8.285,0,0,1,2.732-.462,8.919,8.919,0,0,1,3.226.511,5.373,5.373,0,0,1,2.095,1.387,5.011,5.011,0,0,1,1.1,2.046,9.367,9.367,0,0,1,.32,2.482,11.983,11.983,0,0,1-.087,1.413q-.087.731-.2,1.462l-3.14,16.944h-11.4l2.385-13a10.182,10.182,0,0,0,.174-1.046,8.425,8.425,0,0,0,.059-.95,2.249,2.249,0,0,0-.321-1.291,1.5,1.5,0,0,0-1.307-.463,2.205,2.205,0,0,0-2.239,1.218,15.443,15.443,0,0,0-.96,3.164l-2.267,12.368h-11.4L165,31.311h11.4Z"
|
||||
transform="translate(16.974 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_8"
|
||||
data-name="Caminho 8"
|
||||
d="M191.086,47.769a9.759,9.759,0,0,0,2.24,1.8,5.623,5.623,0,0,0,2.994.876,4.085,4.085,0,0,0,1.54-.317,1.31,1.31,0,0,0,.9-1v-.244a1.188,1.188,0,0,0-.641-1,7.9,7.9,0,0,0-1.977-.8,22.373,22.373,0,0,1-2.617-1,9.351,9.351,0,0,1-2.121-1.315,5.851,5.851,0,0,1-1.425-1.729,4.763,4.763,0,0,1-.523-2.288c0-.194.009-.4.029-.609s.048-.446.087-.705a8.21,8.21,0,0,1,1.57-3.6,10.8,10.8,0,0,1,3.082-2.727,15.743,15.743,0,0,1,4.245-1.728,20.713,20.713,0,0,1,9.768-.049,18.056,18.056,0,0,1,4.246,1.534l-5.176,6.963q-.873-.778-1.89-1.534a4.034,4.034,0,0,0-2.471-.755,2.519,2.519,0,0,0-1.222.318,1.306,1.306,0,0,0-.7.948V39a1.105,1.105,0,0,0,.32.78,3.326,3.326,0,0,0,.785.609,7.057,7.057,0,0,0,.96.463c.329.13.63.243.9.341a15.387,15.387,0,0,1,4.419,2.239,4.543,4.543,0,0,1,1.8,3.847c0,.194-.01.4-.029.609s-.049.431-.087.656a8.652,8.652,0,0,1-1.745,3.872,11.922,11.922,0,0,1-3.255,2.823,15.688,15.688,0,0,1-4.246,1.729,19.246,19.246,0,0,1-4.71.584,20.478,20.478,0,0,1-5.611-.706,27.977,27.977,0,0,1-4.971-1.971Z"
|
||||
transform="translate(19.776 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_9"
|
||||
data-name="Caminho 9"
|
||||
d="M236.524,48.305a13.835,13.835,0,0,1-5.989,6.865,18.259,18.259,0,0,1-9.3,2.386,17.484,17.484,0,0,1-5.349-.731,10.64,10.64,0,0,1-3.78-2.045,8.059,8.059,0,0,1-2.239-3.14,10.9,10.9,0,0,1-.727-4.067,11.786,11.786,0,0,1,.088-1.412q.087-.73.2-1.509a17.016,17.016,0,0,1,1.948-5.282,16.807,16.807,0,0,1,3.605-4.407,17.261,17.261,0,0,1,11.543-4.187A13.3,13.3,0,0,1,232.4,31.92a9.506,9.506,0,0,1,3.662,3.043,9.207,9.207,0,0,1,1.4,2.97,12.491,12.491,0,0,1,.408,3.165,21.843,21.843,0,0,1-.145,2.507q-.147,1.243-.436,2.557H220.533q-.058.342-.088.682t-.028.73a3.728,3.728,0,0,0,.405,1.754,1.722,1.722,0,0,0,1.687.78,3.091,3.091,0,0,0,2.85-1.8Zm-9.71-7.3a1.383,1.383,0,0,0,.059-.39v-.389a3.273,3.273,0,0,0-.465-1.7,1.863,1.863,0,0,0-1.744-.779,2.636,2.636,0,0,0-1.281.317,3.048,3.048,0,0,0-.96.8,4.361,4.361,0,0,0-.61,1.072A4.292,4.292,0,0,0,221.522,41Z"
|
||||
transform="translate(22.385 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_10"
|
||||
data-name="Caminho 10"
|
||||
d="M37.494,22.3H21.116L23.089,9.717H39.467Z"
|
||||
transform="translate(1.58 -9.717)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<g
|
||||
id="Grupo_1"
|
||||
data-name="Grupo 1"
|
||||
transform="translate(64.066 56.235)"
|
||||
>
|
||||
<path
|
||||
id="Caminho_11"
|
||||
data-name="Caminho 11"
|
||||
d="M60.329,60.528h4.356l-.663,4.19h2.772l.662-4.19h4.355L69.846,72.966H65.49l.683-4.322H63.4l-.683,4.322H58.364Z"
|
||||
transform="translate(-58.364 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_12"
|
||||
data-name="Caminho 12"
|
||||
d="M85.916,66.8a7.694,7.694,0,0,1-7.888,6.384c-3.794,0-6.5-2.391-5.87-6.384a7.837,7.837,0,0,1,7.9-6.451C83.833,60.349,86.533,62.89,85.916,66.8Zm-9.215.067a1.887,1.887,0,0,0,1.947,2.391,2.726,2.726,0,0,0,2.7-2.391,1.922,1.922,0,0,0-1.943-2.426A2.783,2.783,0,0,0,76.7,66.866Z"
|
||||
transform="translate(-56.848 -60.349)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_13"
|
||||
data-name="Caminho 13"
|
||||
d="M89.755,60.528h4.651l.684,6.533h.116a15.687,15.687,0,0,1,.573-1.65l2.175-4.882h4.6l.08,12.438H98.265l.466-6.813h-.083a12.046,12.046,0,0,1-.492,1.237l-2.679,5.575h-2.64L92.052,67.7a8.132,8.132,0,0,1-.036-1.55h-.148c-.112.494-.225,1.006-.353,1.5l-1.367,5.312H85.777Z"
|
||||
transform="translate(-55.331 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_14"
|
||||
data-name="Caminho 14"
|
||||
d="M105.37,60.528h8.363l-.536,3.4h-3.811l-.188,1.188h3.481l-.511,3.233h-3.481l-.193,1.221h3.943l-.538,3.4h-8.5Z"
|
||||
transform="translate(-53.38 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_15"
|
||||
data-name="Caminho 15"
|
||||
d="M131.541,65.6a3.375,3.375,0,0,0-2.458-1.254,2.962,2.962,0,0,0-2.841,2.425,2.065,2.065,0,0,0,2.14,2.426,4.238,4.238,0,0,0,2.772-1.155l-.866,4.653a10.737,10.737,0,0,1-3.3.494,5.2,5.2,0,0,1-5.322-6.3,7.861,7.861,0,0,1,7.531-6.533,8.741,8.741,0,0,1,2.954.512Z"
|
||||
transform="translate(-51.368 -60.349)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_16"
|
||||
data-name="Caminho 16"
|
||||
d="M133.985,60.528h8.364l-.538,3.4H138l-.188,1.188h3.481l-.51,3.233H137.3l-.193,1.221h3.943l-.538,3.4h-8.5Z"
|
||||
transform="translate(-50.214 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_17"
|
||||
data-name="Caminho 17"
|
||||
d="M144.395,60.528h4.339l2.969,6.9h.131a18.385,18.385,0,0,1,.121-3.168l.59-3.728h4.322L154.9,72.966h-4.323l-2.943-6.533H147.5a14.36,14.36,0,0,1-.112,2.491l-.64,4.042H142.43Z"
|
||||
transform="translate(-49.062 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_18"
|
||||
data-name="Caminho 18"
|
||||
d="M157.643,60.528h9.5l-.639,4.042-2.473-.116-1.345,8.512h-4.52l1.346-8.512L157,64.57Z"
|
||||
transform="translate(-47.449 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_19"
|
||||
data-name="Caminho 19"
|
||||
d="M168.482,60.528h8.364l-.538,3.4H172.5l-.188,1.188h3.481l-.51,3.233H171.8l-.193,1.221h3.943l-.538,3.4h-8.5Z"
|
||||
transform="translate(-46.397 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_20"
|
||||
data-name="Caminho 20"
|
||||
d="M178.952,60.528h5.46c2.8,0,4.992,1.187,4.5,4.322a3.571,3.571,0,0,1-2.92,3.234l-.016.1a2.5,2.5,0,0,1,.642.742l2.067,4.042h-5.213l-1.348-3.992h-.082l-.631,3.992h-4.421Zm3.55,5.51h.314c.742,0,1.5-.116,1.648-1.04.151-.957-.506-1.073-1.282-1.073h-.347Z"
|
||||
transform="translate(-45.238 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarSupportedContent"
|
||||
aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<!--form class="d-flex ms-auto">
|
||||
<div class="input-group my-3 my-lg-0">
|
||||
<input
|
||||
class="form-control me-2"
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
aria-label="Search"
|
||||
/>
|
||||
<button class="btn btn-outline-success" type="submit">Search</button>
|
||||
</div>
|
||||
</form-->
|
||||
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item dropdown">
|
||||
<a
|
||||
class="nav-link dropdown-toggle"
|
||||
href="#"
|
||||
id="navbarDropdown"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<i class="bi bi-person-fill"></i>
|
||||
</a>
|
||||
<ul
|
||||
class="dropdown-menu dropdown-menu-end"
|
||||
aria-labelledby="navbarDropdown"
|
||||
>
|
||||
<li><a class="dropdown-item" href="#">Action</a></li>
|
||||
<li><a class="dropdown-item" href="#">Another action</a></li>
|
||||
<li><hr class="dropdown-divider" /></li>
|
||||
<li><a class="dropdown-item" href="#">Something else here</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- Navbar -->
|
||||
|
||||
<!-- OffCanvas -->
|
||||
<div
|
||||
class="offcanvas offcanvas-start sidebar-nav text-light"
|
||||
data-bs-backdrop="false"
|
||||
data-bs-scroll="true"
|
||||
tabindex="-1"
|
||||
id="offcanvasExample"
|
||||
aria-labelledby="offcanvasExampleLabel"
|
||||
>
|
||||
<div class="offcanvas-header mt-2">
|
||||
<h5 class="offcanvas-title" id="offcanvasExampleLabel">Mestre Jurunense</h5>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<ul class="navbar-nav">
|
||||
<!--li class="nav-item">
|
||||
<a
|
||||
class="nav-link px-3 sidebar-link"
|
||||
>
|
||||
<span><i class="bi bi-graph-up-arrow me-2"></i></span>
|
||||
<span>Dashboard</span>
|
||||
</a>
|
||||
</li-->
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link px-3 sidebar-link"
|
||||
data-bs-toggle="collapse"
|
||||
href="#collapseExample"
|
||||
role="button"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseExample"
|
||||
>
|
||||
<span><i class="bi bi-shop me-2"></i></span>
|
||||
<span>Cadastros</span>
|
||||
<span class="right-icon ms-auto"
|
||||
><i class="bi bi-chevron-down"></i
|
||||
></span>
|
||||
</a>
|
||||
|
||||
<div class="collapse" id="collapseExample">
|
||||
<div>
|
||||
<ul class="navbar-nav ps-3">
|
||||
<li>
|
||||
<a href="#" class="nav-link px-3">
|
||||
<span>Parceiros</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="nav-link px-3">
|
||||
<span>Categoria</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" class="nav-link px-3">
|
||||
<span>Faixa de comissão</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link px-3 sidebar-link"
|
||||
data-bs-toggle="collapse"
|
||||
href="#collapseregister"
|
||||
role="button"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseregister"
|
||||
>
|
||||
<span><i class="bi bi-person-plus me-2"></i></span>
|
||||
<span>Cadastros</span>
|
||||
<span class="right-icon ms-auto"
|
||||
><i class="bi bi-chevron-down"></i
|
||||
></span>
|
||||
</a>
|
||||
|
||||
<div class="collapse" id="collapseregister">
|
||||
<div>
|
||||
<ul class="navbar-nav ps-3">
|
||||
<li>
|
||||
<a href="#" class="nav-link px-3">
|
||||
<span>Clientes</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- OffCanvas -->
|
||||
|
||||
<main class="mt-5 pt-3">
|
||||
<div class="container-fluid">
|
||||
<span>teste</span>
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!--div class="container-fluid my-0 p-0">
|
||||
<nav
|
||||
class="
|
||||
navbar navbar-expand-md
|
||||
flex-md-column flex-row
|
||||
align-items-center
|
||||
py-2
|
||||
text-center
|
||||
sticky-top
|
||||
"
|
||||
>
|
||||
<div class="container-fluid my-0 p-0 sticky-top">
|
||||
<a class="navbar-brand" href="#">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="230.247"
|
||||
height="50.6"
|
||||
viewBox="0 0 260.247 70.6"
|
||||
>
|
||||
<g
|
||||
id="Grupo_3105"
|
||||
data-name="Grupo 3105"
|
||||
transform="translate(-720 -509)"
|
||||
>
|
||||
<g id="Grupo_2" data-name="Grupo 2" transform="translate(720 509)">
|
||||
<path
|
||||
id="Caminho_1"
|
||||
data-name="Caminho 1"
|
||||
d="M4.118,62.728A5.958,5.958,0,0,0,6.5,64.917a7.776,7.776,0,0,0,3.683.822,5.47,5.47,0,0,0,2.859-.685,6.025,6.025,0,0,0,1.891-1.777,8.772,8.772,0,0,0,1.142-2.326q.39-1.233.7-2.395L22.981,23.4H39.033L32.845,61.293a44.545,44.545,0,0,1-1.8,5.642,18.634,18.634,0,0,1-3.523,5.678,18.474,18.474,0,0,1-6.242,4.412A24.1,24.1,0,0,1,11.322,78.8a32.319,32.319,0,0,1-5.462-.445,46.443,46.443,0,0,1-5.179-1.2Z"
|
||||
transform="translate(-0.681 -8.203)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_2"
|
||||
data-name="Caminho 2"
|
||||
d="M48.366,31.258,45.807,45.086a14.283,14.283,0,0,0-.349,2.679,2.091,2.091,0,0,0,.349,1.315,1.644,1.644,0,0,0,1.337.438,2.183,2.183,0,0,0,2.094-1.046,12.462,12.462,0,0,0,1.047-3.385l2.558-13.828h11.4L61.39,46.4a12.035,12.035,0,0,1-5.233,8.4A18.931,18.931,0,0,1,45.69,57.5q-5.873,0-8.837-2.265a7.582,7.582,0,0,1-2.967-6.4,11.447,11.447,0,0,1,.059-1.168q.057-.583.174-1.266l2.849-15.143Z"
|
||||
transform="translate(2.993 -7.333)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_3"
|
||||
data-name="Caminho 3"
|
||||
d="M82.473,41.439q-.756-.34-1.57-.633a4.352,4.352,0,0,0-1.454-.292A5.481,5.481,0,0,0,76.8,41.1a5.071,5.071,0,0,0-1.715,1.461,7.524,7.524,0,0,0-1.018,1.948,12.739,12.739,0,0,0-.552,2.094L71.6,57.021H60.2L64.97,31.311H76.425l-1.57,4.918.117.1a11.9,11.9,0,0,1,3.692-3.945A9.418,9.418,0,0,1,84.1,30.776h.349Z"
|
||||
transform="translate(5.905 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_4"
|
||||
data-name="Caminho 4"
|
||||
d="M96.512,31.258,93.955,45.086a14.19,14.19,0,0,0-.349,2.679,2.084,2.084,0,0,0,.349,1.315,1.643,1.643,0,0,0,1.337.438,2.181,2.181,0,0,0,2.092-1.046,12.462,12.462,0,0,0,1.047-3.385l2.559-13.828h11.4L109.538,46.4a12.033,12.033,0,0,1-5.234,8.4,18.927,18.927,0,0,1-10.466,2.7q-5.874,0-8.839-2.265a7.584,7.584,0,0,1-2.965-6.4q0-.583.058-1.168t.174-1.266l2.85-15.143Z"
|
||||
transform="translate(8.321 -7.333)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_5"
|
||||
data-name="Caminho 5"
|
||||
d="M121.978,36.083l.057.1a9.7,9.7,0,0,1,1.542-2,12.635,12.635,0,0,1,2.122-1.728,11.456,11.456,0,0,1,2.5-1.217,8.3,8.3,0,0,1,2.733-.462,8.924,8.924,0,0,1,3.226.511,5.36,5.36,0,0,1,2.094,1.387,5,5,0,0,1,1.105,2.046,9.366,9.366,0,0,1,.32,2.482,11.986,11.986,0,0,1-.087,1.413q-.088.731-.2,1.462l-3.14,16.944h-11.4l2.385-13a10.485,10.485,0,0,0,.174-1.046,8.429,8.429,0,0,0,.059-.95,2.249,2.249,0,0,0-.321-1.291,1.5,1.5,0,0,0-1.307-.463,2.205,2.205,0,0,0-2.239,1.218,15.442,15.442,0,0,0-.96,3.164l-2.268,12.368h-11.4l4.768-25.709h11.4Z"
|
||||
transform="translate(11.081 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_6"
|
||||
data-name="Caminho 6"
|
||||
d="M162.677,48.305a13.84,13.84,0,0,1-5.989,6.865,18.263,18.263,0,0,1-9.305,2.386,17.484,17.484,0,0,1-5.349-.731,10.65,10.65,0,0,1-3.78-2.045,8.059,8.059,0,0,1-2.239-3.14,10.9,10.9,0,0,1-.727-4.067,11.78,11.78,0,0,1,.088-1.412q.087-.73.2-1.509a16.96,16.96,0,0,1,1.948-5.282,16.78,16.78,0,0,1,3.6-4.407,17.261,17.261,0,0,1,11.543-4.187,13.3,13.3,0,0,1,5.873,1.144,9.509,9.509,0,0,1,3.663,3.043,9.254,9.254,0,0,1,1.4,2.97,12.541,12.541,0,0,1,.407,3.165,21.587,21.587,0,0,1-.145,2.507,25.718,25.718,0,0,1-.436,2.557H146.686q-.058.342-.088.682t-.028.73a3.728,3.728,0,0,0,.406,1.754,1.719,1.719,0,0,0,1.686.78,3.091,3.091,0,0,0,2.85-1.8ZM152.965,41a1.343,1.343,0,0,0,.059-.39v-.389a3.273,3.273,0,0,0-.465-1.7,1.863,1.863,0,0,0-1.744-.779,2.629,2.629,0,0,0-1.279.317,3.052,3.052,0,0,0-.961.8,4.361,4.361,0,0,0-.61,1.072A4.291,4.291,0,0,0,147.674,41Z"
|
||||
transform="translate(14.213 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_7"
|
||||
data-name="Caminho 7"
|
||||
d="M175.239,36.083l.057.1a9.67,9.67,0,0,1,1.543-2,12.582,12.582,0,0,1,2.121-1.728,11.441,11.441,0,0,1,2.5-1.217,8.285,8.285,0,0,1,2.732-.462,8.919,8.919,0,0,1,3.226.511,5.373,5.373,0,0,1,2.095,1.387,5.011,5.011,0,0,1,1.1,2.046,9.367,9.367,0,0,1,.32,2.482,11.983,11.983,0,0,1-.087,1.413q-.087.731-.2,1.462l-3.14,16.944h-11.4l2.385-13a10.182,10.182,0,0,0,.174-1.046,8.425,8.425,0,0,0,.059-.95,2.249,2.249,0,0,0-.321-1.291,1.5,1.5,0,0,0-1.307-.463,2.205,2.205,0,0,0-2.239,1.218,15.443,15.443,0,0,0-.96,3.164l-2.267,12.368h-11.4L165,31.311h11.4Z"
|
||||
transform="translate(16.974 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_8"
|
||||
data-name="Caminho 8"
|
||||
d="M191.086,47.769a9.759,9.759,0,0,0,2.24,1.8,5.623,5.623,0,0,0,2.994.876,4.085,4.085,0,0,0,1.54-.317,1.31,1.31,0,0,0,.9-1v-.244a1.188,1.188,0,0,0-.641-1,7.9,7.9,0,0,0-1.977-.8,22.373,22.373,0,0,1-2.617-1,9.351,9.351,0,0,1-2.121-1.315,5.851,5.851,0,0,1-1.425-1.729,4.763,4.763,0,0,1-.523-2.288c0-.194.009-.4.029-.609s.048-.446.087-.705a8.21,8.21,0,0,1,1.57-3.6,10.8,10.8,0,0,1,3.082-2.727,15.743,15.743,0,0,1,4.245-1.728,20.713,20.713,0,0,1,9.768-.049,18.056,18.056,0,0,1,4.246,1.534l-5.176,6.963q-.873-.778-1.89-1.534a4.034,4.034,0,0,0-2.471-.755,2.519,2.519,0,0,0-1.222.318,1.306,1.306,0,0,0-.7.948V39a1.105,1.105,0,0,0,.32.78,3.326,3.326,0,0,0,.785.609,7.057,7.057,0,0,0,.96.463c.329.13.63.243.9.341a15.387,15.387,0,0,1,4.419,2.239,4.543,4.543,0,0,1,1.8,3.847c0,.194-.01.4-.029.609s-.049.431-.087.656a8.652,8.652,0,0,1-1.745,3.872,11.922,11.922,0,0,1-3.255,2.823,15.688,15.688,0,0,1-4.246,1.729,19.246,19.246,0,0,1-4.71.584,20.478,20.478,0,0,1-5.611-.706,27.977,27.977,0,0,1-4.971-1.971Z"
|
||||
transform="translate(19.776 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_9"
|
||||
data-name="Caminho 9"
|
||||
d="M236.524,48.305a13.835,13.835,0,0,1-5.989,6.865,18.259,18.259,0,0,1-9.3,2.386,17.484,17.484,0,0,1-5.349-.731,10.64,10.64,0,0,1-3.78-2.045,8.059,8.059,0,0,1-2.239-3.14,10.9,10.9,0,0,1-.727-4.067,11.786,11.786,0,0,1,.088-1.412q.087-.73.2-1.509a17.016,17.016,0,0,1,1.948-5.282,16.807,16.807,0,0,1,3.605-4.407,17.261,17.261,0,0,1,11.543-4.187A13.3,13.3,0,0,1,232.4,31.92a9.506,9.506,0,0,1,3.662,3.043,9.207,9.207,0,0,1,1.4,2.97,12.491,12.491,0,0,1,.408,3.165,21.843,21.843,0,0,1-.145,2.507q-.147,1.243-.436,2.557H220.533q-.058.342-.088.682t-.028.73a3.728,3.728,0,0,0,.405,1.754,1.722,1.722,0,0,0,1.687.78,3.091,3.091,0,0,0,2.85-1.8Zm-9.71-7.3a1.383,1.383,0,0,0,.059-.39v-.389a3.273,3.273,0,0,0-.465-1.7,1.863,1.863,0,0,0-1.744-.779,2.636,2.636,0,0,0-1.281.317,3.048,3.048,0,0,0-.96.8,4.361,4.361,0,0,0-.61,1.072A4.292,4.292,0,0,0,221.522,41Z"
|
||||
transform="translate(22.385 -7.386)"
|
||||
fill="#fff"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_10"
|
||||
data-name="Caminho 10"
|
||||
d="M37.494,22.3H21.116L23.089,9.717H39.467Z"
|
||||
transform="translate(1.58 -9.717)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<g
|
||||
id="Grupo_1"
|
||||
data-name="Grupo 1"
|
||||
transform="translate(64.066 56.235)"
|
||||
>
|
||||
<path
|
||||
id="Caminho_11"
|
||||
data-name="Caminho 11"
|
||||
d="M60.329,60.528h4.356l-.663,4.19h2.772l.662-4.19h4.355L69.846,72.966H65.49l.683-4.322H63.4l-.683,4.322H58.364Z"
|
||||
transform="translate(-58.364 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_12"
|
||||
data-name="Caminho 12"
|
||||
d="M85.916,66.8a7.694,7.694,0,0,1-7.888,6.384c-3.794,0-6.5-2.391-5.87-6.384a7.837,7.837,0,0,1,7.9-6.451C83.833,60.349,86.533,62.89,85.916,66.8Zm-9.215.067a1.887,1.887,0,0,0,1.947,2.391,2.726,2.726,0,0,0,2.7-2.391,1.922,1.922,0,0,0-1.943-2.426A2.783,2.783,0,0,0,76.7,66.866Z"
|
||||
transform="translate(-56.848 -60.349)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_13"
|
||||
data-name="Caminho 13"
|
||||
d="M89.755,60.528h4.651l.684,6.533h.116a15.687,15.687,0,0,1,.573-1.65l2.175-4.882h4.6l.08,12.438H98.265l.466-6.813h-.083a12.046,12.046,0,0,1-.492,1.237l-2.679,5.575h-2.64L92.052,67.7a8.132,8.132,0,0,1-.036-1.55h-.148c-.112.494-.225,1.006-.353,1.5l-1.367,5.312H85.777Z"
|
||||
transform="translate(-55.331 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_14"
|
||||
data-name="Caminho 14"
|
||||
d="M105.37,60.528h8.363l-.536,3.4h-3.811l-.188,1.188h3.481l-.511,3.233h-3.481l-.193,1.221h3.943l-.538,3.4h-8.5Z"
|
||||
transform="translate(-53.38 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_15"
|
||||
data-name="Caminho 15"
|
||||
d="M131.541,65.6a3.375,3.375,0,0,0-2.458-1.254,2.962,2.962,0,0,0-2.841,2.425,2.065,2.065,0,0,0,2.14,2.426,4.238,4.238,0,0,0,2.772-1.155l-.866,4.653a10.737,10.737,0,0,1-3.3.494,5.2,5.2,0,0,1-5.322-6.3,7.861,7.861,0,0,1,7.531-6.533,8.741,8.741,0,0,1,2.954.512Z"
|
||||
transform="translate(-51.368 -60.349)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_16"
|
||||
data-name="Caminho 16"
|
||||
d="M133.985,60.528h8.364l-.538,3.4H138l-.188,1.188h3.481l-.51,3.233H137.3l-.193,1.221h3.943l-.538,3.4h-8.5Z"
|
||||
transform="translate(-50.214 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_17"
|
||||
data-name="Caminho 17"
|
||||
d="M144.395,60.528h4.339l2.969,6.9h.131a18.385,18.385,0,0,1,.121-3.168l.59-3.728h4.322L154.9,72.966h-4.323l-2.943-6.533H147.5a14.36,14.36,0,0,1-.112,2.491l-.64,4.042H142.43Z"
|
||||
transform="translate(-49.062 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_18"
|
||||
data-name="Caminho 18"
|
||||
d="M157.643,60.528h9.5l-.639,4.042-2.473-.116-1.345,8.512h-4.52l1.346-8.512L157,64.57Z"
|
||||
transform="translate(-47.449 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_19"
|
||||
data-name="Caminho 19"
|
||||
d="M168.482,60.528h8.364l-.538,3.4H172.5l-.188,1.188h3.481l-.51,3.233H171.8l-.193,1.221h3.943l-.538,3.4h-8.5Z"
|
||||
transform="translate(-46.397 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
<path
|
||||
id="Caminho_20"
|
||||
data-name="Caminho 20"
|
||||
d="M178.952,60.528h5.46c2.8,0,4.992,1.187,4.5,4.322a3.571,3.571,0,0,1-2.92,3.234l-.016.1a2.5,2.5,0,0,1,.642.742l2.067,4.042h-5.213l-1.348-3.992h-.082l-.631,3.992h-4.421Zm3.55,5.51h.314c.742,0,1.5-.116,1.648-1.04.151-.957-.506-1.073-1.282-1.073h-.347Z"
|
||||
transform="translate(-45.238 -60.329)"
|
||||
fill="#ef7d00"
|
||||
></path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</a>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#nav"
|
||||
aria-controls="nav"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="row min-vh-100 flex-column flex-md-row">
|
||||
<aside class="col-12 col-md-3 col-xl-2 p-0 bg-dark">
|
||||
<nav
|
||||
class="
|
||||
navbar navbar-expand-md navbar-dark
|
||||
bd-dark
|
||||
flex-md-column flex-row
|
||||
align-items-center
|
||||
py-2
|
||||
text-center
|
||||
"
|
||||
id="sidebar"
|
||||
>
|
||||
<div class="text-center p-3">
|
||||
<img
|
||||
src="https://impreza.us-themes.com/wp-content/uploads/paolo-bendandi-D-8XODEIr_s-unsplash.jpg"
|
||||
alt="profile picture"
|
||||
class="img-fluid rounded-circle my-4 p-1 d-none d-md-block shadow"
|
||||
/>
|
||||
<a href="#" class="navbar-brand mx-0 font-weight-bold text-nowrap"
|
||||
>XcentPupil</a
|
||||
>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
class="navbar-toggler border-0 order-1"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#nav"
|
||||
aria-controls="nav"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
|
||||
<div class="collapse navbar-collapse order-last" id="nav">
|
||||
<ul class="navbar-nav flex-column w-100 justify-content-center">
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link active"> Edit Profile</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link"> Projects</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link"> Tasks </a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="#" class="nav-link"> Users Info </a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</aside>
|
||||
<main class="col px-0 flex-grow-1 overflow-auto">
|
||||
<div class="container py-3">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</!--div>
|
||||
|
||||
<!--div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
<div class="d-line" style="width: 240px; left: -240;">
|
||||
<div class="sidebar fixed">
|
||||
<span class="fs-5 fw-semibold">MENU</span>
|
||||
<ul class="list-unstyled ps-0">
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#home-collapse" aria-expanded="true">
|
||||
Cadastro
|
||||
</button>
|
||||
<div class="collapse show" id="home-collapse">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">Clientes</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
<li class="border-top my-3"></li>
|
||||
<li class="mb-1">
|
||||
<button class="btn btn-toggle align-items-center rounded collapsed" data-bs-toggle="collapse" data-bs-target="#account-collapse" aria-expanded="false">
|
||||
Tabelas auxiliares
|
||||
</button>
|
||||
<div class="collapse" id="account-collapse">
|
||||
<ul class="btn-toggle-nav list-unstyled fw-normal pb-1 small">
|
||||
<li><a href="#" class="link-dark rounded">Fidelidade</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="col-10">
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div-->
|
||||
64
src/app/crm/menu-crm/menu-crm.component.scss
Normal file
64
src/app/crm/menu-crm/menu-crm.component.scss
Normal file
@@ -0,0 +1,64 @@
|
||||
.navbar {
|
||||
background-color: #2D2E83;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
#menu-vertical{
|
||||
position:fixed;
|
||||
z-index:999;
|
||||
overflow:hidden;
|
||||
padding:6px;
|
||||
height: 100vh;
|
||||
background-color: #2D2E83;
|
||||
}
|
||||
|
||||
:root {
|
||||
--offcanvas-width: 270px;
|
||||
--topNavbarHeight: 56px;
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
width: 270px;
|
||||
background-color: #2D2E83;
|
||||
}
|
||||
|
||||
.sidebar-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sidebar-link .right-icon {
|
||||
display: inline-flex;
|
||||
transition: all ease 0.25s;
|
||||
}
|
||||
|
||||
.sidebar-link[aria-expanded="true"] .right-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
li a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
|
||||
body {
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
main {
|
||||
margin-left: 270px;
|
||||
}
|
||||
|
||||
.offcanvas-backdrop::before{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-nav{
|
||||
transform: none;
|
||||
visibility: visible !important;
|
||||
top: 56px;
|
||||
height: calc(100% - 56px);
|
||||
}
|
||||
}
|
||||
25
src/app/crm/menu-crm/menu-crm.component.spec.ts
Normal file
25
src/app/crm/menu-crm/menu-crm.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MenuCrmComponent } from './menu-crm.component';
|
||||
|
||||
describe('MenuCrmComponent', () => {
|
||||
let component: MenuCrmComponent;
|
||||
let fixture: ComponentFixture<MenuCrmComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ MenuCrmComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MenuCrmComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
18
src/app/crm/menu-crm/menu-crm.component.ts
Normal file
18
src/app/crm/menu-crm/menu-crm.component.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-menu-crm',
|
||||
templateUrl: './menu-crm.component.html',
|
||||
styleUrls: ['./menu-crm.component.scss']
|
||||
})
|
||||
export class MenuCrmComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
status: boolean = false;
|
||||
clickEvent(){
|
||||
this.status = !this.status;
|
||||
}
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
0
src/app/financial/checkout/checkout.component.css
Normal file
0
src/app/financial/checkout/checkout.component.css
Normal file
105
src/app/financial/checkout/checkout.component.html
Normal file
105
src/app/financial/checkout/checkout.component.html
Normal file
@@ -0,0 +1,105 @@
|
||||
<div class="container">
|
||||
<nav class="navbar navbar-expand-lg navbar-light bg-danger">
|
||||
<div class="container-fluid">
|
||||
<a class="navbar-brand text-white" href="#">Financial</a>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarNav"
|
||||
aria-controls="navbarNav"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" aria-current="page" href="#">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Features</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">Pricing</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link disabled"
|
||||
href="#"
|
||||
tabindex="-1"
|
||||
aria-disabled="true"
|
||||
>Disabled</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="card mt-3">
|
||||
<h2 class="card-header">Conferência de caixa</h2>
|
||||
<form class="mt-3 px-3" action="">
|
||||
|
||||
<div class="mb-3">
|
||||
<kendo-floatinglabel text="Loja">
|
||||
<kendo-combobox
|
||||
style="width: 450px"
|
||||
[data]="stores"
|
||||
[textField]="'name'"
|
||||
[valueField]="'id'"
|
||||
[placeholder]="'Selecione a loja desejada'"
|
||||
(valueChange)="handleStoreChange($event)"
|
||||
></kendo-combobox>
|
||||
</kendo-floatinglabel>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<kendo-floatinglabel text="Caixa">
|
||||
<kendo-combobox
|
||||
style="width: 450px"
|
||||
[disabled]="isDisabledCheckout"
|
||||
[data]="checkouts"
|
||||
[textField]="'description'"
|
||||
[valueField]="'id'"
|
||||
[placeholder]="'Selecione o checkout desejado'"
|
||||
(valueChange)="handleCheckoutChange($event)"
|
||||
></kendo-combobox>
|
||||
</kendo-floatinglabel>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<kendo-floatinglabel text="Usuário">
|
||||
<kendo-combobox
|
||||
style="width: 450px"
|
||||
[disabled]="isDisabledUser"
|
||||
[data]="users"
|
||||
(valueChange)="handleUserChange($event)"
|
||||
[textField]="'name'"
|
||||
[valueField]="'id'"
|
||||
[placeholder]="'Selecione o usuário desejado'"
|
||||
></kendo-combobox>
|
||||
</kendo-floatinglabel>
|
||||
</div>
|
||||
|
||||
<div class="mb-3">
|
||||
<kendo-floatinglabel text="Data movimento">
|
||||
<kendo-datepicker [format]="format" [(value)]="value"></kendo-datepicker>
|
||||
</kendo-floatinglabel>
|
||||
</div>
|
||||
|
||||
<div class="row mb-3 mt-3">
|
||||
<div class="col12">
|
||||
<button kendoButton look="outline" [primary]="true" (click)="findOrders()">Pesquisar</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<kendo-grid>
|
||||
|
||||
</kendo-grid>
|
||||
</div>
|
||||
25
src/app/financial/checkout/checkout.component.spec.ts
Normal file
25
src/app/financial/checkout/checkout.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { CheckoutComponent } from './checkout.component';
|
||||
|
||||
describe('CheckoutComponent', () => {
|
||||
let component: CheckoutComponent;
|
||||
let fixture: ComponentFixture<CheckoutComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ CheckoutComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(CheckoutComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
82
src/app/financial/checkout/checkout.component.ts
Normal file
82
src/app/financial/checkout/checkout.component.ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { FormatSettings } from '@progress/kendo-angular-dateinputs';
|
||||
import { ComboBoxComponent } from '@progress/kendo-angular-dropdowns';
|
||||
import { CheckoutOrder } from 'src/app/models/checkout-order.model';
|
||||
import { Checkout } from 'src/app/models/checkout.model';
|
||||
import { StoreERP } from 'src/app/models/store.model';
|
||||
import { User } from 'src/app/models/user.model';
|
||||
import { LookupService } from 'src/app/services/lookup.service';
|
||||
|
||||
@Component({
|
||||
selector: 'app-checkout',
|
||||
templateUrl: './checkout.component.html',
|
||||
styleUrls: ['./checkout.component.css']
|
||||
})
|
||||
export class CheckoutComponent implements OnInit, OnDestroy {
|
||||
@ViewChild('combo') public combo: ComboBoxComponent;
|
||||
|
||||
public stores: StoreERP[] = [];
|
||||
public checkouts: Checkout[] = [];
|
||||
public users: User[] = [];
|
||||
public checkoutOrders: CheckoutOrder[] = [];
|
||||
public value: Date = new Date();
|
||||
public format: FormatSettings = {
|
||||
displayFormat: 'dd/MM/yyyy',
|
||||
inputFormat: 'dd/MM/yyyy',
|
||||
};
|
||||
|
||||
public selectStore: StoreERP;
|
||||
public selectCheckout: Checkout;
|
||||
public selectUser: User;
|
||||
public isDisabledCheckout = true;
|
||||
public isDisabledUser = true;
|
||||
|
||||
constructor(private lookupService: LookupService) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.lookupService.getStore().subscribe((data) => (this.stores = data));
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
throw new Error('Method not implemented.');
|
||||
/*****NAO ESQUECER DO UNSUBSCRIBE************/
|
||||
}
|
||||
|
||||
fechDataStore(idStore: string) {
|
||||
this.lookupService.getCheckout(idStore).subscribe((data) => (this.checkouts = data));
|
||||
this.lookupService.getUser(idStore).subscribe((data) => (this.users = data));
|
||||
}
|
||||
|
||||
handleStoreChange(value) {
|
||||
this.selectStore = value;
|
||||
|
||||
if (value === undefined) {
|
||||
this.isDisabledCheckout = true;
|
||||
this.checkouts = [];
|
||||
this.isDisabledUser = true;
|
||||
this.users = [];
|
||||
} else {
|
||||
this.isDisabledCheckout = false;
|
||||
this.lookupService.getCheckout(value.id).subscribe((data) => (this.checkouts = data));
|
||||
this.isDisabledUser = false;
|
||||
this.lookupService.getUser(value.id).subscribe((data) => (this.users = data));
|
||||
}
|
||||
}
|
||||
|
||||
handleCheckoutChange(value) {
|
||||
this.selectCheckout = value;
|
||||
}
|
||||
|
||||
|
||||
handleUserChange(value) {
|
||||
this.selectUser = value;
|
||||
}
|
||||
|
||||
findOrders(){
|
||||
console.log(this.selectStore);
|
||||
console.log(this.selectCheckout);
|
||||
console.log(this.selectUser);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
16
src/app/financial/financial-routing.module.ts
Normal file
16
src/app/financial/financial-routing.module.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { RouterModule, Routes } from '@angular/router';
|
||||
import { CheckoutComponent } from './checkout/checkout.component';
|
||||
|
||||
const routes: Routes = [{ path: 'checkout', component: CheckoutComponent }];
|
||||
|
||||
@NgModule({
|
||||
declarations: [],
|
||||
imports: [
|
||||
CommonModule,
|
||||
RouterModule.forChild(routes)
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class FinancialRoutingModule { }
|
||||
18
src/app/financial/financial.module.ts
Normal file
18
src/app/financial/financial.module.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CheckoutComponent } from './checkout/checkout.component';
|
||||
import { FinancialRoutingModule } from './financial-routing.module';
|
||||
import { KendoModule } from '../shared/kendo.module';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
@NgModule({
|
||||
declarations: [CheckoutComponent],
|
||||
imports: [
|
||||
CommonModule,
|
||||
FinancialRoutingModule,
|
||||
FormsModule,
|
||||
KendoModule,
|
||||
]
|
||||
})
|
||||
|
||||
export class FinancialModule { }
|
||||
16
src/app/guards/auth.guard.spec.ts
Normal file
16
src/app/guards/auth.guard.spec.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { AuthGuard } from './auth.guard';
|
||||
|
||||
describe('AuthGuardService', () => {
|
||||
let service: AuthGuard;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({});
|
||||
service = TestBed.inject(AuthGuard);
|
||||
});
|
||||
|
||||
it('should be created', () => {
|
||||
expect(service).toBeTruthy();
|
||||
});
|
||||
});
|
||||
24
src/app/guards/auth.guard.ts
Normal file
24
src/app/guards/auth.guard.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router';
|
||||
import { Observable } from 'rxjs';
|
||||
import { AuthService } from '../auth/services/auth.service';
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class AuthGuard implements CanActivate {
|
||||
|
||||
constructor(private authService: AuthService, private router: Router) { }
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot,
|
||||
state: RouterStateSnapshot): Observable<boolean> | boolean {
|
||||
if (this.authService.isAuthenticate()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
this.router.navigate(['/login']);
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
30
src/app/interceptions/error.handle.ts
Normal file
30
src/app/interceptions/error.handle.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import { ErrorHandler, Injectable, NgZone } from '@angular/core';
|
||||
import { DialogService } from '@progress/kendo-angular-dialog';
|
||||
import { MessageErrorComponent } from '../shared/menssages/message-error/message-error.component';
|
||||
|
||||
@Injectable()
|
||||
export class ErrorsHandler implements ErrorHandler {
|
||||
constructor(private dialogService: DialogService, private ngZone: NgZone) {}
|
||||
|
||||
handleError(error: any) {
|
||||
console.log(error.message);
|
||||
const dialogRef = this.dialogService
|
||||
.open({
|
||||
title: 'Error Dialog',
|
||||
content: MessageErrorComponent,
|
||||
actions: [{ text: 'OK', primary: true }],
|
||||
width: 400,
|
||||
height: 550,
|
||||
minWidth: 250,
|
||||
});
|
||||
|
||||
const messageInfo = dialogRef.content.instance;
|
||||
messageInfo.status = error.status;
|
||||
messageInfo.message = error.message;
|
||||
console.log(error.status + '-' + error.message);
|
||||
this.ngZone.run(() => {
|
||||
dialogRef.result.subscribe((result) => console.log(result));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
188
src/app/menu-ecosistema/menu-ecosistema.component.html
Normal file
188
src/app/menu-ecosistema/menu-ecosistema.component.html
Normal file
@@ -0,0 +1,188 @@
|
||||
<header>
|
||||
<app-header-system></app-header-system>
|
||||
</header>
|
||||
|
||||
<main class="container">
|
||||
<div id="title-page" class="mt-3 ms-2">
|
||||
<h1>Selecione o módulo desejado</h1>
|
||||
</div>
|
||||
<div class="row g-3 m-2 align-items-center">
|
||||
<div *ngIf="moduleSale" id="item-module" class="col-12 col-sm-6 col-md-4 col-lg-2 ">
|
||||
<a (click)="openModule('sales/menu')">
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
<svg class="mt-3 m-3" width="55" height="55" viewBox="0 0 90 80" fill="#EC7E31"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<g>
|
||||
<path d="M22,66h5c1.1,0,2-0.9,2-2V33c0-1.1-0.9-2-2-2h-5c-1.1,0-2,0.9-2,2v31C20,65.1,20.9,66,22,66z" />
|
||||
</g>
|
||||
<g>
|
||||
<path d="M78,31h-5c-1.1,0-2,0.9-2,2v31c0,1.1,0.9,2,2,2h5c1.1,0,2-0.9,2-2V33C80,31.9,79.1,31,78,31z" />
|
||||
</g>
|
||||
<g>
|
||||
<path d="M53,66c1.1,0,2-0.9,2-2V33c0-1.1-0.9-2-2-2h-6c-1.1,0-2,0.9-2,2v31c0,1.1,0.9,2,2,2H53z" />
|
||||
</g>
|
||||
<g>
|
||||
<path d="M65,66c1.1,0,2-0.9,2-2V33c0-1.1-0.9-2-2-2h-2c-1.1,0-2,0.9-2,2v31c0,1.1,0.9,2,2,2H65z" />
|
||||
</g>
|
||||
<g>
|
||||
<path d="M39,66c1.1,0,2-0.9,2-2V33c0-1.1-0.9-2-2-2h-2c-1.1,0-2,0.9-2,2v31c0,1.1,0.9,2,2,2H39z" />
|
||||
</g>
|
||||
<g>
|
||||
<path d="M78,72H22c-1.1,0-2,0.9-2,2v2c0,1.1,0.9,2,2,2h56c1.1,0,2-0.9,2-2v-2C80,72.9,79.1,72,78,72z" />
|
||||
</g>
|
||||
<g>
|
||||
<path d="M78,20H22c-1.1,0-2,0.9-2,2v2c0,1.1,0.9,2,2,2h56c1.1,0,2-0.9,2-2v-2C80,20.9,79.1,20,78,20z" />
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Vendas</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div *ngIf="modulePartner" id="item-module" class="col-12 col-sm-6 col-md-4 col-lg-2 align-self-center">
|
||||
<a (click)="openModule('partner')">
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
|
||||
<svg class="mt-3 m-3" width="55" height="55" viewBox="0 0 90 80" fill="#EC7E31"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path
|
||||
d="M56.19,20.52a1.73,1.73,0,0,0-2.47,0l-2.47,2.25a1.62,1.62,0,0,0,0,2.43l4.21,4.08a1.1,1.1,0,0,1-.82,1.9H31.83A1.92,1.92,0,0,0,30,32.92v3.46a1.85,1.85,0,0,0,1.83,1.74H54.64a1.12,1.12,0,0,1,.82,1.9L51.25,44.1a1.62,1.62,0,0,0,0,2.43L53.72,49a1.72,1.72,0,0,0,2.47,0L69.65,36a1.62,1.62,0,0,0,0-2.43ZM44,51.05a1.73,1.73,0,0,1,2.48,0L49,53.3a1.62,1.62,0,0,1,0,2.43L44.74,59.8a1.1,1.1,0,0,0,.82,1.91H68.37a1.92,1.92,0,0,1,1.83,1.73v3.47a1.85,1.85,0,0,1-1.83,1.73H45.56a1.12,1.12,0,0,0-.82,1.91L49,74.63a1.61,1.61,0,0,1,0,2.42l-2.47,2.43a1.74,1.74,0,0,1-2.48,0l-13.45-13a1.62,1.62,0,0,1,0-2.43Z"
|
||||
fill-rule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Mestre Jurunense</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div *ngIf="moduleAdmin" id="item-module" class="col-12 col-sm-6 col-md-4 col-lg-2 align-self-center">
|
||||
<a (click)="openModule('admin/permission-user')">
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
<div class="svg-container">
|
||||
<svg class="mt-3 m-3" width="55" height="55" viewBox="0 0 90 80" fill="#EC7E31"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<g>
|
||||
<path d="M25.8,60.6h-4.5c-0.7,0-1.3,0.6-1.3,1.3v16.1c0,0.7,0.6,1.3,1.3,1.3h2.2c2,0,3.6-1.6,3.6-3.6V62
|
||||
C27.2,61.2,26.5,60.6,25.8,60.6z" />
|
||||
<path d="M79.9,69.4c-0.7-1.6-2-3.3-3.9-3.5c-1-0.1-2,0.3-2.9,0.6c-3.6,1.3-7.2,2.5-10.8,3.8
|
||||
c-2.3,0.8-4.7,1.6-7.2,1.8c-1.7,0.1-3.4,0-5.1,0c-0.9,0-1.7-0.7-1.7-1.7s0.7-1.7,1.7-1.7l9.1,0c1.7,0,3-1.4,3-3s-1.4-3-3-3h-7
|
||||
c-0.3,0-2.2-0.1-3.4-0.6c-1.3-0.6-3-0.7-3-0.6c0,0,0,0-0.1,0H33.4c-1.5,0-2.7,1.2-2.7,2.7v11.3c0,1.3,1,2.4,2.3,2.6
|
||||
c0.1,0,0.2,0,0.3,0c2.3,0,4.6,0.5,6.9,0.9c2.3,0.5,4.5,0.8,6.9,0.8c3,0.1,6.1-0.4,9-1.1c2.9-0.8,5.7-1.9,8.5-2.8
|
||||
c4.8-1.6,9.7-3.3,14.5-4.9C79.7,70.7,80.2,70.2,79.9,69.4z" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M58,40.1v15c0,0.5,0.5,0.7,0.9,0.6c2.9-1.7,11.9-6.7,11.9-6.7
|
||||
c1.2-0.7,1.9-1.9,1.9-3.3V32.2c0-0.5-0.5-0.7-0.9-0.6l-13.2,7.4C58.3,39.3,58,39.7,58,40.1" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M56.8,36L70,28.6c0.4-0.2,0.4-0.8,0-1c-2.9-1.7-12-6.8-12-6.8
|
||||
c-1.2-0.7-2.6-0.7-3.8,0c0,0-9,5.1-12,6.8c-0.4,0.2-0.4,0.8,0,1L55.6,36C55.9,36.2,56.4,36.2,56.8,36" />
|
||||
<path fill-rule="evenodd" clip-rule="evenodd"
|
||||
d="M53.7,39.1l-13.2-7.4c-0.4-0.2-0.9,0.1-0.9,0.6v13.4
|
||||
c0,1.3,0.7,2.6,1.9,3.3c0,0,9,5.1,11.9,6.7c0.4,0.2,0.9-0.1,0.9-0.6V40.1C54.3,39.7,54.1,39.3,53.7,39.1" />
|
||||
</g>
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Configurações</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<!--div class="container mt-3 mb-3 border rounded-3 shadow" style="height: 85vh">
|
||||
<h1>Selecione o módulo desejado</h1>
|
||||
<div class="row g-3 m-2 align-items-center">
|
||||
<div class="col-12 col-sm-6 col-md-4 col-lg-2">
|
||||
<a href="/#/sales/menu">
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
<svg
|
||||
class="mt-3 m-3"
|
||||
width="54"
|
||||
height="55"
|
||||
viewBox="0 0 54 55"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19.6602 31.7765C24.8584 30.7533 28.443 25.8649 27.9396 20.4861C27.4362 15.1068 23.0092 11 17.7154 11C12.421 11 7.99461 15.1068 7.49064 20.4861C6.98722 25.8649 10.5718 30.7533 15.77 31.7765C6.797 32.8025 0.00929224 40.5424 0 49.7584V55H35.4444V49.7584C35.439 40.5357 28.6414 32.7913 19.6602 31.7765ZM10.257 21.4792C10.257 17.267 13.6022 13.852 17.7291 13.852C21.8559 13.852 25.2017 17.267 25.2017 21.4792C25.2017 25.6914 21.8559 29.1058 17.7291 29.1058C13.6038 29.1019 10.2608 25.6897 10.257 21.4792ZM32.6458 52.1435H2.7986V49.7584C2.7986 41.3418 9.48301 34.5192 17.7291 34.5192C25.9751 34.5192 32.6595 41.3418 32.6595 49.7584V52.1435H32.6458Z"
|
||||
fill="#EC7E31"
|
||||
/>
|
||||
<path
|
||||
d="M41.2061 0V24.4444"
|
||||
stroke="#EC7E31"
|
||||
stroke-width="3"
|
||||
/>
|
||||
<path
|
||||
d="M53.4282 12.6436L28.1108 12.6436"
|
||||
stroke="#EC7E31"
|
||||
stroke-width="3"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Vendas</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-12 col-sm-6 col-md-4 col-lg-2 align-self-center">
|
||||
<a href="/#/partner">
|
||||
<div class="card">
|
||||
<div class="card-title">
|
||||
<svg
|
||||
class="mt-3 m-3"
|
||||
width="54"
|
||||
height="55"
|
||||
viewBox="0 0 54 55"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M19.6602 31.7765C24.8584 30.7533 28.443 25.8649 27.9396 20.4861C27.4362 15.1068 23.0092 11 17.7154 11C12.421 11 7.99461 15.1068 7.49064 20.4861C6.98722 25.8649 10.5718 30.7533 15.77 31.7765C6.797 32.8025 0.00929224 40.5424 0 49.7584V55H35.4444V49.7584C35.439 40.5357 28.6414 32.7913 19.6602 31.7765ZM10.257 21.4792C10.257 17.267 13.6022 13.852 17.7291 13.852C21.8559 13.852 25.2017 17.267 25.2017 21.4792C25.2017 25.6914 21.8559 29.1058 17.7291 29.1058C13.6038 29.1019 10.2608 25.6897 10.257 21.4792ZM32.6458 52.1435H2.7986V49.7584C2.7986 41.3418 9.48301 34.5192 17.7291 34.5192C25.9751 34.5192 32.6595 41.3418 32.6595 49.7584V52.1435H32.6458Z"
|
||||
fill="#EC7E31"
|
||||
/>
|
||||
<path
|
||||
d="M41.2061 0V24.4444"
|
||||
stroke="#EC7E31"
|
||||
stroke-width="3"
|
||||
/>
|
||||
<path
|
||||
d="M53.4282 12.6436L28.1108 12.6436"
|
||||
stroke="#EC7E31"
|
||||
stroke-width="3"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="card-text">Mestre Jurunese</p>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row h-100">
|
||||
<div class="col-7 p-0">
|
||||
<img
|
||||
src="../../assets/img/loja.jpeg"
|
||||
alt=""
|
||||
style="width: 100%; height: 100%"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-5" style="background-color: white">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div-->
|
||||
|
||||
<footer></footer>
|
||||
182
src/app/menu-ecosistema/menu-ecosistema.component.scss
Normal file
182
src/app/menu-ecosistema/menu-ecosistema.component.scss
Normal file
@@ -0,0 +1,182 @@
|
||||
.row.menu {
|
||||
height: 90%;
|
||||
margin: 60px 25px 25px 25px;
|
||||
background: #f8f8f8;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
height: 90vh;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 200px;
|
||||
height: 160px;
|
||||
background: #ffffff;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.card-small {
|
||||
width: 180px;
|
||||
height: 150px;
|
||||
background: #ffffff;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
width: 170px;
|
||||
height: 44px;
|
||||
|
||||
font-family: Montserrat;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
text-transform: uppercase;
|
||||
text-decoration: none;
|
||||
|
||||
color: #1c1e54;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.card:hover {
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 4px 17px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.a-wrapper-customer {
|
||||
width: 95%;
|
||||
min-height: 95%;
|
||||
margin-top: 5px;
|
||||
background: #f8f8f8;
|
||||
border-radius: 25px;
|
||||
}
|
||||
|
||||
.title {
|
||||
width: 136px;
|
||||
height: 44px;
|
||||
|
||||
font-family: Montserrat;
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
font-size: 18px;
|
||||
line-height: 22px;
|
||||
text-transform: uppercase;
|
||||
|
||||
color: #1c1e54;
|
||||
}
|
||||
|
||||
.a-title-page {
|
||||
width: 290px;
|
||||
height: 98px;
|
||||
|
||||
font-family: Montserrat;
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-size: 40px;
|
||||
line-height: 49px;
|
||||
|
||||
color: #6b6ebe;
|
||||
}
|
||||
|
||||
.a-search-customer {
|
||||
width: 100%;
|
||||
height: 60px;
|
||||
background: #ffffff;
|
||||
border-radius: 20px;
|
||||
}
|
||||
|
||||
.a-input {
|
||||
height: 27px;
|
||||
|
||||
font-family: Montserrat;
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-size: 22px;
|
||||
line-height: 27px;
|
||||
border: none;
|
||||
/* identical to box height */
|
||||
|
||||
text-align: center;
|
||||
|
||||
color: #c4c4c4;
|
||||
}
|
||||
|
||||
.custom-size {
|
||||
width: 150px;
|
||||
height: 150px;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Smartphones */
|
||||
@media (max-width: 575.98px) {
|
||||
#title-page {
|
||||
padding-top: 90px;
|
||||
}
|
||||
|
||||
#item-module {
|
||||
margin-bottom: 00px;
|
||||
}
|
||||
|
||||
h1{
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.card-small {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.row.g-3.m-2.align-items-center {
|
||||
flex-direction: column;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0 10px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tablets */
|
||||
@media (max-width: 991.98px) {
|
||||
#title-page {
|
||||
padding-top: 90px;
|
||||
}
|
||||
|
||||
#item-module {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
h1{
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.card {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.card-text {
|
||||
font-size: 18px;
|
||||
text-align: right;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.card-bdy {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
25
src/app/menu-ecosistema/menu-ecosistema.component.spec.ts
Normal file
25
src/app/menu-ecosistema/menu-ecosistema.component.spec.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { MenuEcosistemaComponent } from './menu-ecosistema.component';
|
||||
|
||||
describe('MenuEcosistemaComponent', () => {
|
||||
let component: MenuEcosistemaComponent;
|
||||
let fixture: ComponentFixture<MenuEcosistemaComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ MenuEcosistemaComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MenuEcosistemaComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
63
src/app/menu-ecosistema/menu-ecosistema.component.ts
Normal file
63
src/app/menu-ecosistema/menu-ecosistema.component.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { AuthService } from '../auth/services/auth.service';
|
||||
import { ModuleSystem } from '../models/module.model';
|
||||
|
||||
@Component({
|
||||
selector: 'app-menu-ecosistema',
|
||||
templateUrl: './menu-ecosistema.component.html',
|
||||
styleUrls: ['./menu-ecosistema.component.scss']
|
||||
})
|
||||
export class MenuEcosistemaComponent implements OnInit {
|
||||
|
||||
modules: ModuleSystem[];
|
||||
moduleSale: boolean = true;
|
||||
modulePartner: boolean = true;
|
||||
moduleAdmin = true;
|
||||
|
||||
constructor(
|
||||
private readonly router: Router,
|
||||
private readonly authService: AuthService) { }
|
||||
|
||||
|
||||
|
||||
ngOnInit(): void {
|
||||
this.authService.getModules(this.authService.getUser())
|
||||
.subscribe(m => {
|
||||
this.modules = m;
|
||||
this.modulesUser();
|
||||
});
|
||||
}
|
||||
|
||||
modulesUser() {
|
||||
console.log(JSON.stringify(this.modules));
|
||||
let module = this.modules.find(m => m.moduleId == 1) ;
|
||||
if ( module === null ){
|
||||
this.moduleSale = false;
|
||||
} else {
|
||||
console.log(JSON.stringify(module));
|
||||
this.moduleSale = module.access == "S";
|
||||
}
|
||||
module = this.modules.find(m => m.moduleId == 2) ;
|
||||
if ( module === undefined ){
|
||||
this.modulePartner = false;
|
||||
} else {
|
||||
console.log(JSON.stringify(module));
|
||||
this.modulePartner = module.access == "S";
|
||||
}
|
||||
module = this.modules.find(m => m.moduleId == 3) ;
|
||||
this.moduleAdmin = false;
|
||||
if ( module === undefined || module == null ){
|
||||
this.moduleAdmin = false;
|
||||
} else {
|
||||
console.log(JSON.stringify(module));
|
||||
this.moduleAdmin = module.access == "S";
|
||||
}
|
||||
}
|
||||
|
||||
openModule(url: string) {
|
||||
this.router.navigate([url]);
|
||||
// window.open(url, '_blank');
|
||||
}
|
||||
|
||||
}
|
||||
167
src/app/menu/menu.component.html
Normal file
167
src/app/menu/menu.component.html
Normal file
@@ -0,0 +1,167 @@
|
||||
|
||||
<!--Navbar -->
|
||||
<nav class="navbar navbar-expand-lg navbar-dark bg-dark fixed-top">
|
||||
<div class="container-fluid">
|
||||
<!-- offcanvas trigger-->
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="offcanvas"
|
||||
data-bs-target="#offcanvasExample"
|
||||
aria-controls="offcanvasExample"
|
||||
>
|
||||
<span
|
||||
class="navbar-toggler-icon"
|
||||
data-bs-target="#offcanvasExample"
|
||||
></span>
|
||||
</button>
|
||||
<!-- offcanvas trigger-->
|
||||
<a class="navbar-brand" style="height: 40px; width: 120px" href="#">
|
||||
<img src="assets/img/logo.svg" alt="" />
|
||||
</a>
|
||||
<button
|
||||
class="navbar-toggler"
|
||||
type="button"
|
||||
data-bs-toggle="collapse"
|
||||
data-bs-target="#navbarSupportedContent"
|
||||
aria-controls="navbarSupportedContent"
|
||||
aria-expanded="false"
|
||||
aria-label="Toggle navigation"
|
||||
>
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||
<form class="d-flex ms-auto">
|
||||
<div class="input-group my-3 my-lg-0">
|
||||
<input
|
||||
class="form-control me-2"
|
||||
type="search"
|
||||
placeholder="Search"
|
||||
aria-label="Search"
|
||||
/>
|
||||
<button class="btn btn-outline-success" type="submit">Search</button>
|
||||
</div>
|
||||
</form>
|
||||
<ul class="navbar-nav mb-2 mb-lg-0">
|
||||
<li class="nav-item dropdown">
|
||||
<a
|
||||
class="nav-link dropdown-toggle"
|
||||
href="#"
|
||||
id="navbarDropdown"
|
||||
role="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<i class="bi bi-person-fill"></i>
|
||||
</a>
|
||||
<ul
|
||||
class="dropdown-menu dropdown-menu-end"
|
||||
aria-labelledby="navbarDropdown"
|
||||
>
|
||||
<li><a class="dropdown-item" href="#">Action</a></li>
|
||||
<li><a class="dropdown-item" href="#">Another action</a></li>
|
||||
<li><hr class="dropdown-divider" /></li>
|
||||
<li><a class="dropdown-item" href="#">Something else here</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<!-- Navbar -->
|
||||
|
||||
<!-- OffCanvas -->
|
||||
<div
|
||||
class="offcanvas offcanvas-start sidebar-nav bg-dark text-light"
|
||||
data-bs-backdrop="false"
|
||||
data-bs-scroll="true"
|
||||
tabindex="-1"
|
||||
id="offcanvasExample"
|
||||
aria-labelledby="offcanvasExampleLabel"
|
||||
>
|
||||
<div class="offcanvas-header">
|
||||
<h5 class="offcanvas-title" id="offcanvasExampleLabel">Módulo de vendas</h5>
|
||||
</div>
|
||||
<div class="offcanvas-body">
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link px-3 sidebar-link"
|
||||
>
|
||||
<span><i class="bi bi-graph-up-arrow me-2"></i></span>
|
||||
<span>Dashboard</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link px-3 sidebar-link"
|
||||
data-bs-toggle="collapse"
|
||||
href="#collapseExample"
|
||||
role="button"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseExample"
|
||||
>
|
||||
<span><i class="bi bi-shop me-2"></i></span>
|
||||
<span>Vendas</span>
|
||||
<span class="right-icon ms-auto"
|
||||
><i class="bi bi-chevron-down"></i
|
||||
></span>
|
||||
</a>
|
||||
|
||||
<div class="collapse" id="collapseExample">
|
||||
<div>
|
||||
<ul class="navbar-nav ps-3">
|
||||
<li>
|
||||
<a href="#" class="nav-link px-3">
|
||||
<span>Pedidos de venda</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a
|
||||
class="nav-link px-3 sidebar-link"
|
||||
data-bs-toggle="collapse"
|
||||
href="#collapseregister"
|
||||
role="button"
|
||||
aria-expanded="false"
|
||||
aria-controls="collapseregister"
|
||||
>
|
||||
<span><i class="bi bi-person-plus me-2"></i></span>
|
||||
<span>Cadastros</span>
|
||||
<span class="right-icon ms-auto"
|
||||
><i class="bi bi-chevron-down"></i
|
||||
></span>
|
||||
</a>
|
||||
|
||||
<div class="collapse" id="collapseregister">
|
||||
<div>
|
||||
<ul class="navbar-nav ps-3">
|
||||
<li>
|
||||
<a href="#" class="nav-link px-3">
|
||||
<span>Clientes</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<!-- OffCanvas -->
|
||||
|
||||
<main class="mt-5 pt-3">
|
||||
<div class="container-fluid">
|
||||
<span>teste</span>
|
||||
<router-outlet></router-outlet>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
61
src/app/menu/menu.component.scss
Normal file
61
src/app/menu/menu.component.scss
Normal file
@@ -0,0 +1,61 @@
|
||||
.navbar {
|
||||
background-color: rgba(28, 30, 84, 1);
|
||||
}
|
||||
|
||||
#menu-vertical{
|
||||
position:fixed;
|
||||
z-index:999;
|
||||
overflow:hidden;
|
||||
padding:6px;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
:root {
|
||||
--offcanvas-width: 270px;
|
||||
--topNavbarHeight: 56px;
|
||||
}
|
||||
|
||||
.sidebar-nav {
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.sidebar-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.sidebar-link .right-icon {
|
||||
display: inline-flex;
|
||||
transition: all ease 0.25s;
|
||||
}
|
||||
|
||||
.sidebar-link[aria-expanded="true"] .right-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
li a {
|
||||
text-decoration: none;
|
||||
color: white;
|
||||
}
|
||||
|
||||
@media (min-width: 992px) {
|
||||
|
||||
body {
|
||||
overflow: auto !important;
|
||||
}
|
||||
|
||||
main {
|
||||
margin-left: 270px;
|
||||
}
|
||||
|
||||
.offcanvas-backdrop::before{
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sidebar-nav{
|
||||
transform: none;
|
||||
visibility: visible !important;
|
||||
top: 56px;
|
||||
height: calc(100% - 56px);
|
||||
}
|
||||
}
|
||||
28
src/app/menu/menu.component.spec.ts
Normal file
28
src/app/menu/menu.component.spec.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
/* tslint:disable:no-unused-variable */
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { By } from '@angular/platform-browser';
|
||||
import { DebugElement } from '@angular/core';
|
||||
|
||||
import { MenuComponent } from './menu.component';
|
||||
|
||||
describe('MenuComponent', () => {
|
||||
let component: MenuComponent;
|
||||
let fixture: ComponentFixture<MenuComponent>;
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [ MenuComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(MenuComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
15
src/app/menu/menu.component.ts
Normal file
15
src/app/menu/menu.component.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-menu',
|
||||
templateUrl: './menu.component.html',
|
||||
styleUrls: ['./menu.component.scss']
|
||||
})
|
||||
export class MenuComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
8
src/app/models/actions-user.model.ts
Normal file
8
src/app/models/actions-user.model.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export class ActionsUser {
|
||||
moduleId: number;
|
||||
processId: number;
|
||||
pageId: number;
|
||||
actionId: number;
|
||||
userId: number;
|
||||
access: string;
|
||||
}
|
||||
4
src/app/models/auth.user.model.ts
Normal file
4
src/app/models/auth.user.model.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface AuthUser {
|
||||
email: string;
|
||||
password: string;
|
||||
}
|
||||
90
src/app/models/billing.model.ts
Normal file
90
src/app/models/billing.model.ts
Normal file
@@ -0,0 +1,90 @@
|
||||
export interface Billing {
|
||||
codcob: string;
|
||||
cobranca: string;
|
||||
pagcomissao: string;
|
||||
txjuros: number;
|
||||
codmoeda: string;
|
||||
baixacxbanco: string;
|
||||
nivelvenda: number;
|
||||
fluxocx: string;
|
||||
colunafluxocx: number;
|
||||
numdiasvencfluxocx: number;
|
||||
bloqautomatico: string;
|
||||
numdiasbloqautomatic?: any;
|
||||
exibircxmot: string;
|
||||
exibirbk: string;
|
||||
percacresvenda: number;
|
||||
prazomaximovenda: number;
|
||||
letracob?: any;
|
||||
boleto: string;
|
||||
custodia: string;
|
||||
permitealtcobdesd: string;
|
||||
percom: number;
|
||||
vltarifa?: any;
|
||||
codecf?: any;
|
||||
cartao: string;
|
||||
obsnf?: any;
|
||||
numdiasliberacaocredito?: any;
|
||||
codclicc: number;
|
||||
prazocc: number;
|
||||
perctxadmincc: number;
|
||||
codcontacc: number;
|
||||
codcobcc: string;
|
||||
enviacobrancafv: string;
|
||||
validalimcredecf: string;
|
||||
diascarencia: number;
|
||||
acertoautocxmot: string;
|
||||
codparaprotesto: string;
|
||||
envioparaprotesto: string;
|
||||
numdiasprotesto: string;
|
||||
numbanco?: any;
|
||||
permitedescdevcli: string;
|
||||
percommot?: any;
|
||||
cobrancabroker: string;
|
||||
vlminpedido?: any;
|
||||
depositobancario: string;
|
||||
tipocomissao: string;
|
||||
codbancotarifa?: any;
|
||||
codfilial?: any;
|
||||
exportarecf: string;
|
||||
codbanco?: any;
|
||||
somatarifabancduplic?: any;
|
||||
somatarifabancnf?: any;
|
||||
codoperadoracartao: string;
|
||||
tipooperacaotef: string;
|
||||
tipopagtoecf: string;
|
||||
nummaxparcelas?: any;
|
||||
codparanaoprotesto?: any;
|
||||
permitebaixamanual: string;
|
||||
numviascpadicional: string;
|
||||
codbandeira: number;
|
||||
selecionaclienteecf: string;
|
||||
autenticaracertocx402: string;
|
||||
utilizachdesc?: any;
|
||||
codcobchdesc?: any;
|
||||
codcobdevchdesc?: any;
|
||||
permitecontravale: string;
|
||||
cobrancaemtransito: string;
|
||||
calcjuroscobranca: string;
|
||||
codigobandeira?: any;
|
||||
convenio?: any;
|
||||
recargacelular: string;
|
||||
codrede?: any;
|
||||
txprimeiraparcela: string;
|
||||
naovalidaprazomedio?: any;
|
||||
cheque: string;
|
||||
flexivel: string;
|
||||
codcobsefaz: string;
|
||||
codbandeiraoperadoracartao: string;
|
||||
bandeiracartao?: any;
|
||||
percmulta: number;
|
||||
cobsuppliercard: string;
|
||||
indpag: number;
|
||||
dtmxsalter: Date;
|
||||
mxdiasinad?: any;
|
||||
mxinad?: any;
|
||||
codoutro?: any;
|
||||
carteiradigital?: any;
|
||||
nomecarteiradigital?: any;
|
||||
descricaoformapagto?: any;
|
||||
}
|
||||
4
src/app/models/brand.model.ts
Normal file
4
src/app/models/brand.model.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export class BrandFilter {
|
||||
description: string;
|
||||
checked: boolean;
|
||||
}
|
||||
9
src/app/models/calculate-price-color.model.ts
Normal file
9
src/app/models/calculate-price-color.model.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export class CalculatePriceColor {
|
||||
storeId: string;
|
||||
productId: number;
|
||||
letter: string;
|
||||
line: string;
|
||||
can: number;
|
||||
color: string;
|
||||
price: number;
|
||||
}
|
||||
12
src/app/models/cart-itens.model.ts
Normal file
12
src/app/models/cart-itens.model.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
export class CartItensModel {
|
||||
idProduct: number;
|
||||
ean: number;
|
||||
idStock: string;
|
||||
deliveryMethod: string;
|
||||
quantity: number;
|
||||
listPrice: number;
|
||||
salePrice: number;
|
||||
descriptionAux: string;
|
||||
environment?: string;
|
||||
}
|
||||
29
src/app/models/cart.model.ts
Normal file
29
src/app/models/cart.model.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { CartItensModel } from './cart-itens.model';
|
||||
|
||||
export class CartModel {
|
||||
id: string;
|
||||
saleStore: string;
|
||||
userId: number;
|
||||
idCustomer: number;
|
||||
idSeller: number;
|
||||
idProfessional: number;
|
||||
idPaymentPlan: number;
|
||||
idBilling: string;
|
||||
shippingDate: Date;
|
||||
scheduleDelivery: boolean;
|
||||
shippingValue: number;
|
||||
notation1: string;
|
||||
notation2: string;
|
||||
notation3: string;
|
||||
idAddress: number;
|
||||
deliveryNote1: string;
|
||||
deliveryNote2: string;
|
||||
deliveryNote3: string;
|
||||
shippingPriority: string;
|
||||
idStorePlace?: number;
|
||||
preCustomerDocument: string;
|
||||
preCustomerName: string;
|
||||
preCustomerPhone: string;
|
||||
carrierId: number;
|
||||
itens: CartItensModel[];
|
||||
}
|
||||
6
src/app/models/category-partner.model.ts
Normal file
6
src/app/models/category-partner.model.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
export class CategoryPartner {
|
||||
id: number;
|
||||
partnerType: string;
|
||||
name: string;
|
||||
paymentType: string;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user