From 13bfcaf95c5403dc8d3496f2a6273985cea69aed Mon Sep 17 00:00:00 2001 From: Gabriel Masiero Date: Thu, 27 May 2021 16:40:30 -0300 Subject: [PATCH 1/8] commit api project --- desafio-fullstack-api | 1 + 1 file changed, 1 insertion(+) create mode 160000 desafio-fullstack-api diff --git a/desafio-fullstack-api b/desafio-fullstack-api new file mode 160000 index 000000000..31bff9fa9 --- /dev/null +++ b/desafio-fullstack-api @@ -0,0 +1 @@ +Subproject commit 31bff9fa9d76309676c059a15479e37acd73c88a From 0d75bd5928a0419fbef7ecd93d940a40d11f80dd Mon Sep 17 00:00:00 2001 From: Gabriel Masiero Date: Thu, 27 May 2021 16:45:10 -0300 Subject: [PATCH 2/8] commit frontend project --- desafio-fullstack-front/.editorconfig | 13 ++ desafio-fullstack-front/.gitignore | 39 +++++ desafio-fullstack-front/README.md | 27 +++ desafio-fullstack-front/angular.json | 127 ++++++++++++++ .../e2e/protractor.conf.js | 28 ++++ .../e2e/src/app.e2e-spec.ts | 14 ++ desafio-fullstack-front/e2e/src/app.po.ts | 11 ++ desafio-fullstack-front/e2e/tsconfig.e2e.json | 13 ++ desafio-fullstack-front/package.json | 51 ++++++ .../src/app/app-routing.module.ts | 35 ++++ .../src/app/app.component.css | 0 .../src/app/app.component.html | 2 + .../src/app/app.component.ts | 10 ++ desafio-fullstack-front/src/app/app.module.ts | 34 ++++ .../course-detail/course-detail.component.css | 158 ++++++++++++++++++ .../course-detail.component.html | 44 +++++ .../course-detail/course-detail.component.ts | 95 +++++++++++ .../src/app/course/course.component.css | 83 +++++++++ .../src/app/course/course.component.html | 56 +++++++ .../src/app/course/course.component.ts | 36 ++++ .../src/app/login/login.component.css | 49 ++++++ .../src/app/login/login.component.html | 18 ++ .../src/app/login/login.component.ts | 61 +++++++ .../src/app/models/classroom.model.ts | 6 + .../src/app/models/course.model.ts | 13 ++ .../src/app/models/teacher.model.ts | 6 + .../src/app/services/auth.service.ts | 15 ++ .../src/app/services/classroom.service.ts | 17 ++ .../src/app/services/course.service.ts | 32 ++++ .../src/app/services/teacher.service.ts | 17 ++ desafio-fullstack-front/src/assets/.gitkeep | 0 .../src/assets/images/add-outline.svg | 1 + .../src/assets/images/trash-outline.svg | 1 + desafio-fullstack-front/src/browserslist | 9 + .../src/environments/environment.prod.ts | 3 + .../src/environments/environment.ts | 17 ++ desafio-fullstack-front/src/favicon.ico | Bin 0 -> 5430 bytes desafio-fullstack-front/src/index.html | 14 ++ desafio-fullstack-front/src/karma.conf.js | 31 ++++ desafio-fullstack-front/src/main.ts | 12 ++ desafio-fullstack-front/src/polyfills.ts | 80 +++++++++ desafio-fullstack-front/src/styles.css | 2 + desafio-fullstack-front/src/test.ts | 20 +++ desafio-fullstack-front/src/tsconfig.app.json | 11 ++ .../src/tsconfig.spec.json | 18 ++ desafio-fullstack-front/src/tslint.json | 17 ++ desafio-fullstack-front/tsconfig.json | 21 +++ desafio-fullstack-front/tslint.json | 130 ++++++++++++++ 48 files changed, 1497 insertions(+) create mode 100644 desafio-fullstack-front/.editorconfig create mode 100644 desafio-fullstack-front/.gitignore create mode 100644 desafio-fullstack-front/README.md create mode 100644 desafio-fullstack-front/angular.json create mode 100644 desafio-fullstack-front/e2e/protractor.conf.js create mode 100644 desafio-fullstack-front/e2e/src/app.e2e-spec.ts create mode 100644 desafio-fullstack-front/e2e/src/app.po.ts create mode 100644 desafio-fullstack-front/e2e/tsconfig.e2e.json create mode 100644 desafio-fullstack-front/package.json create mode 100644 desafio-fullstack-front/src/app/app-routing.module.ts create mode 100644 desafio-fullstack-front/src/app/app.component.css create mode 100644 desafio-fullstack-front/src/app/app.component.html create mode 100644 desafio-fullstack-front/src/app/app.component.ts create mode 100644 desafio-fullstack-front/src/app/app.module.ts create mode 100644 desafio-fullstack-front/src/app/course-detail/course-detail.component.css create mode 100644 desafio-fullstack-front/src/app/course-detail/course-detail.component.html create mode 100644 desafio-fullstack-front/src/app/course-detail/course-detail.component.ts create mode 100644 desafio-fullstack-front/src/app/course/course.component.css create mode 100644 desafio-fullstack-front/src/app/course/course.component.html create mode 100644 desafio-fullstack-front/src/app/course/course.component.ts create mode 100644 desafio-fullstack-front/src/app/login/login.component.css create mode 100644 desafio-fullstack-front/src/app/login/login.component.html create mode 100644 desafio-fullstack-front/src/app/login/login.component.ts create mode 100644 desafio-fullstack-front/src/app/models/classroom.model.ts create mode 100644 desafio-fullstack-front/src/app/models/course.model.ts create mode 100644 desafio-fullstack-front/src/app/models/teacher.model.ts create mode 100644 desafio-fullstack-front/src/app/services/auth.service.ts create mode 100644 desafio-fullstack-front/src/app/services/classroom.service.ts create mode 100644 desafio-fullstack-front/src/app/services/course.service.ts create mode 100644 desafio-fullstack-front/src/app/services/teacher.service.ts create mode 100644 desafio-fullstack-front/src/assets/.gitkeep create mode 100644 desafio-fullstack-front/src/assets/images/add-outline.svg create mode 100644 desafio-fullstack-front/src/assets/images/trash-outline.svg create mode 100644 desafio-fullstack-front/src/browserslist create mode 100644 desafio-fullstack-front/src/environments/environment.prod.ts create mode 100644 desafio-fullstack-front/src/environments/environment.ts create mode 100644 desafio-fullstack-front/src/favicon.ico create mode 100644 desafio-fullstack-front/src/index.html create mode 100644 desafio-fullstack-front/src/karma.conf.js create mode 100644 desafio-fullstack-front/src/main.ts create mode 100644 desafio-fullstack-front/src/polyfills.ts create mode 100644 desafio-fullstack-front/src/styles.css create mode 100644 desafio-fullstack-front/src/test.ts create mode 100644 desafio-fullstack-front/src/tsconfig.app.json create mode 100644 desafio-fullstack-front/src/tsconfig.spec.json create mode 100644 desafio-fullstack-front/src/tslint.json create mode 100644 desafio-fullstack-front/tsconfig.json create mode 100644 desafio-fullstack-front/tslint.json diff --git a/desafio-fullstack-front/.editorconfig b/desafio-fullstack-front/.editorconfig new file mode 100644 index 000000000..6e87a003d --- /dev/null +++ b/desafio-fullstack-front/.editorconfig @@ -0,0 +1,13 @@ +# Editor configuration, see http://editorconfig.org +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +max_line_length = off +trim_trailing_whitespace = false diff --git a/desafio-fullstack-front/.gitignore b/desafio-fullstack-front/.gitignore new file mode 100644 index 000000000..ee5c9d833 --- /dev/null +++ b/desafio-fullstack-front/.gitignore @@ -0,0 +1,39 @@ +# See http://help.github.com/ignore-files/ for more about ignoring files. + +# compiled output +/dist +/tmp +/out-tsc + +# dependencies +/node_modules + +# 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 + +# misc +/.sass-cache +/connect.lock +/coverage +/libpeerconnection.log +npm-debug.log +yarn-error.log +testem.log +/typings + +# System Files +.DS_Store +Thumbs.db diff --git a/desafio-fullstack-front/README.md b/desafio-fullstack-front/README.md new file mode 100644 index 000000000..966590328 --- /dev/null +++ b/desafio-fullstack-front/README.md @@ -0,0 +1,27 @@ +# DesafioFullstackFront + +This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.1.1. + +## Development server + +Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. + +## Code scaffolding + +Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. + +## Build + +Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. + +## Running unit tests + +Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). + +## Running end-to-end tests + +Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). + +## Further help + +To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). diff --git a/desafio-fullstack-front/angular.json b/desafio-fullstack-front/angular.json new file mode 100644 index 000000000..62cd18806 --- /dev/null +++ b/desafio-fullstack-front/angular.json @@ -0,0 +1,127 @@ +{ + "$schema": "./node_modules/@angular/cli/lib/config/schema.json", + "version": 1, + "newProjectRoot": "projects", + "projects": { + "desafio-fullstack-front": { + "root": "", + "sourceRoot": "src", + "projectType": "application", + "prefix": "app", + "schematics": {}, + "architect": { + "build": { + "builder": "@angular-devkit/build-angular:browser", + "options": { + "outputPath": "dist/desafio-fullstack-front", + "index": "src/index.html", + "main": "src/main.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.app.json", + "assets": [ + "src/favicon.ico", + "src/assets" + ], + "styles": [ + "src/styles.css" + ], + "scripts": [] + }, + "configurations": { + "production": { + "fileReplacements": [ + { + "replace": "src/environments/environment.ts", + "with": "src/environments/environment.prod.ts" + } + ], + "optimization": true, + "outputHashing": "all", + "sourceMap": false, + "extractCss": true, + "namedChunks": false, + "aot": true, + "extractLicenses": true, + "vendorChunk": false, + "buildOptimizer": true + } + } + }, + "serve": { + "builder": "@angular-devkit/build-angular:dev-server", + "options": { + "browserTarget": "desafio-fullstack-front:build" + }, + "configurations": { + "production": { + "browserTarget": "desafio-fullstack-front:build:production" + } + } + }, + "extract-i18n": { + "builder": "@angular-devkit/build-angular:extract-i18n", + "options": { + "browserTarget": "desafio-fullstack-front:build" + } + }, + "test": { + "builder": "@angular-devkit/build-angular:karma", + "options": { + "main": "src/test.ts", + "polyfills": "src/polyfills.ts", + "tsConfig": "src/tsconfig.spec.json", + "karmaConfig": "src/karma.conf.js", + "styles": [ + "src/styles.css" + ], + "scripts": [], + "assets": [ + "src/favicon.ico", + "src/assets" + ] + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": [ + "src/tsconfig.app.json", + "src/tsconfig.spec.json" + ], + "exclude": [ + "**/node_modules/**" + ] + } + } + } + }, + "desafio-fullstack-front-e2e": { + "root": "e2e/", + "projectType": "application", + "architect": { + "e2e": { + "builder": "@angular-devkit/build-angular:protractor", + "options": { + "protractorConfig": "e2e/protractor.conf.js", + "devServerTarget": "desafio-fullstack-front:serve" + }, + "configurations": { + "production": { + "devServerTarget": "desafio-fullstack-front:serve:production" + } + } + }, + "lint": { + "builder": "@angular-devkit/build-angular:tslint", + "options": { + "tsConfig": "e2e/tsconfig.e2e.json", + "exclude": [ + "**/node_modules/**" + ] + } + } + } + } + }, + "defaultProject": "desafio-fullstack-front" +} \ No newline at end of file diff --git a/desafio-fullstack-front/e2e/protractor.conf.js b/desafio-fullstack-front/e2e/protractor.conf.js new file mode 100644 index 000000000..86776a391 --- /dev/null +++ b/desafio-fullstack-front/e2e/protractor.conf.js @@ -0,0 +1,28 @@ +// Protractor configuration file, see link for more information +// https://github.com/angular/protractor/blob/master/lib/config.ts + +const { SpecReporter } = require('jasmine-spec-reporter'); + +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.e2e.json') + }); + jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); + } +}; \ No newline at end of file diff --git a/desafio-fullstack-front/e2e/src/app.e2e-spec.ts b/desafio-fullstack-front/e2e/src/app.e2e-spec.ts new file mode 100644 index 000000000..a0b19ea84 --- /dev/null +++ b/desafio-fullstack-front/e2e/src/app.e2e-spec.ts @@ -0,0 +1,14 @@ +import { AppPage } from './app.po'; + +describe('workspace-project App', () => { + let page: AppPage; + + beforeEach(() => { + page = new AppPage(); + }); + + it('should display welcome message', () => { + page.navigateTo(); + expect(page.getParagraphText()).toEqual('Welcome to desafio-fullstack-front!'); + }); +}); diff --git a/desafio-fullstack-front/e2e/src/app.po.ts b/desafio-fullstack-front/e2e/src/app.po.ts new file mode 100644 index 000000000..82ea75ba5 --- /dev/null +++ b/desafio-fullstack-front/e2e/src/app.po.ts @@ -0,0 +1,11 @@ +import { browser, by, element } from 'protractor'; + +export class AppPage { + navigateTo() { + return browser.get('/'); + } + + getParagraphText() { + return element(by.css('app-root h1')).getText(); + } +} diff --git a/desafio-fullstack-front/e2e/tsconfig.e2e.json b/desafio-fullstack-front/e2e/tsconfig.e2e.json new file mode 100644 index 000000000..a6dd62202 --- /dev/null +++ b/desafio-fullstack-front/e2e/tsconfig.e2e.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/app", + "module": "commonjs", + "target": "es5", + "types": [ + "jasmine", + "jasminewd2", + "node" + ] + } +} \ No newline at end of file diff --git a/desafio-fullstack-front/package.json b/desafio-fullstack-front/package.json new file mode 100644 index 000000000..5e344cc4b --- /dev/null +++ b/desafio-fullstack-front/package.json @@ -0,0 +1,51 @@ +{ + "name": "desafio-fullstack-front", + "version": "0.0.0", + "scripts": { + "ng": "ng", + "start": "ng serve", + "build": "ng build", + "test": "ng test", + "lint": "ng lint", + "e2e": "ng e2e" + }, + "private": true, + "dependencies": { + "@angular/animations": "^6.1.0", + "@angular/cdk": "^12.0.2", + "@angular/common": "^6.1.0", + "@angular/compiler": "^6.1.0", + "@angular/core": "^6.1.0", + "@angular/forms": "^6.1.0", + "@angular/http": "^6.1.0", + "@angular/platform-browser": "^6.1.0", + "@angular/platform-browser-dynamic": "^6.1.0", + "@angular/router": "^6.1.0", + "@ng-select/ng-select": "^2.20.5", + "core-js": "^2.5.4", + "rxjs": "6.0.0", + "sweetalert2": "^8.14.0", + "zone.js": "~0.8.26" + }, + "devDependencies": { + "@angular-devkit/build-angular": "~0.7.0", + "@angular/cli": "~6.1.1", + "@angular/compiler-cli": "^6.1.0", + "@angular/language-service": "^6.1.0", + "@types/jasmine": "~2.8.6", + "@types/jasminewd2": "~2.0.3", + "@types/node": "~8.9.4", + "codelyzer": "~4.2.1", + "jasmine-core": "~2.99.1", + "jasmine-spec-reporter": "~4.2.1", + "karma": "~1.7.1", + "karma-chrome-launcher": "~2.2.0", + "karma-coverage-istanbul-reporter": "~2.0.0", + "karma-jasmine": "~1.1.1", + "karma-jasmine-html-reporter": "^0.2.2", + "protractor": "~5.3.0", + "ts-node": "~5.0.1", + "tslint": "~5.9.1", + "typescript": "~2.7.2" + } +} diff --git a/desafio-fullstack-front/src/app/app-routing.module.ts b/desafio-fullstack-front/src/app/app-routing.module.ts new file mode 100644 index 000000000..002e7de21 --- /dev/null +++ b/desafio-fullstack-front/src/app/app-routing.module.ts @@ -0,0 +1,35 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; +import { CourseDetailComponent } from './course-detail/course-detail.component'; +import { CourseComponent } from './course/course.component'; +import { LoginComponent } from './login/login.component'; + +const routes: Routes = [ + { + path: '', + component: LoginComponent, + }, + { + path: 'course', + component: CourseComponent + }, + { + path: 'course-detail', + component: CourseDetailComponent + }, + { + path: 'course-detail/:id', + component: CourseDetailComponent + } +]; + +@NgModule({ + imports: [ + RouterModule.forRoot(routes) + ], + exports: [ + RouterModule + ], + declarations: [] +}) +export class AppRoutingModule { } \ No newline at end of file diff --git a/desafio-fullstack-front/src/app/app.component.css b/desafio-fullstack-front/src/app/app.component.css new file mode 100644 index 000000000..e69de29bb diff --git a/desafio-fullstack-front/src/app/app.component.html b/desafio-fullstack-front/src/app/app.component.html new file mode 100644 index 000000000..6a164d697 --- /dev/null +++ b/desafio-fullstack-front/src/app/app.component.html @@ -0,0 +1,2 @@ + + diff --git a/desafio-fullstack-front/src/app/app.component.ts b/desafio-fullstack-front/src/app/app.component.ts new file mode 100644 index 000000000..4ac4cfdbf --- /dev/null +++ b/desafio-fullstack-front/src/app/app.component.ts @@ -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 = 'desafio-fullstack-front'; +} diff --git a/desafio-fullstack-front/src/app/app.module.ts b/desafio-fullstack-front/src/app/app.module.ts new file mode 100644 index 000000000..3e9848ca7 --- /dev/null +++ b/desafio-fullstack-front/src/app/app.module.ts @@ -0,0 +1,34 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core'; + +import { AppComponent } from './app.component'; +import { LoginComponent } from './login/login.component'; +import { AppRoutingModule } from './app-routing.module'; +import { FormsModule, ReactiveFormsModule } from '@angular/forms'; +import { HttpClientModule } from '@angular/common/http'; +import { CourseComponent } from './course/course.component'; +import { CourseDetailComponent } from './course-detail/course-detail.component'; +import { NgMultiSelectDropDownModule } from 'ng-multiselect-dropdown'; +import { NgSelectModule } from '@ng-select/ng-select'; + +@NgModule({ + declarations: [ + AppComponent, + LoginComponent, + CourseComponent, + CourseDetailComponent + ], + imports: [ + BrowserModule, + AppRoutingModule, + HttpClientModule, + FormsModule, + ReactiveFormsModule, + NgSelectModule, + NgMultiSelectDropDownModule.forRoot() + ], + providers: [], + schemas: [CUSTOM_ELEMENTS_SCHEMA], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/desafio-fullstack-front/src/app/course-detail/course-detail.component.css b/desafio-fullstack-front/src/app/course-detail/course-detail.component.css new file mode 100644 index 000000000..a296afa49 --- /dev/null +++ b/desafio-fullstack-front/src/app/course-detail/course-detail.component.css @@ -0,0 +1,158 @@ +.main { + display: flex; + justify-content: center !important; + align-items: center !important; + width: 100% !important; +} + +.grid-container { + display: grid; + grid-template-columns: 10% 80% 10%; +} + +.grid-list-courses { + display: grid; + grid-template-columns: 50% 50%; +} + +.grid-second-line { + display: grid; + grid-template-columns: 50% 50%; +} + +.grid-third-line { + display: grid; + grid-template-columns: 50% 50%; +} + +.ng-select { + border: 1px black solid; + border-radius: none; +} + +.button-container { + padding-top: 10px; + padding-bottom: 10px; + text-align: center; +} + +.button-container button { + height: 40px; + width: 150px; + background-color: black; + color: #fff; +} + +input { + width: 100%; + height: 32px; + background-color: #fff !important; + box-shadow: none !important; +} + +.grid-item { + text-align: center; +} + +.left { + padding-right: 5px !important; +} + +.right { + padding-left: 5px !important; +} + +.container-center { + width: 100% !important; +} + +.container-content { + padding: 40px; +} + +.teachers { + text-align: left; + margin: 0; +} + +.classrooms { + margin: 0; +} + +button { + background: none; + border: none; +} + +.schedule { + margin: 0; +} + +.container-header { + text-align: center; + background-color: #bdbdbd; + width: 100% !important; +} + +.container-header h1 { + text-align: center; +} + +.grid-item { + margin: 10px; +} + +.margin-container-select-left { + margin-right: 3px; +} + +.margin-container-select-right { + margin-left: 0px; +} + +.no-margin { + margin: 0px !important; +} + +.input-left { + margin-right: 2px; +} + +.input-right { + margin-left: 2px; +} + +@media only screen and (max-width: 800px) { + .grid-container { + display: grid; + grid-template-columns: 100%; + } + + .grid-list-courses { + display: grid; + grid-template-columns: 100%; + } + + .grid-second-line { + display: grid; + grid-template-columns: 100%; + } + + .grid-third-line { + display: grid; + grid-template-columns: 46% 46%; + margin-left: 5px; + } + + .left { + margin-left: 5px !important; + } + + .input-left { + margin-right: 0px; + } + + .input-right { + margin-left: 0px; + } +} diff --git a/desafio-fullstack-front/src/app/course-detail/course-detail.component.html b/desafio-fullstack-front/src/app/course-detail/course-detail.component.html new file mode 100644 index 000000000..9a8b2596a --- /dev/null +++ b/desafio-fullstack-front/src/app/course-detail/course-detail.component.html @@ -0,0 +1,44 @@ +
+
+
+
+
+
+

Detalhe do curso

+
+
+
+
+
+
+
+ +
+
+ + +
+
+
+
+ + + +
+
+
+ +
+
+ +
+
+
+
+ +
+
+
+
\ No newline at end of file diff --git a/desafio-fullstack-front/src/app/course-detail/course-detail.component.ts b/desafio-fullstack-front/src/app/course-detail/course-detail.component.ts new file mode 100644 index 000000000..7356f1b47 --- /dev/null +++ b/desafio-fullstack-front/src/app/course-detail/course-detail.component.ts @@ -0,0 +1,95 @@ +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { Teacher } from '../models/teacher.model'; +import { ClassroomService } from '../services/classroom.service'; +import { TeacherService } from '../services/teacher.service'; + +import Swal from 'sweetalert2'; +import { CourseService } from '../services/course.service'; +import { ActivatedRoute, Router } from '@angular/router'; +import { Classroom } from '../models/classroom.model'; + +@Component({ + selector: 'app-course-detail', + templateUrl: './course-detail.component.html', + styleUrls: ['./course-detail.component.css'] +}) +export class CourseDetailComponent implements OnInit { + + teachers: Teacher[]; + classrooms: Classroom[] + + formGroup: FormGroup; + + loading: boolean = false; + + id = null; + + constructor(private teacherService: TeacherService, private classroomService: ClassroomService, + private fb: FormBuilder, private courseService: CourseService, private router: Router, private activatedRoute: ActivatedRoute) { + this.activatedRoute.paramMap.subscribe(params => { + this.id = params.get('id'); + }); + } + + ngOnInit() { + this.createFormGroup() + this.loadData() + } + + createFormGroup() { + this.formGroup = this.fb.group({ + id: [''], + name: ['', Validators.required], + startTime: ['', Validators.required], + endTime: ['', Validators.required], + teachers: [[], Validators.required], + classrooms: [[], Validators.required] + }) + } + + async loadData() { + + if (this.id) { + const course = await this.courseService.getById(this.id); + this.formGroup.setValue(course) + } + + this.teachers = await this.teacherService.getAll(); + this.classrooms = await this.classroomService.getAll(); + + } + + async save() { + try { + if (!this.formGroup.valid) { + return Swal.fire('Erro', 'É necessário preencher todos os campos para continuar.', 'error'); + } + + this.loading = true; + + const object = { + name: this.formGroup.get('name').value, + startTime: this.formGroup.get('startTime').value, + endTime: this.formGroup.get('endTime').value, + teachers: this.formGroup.get('teachers').value.map((x) => { return { id: x.id } }), + classrooms: this.formGroup.get('classrooms').value.map((x) => { return { id: x.id } }) + } + + this.id ? await this.courseService.update(this.id, object) : await this.courseService.save(object); + + await Swal.fire('Sucesso', `Curso ${this.id ? 'alterado' : 'cadastrado'} com sucesso`, 'success'); + + this.loading = false; + this.router.navigate(['/course']) + } catch (error) { + Swal.fire('Erro', `Ocorreu um erro ao tentar salvar o curso`, 'error'); + } finally { + this.loading = false; + } + + } + + + +} diff --git a/desafio-fullstack-front/src/app/course/course.component.css b/desafio-fullstack-front/src/app/course/course.component.css new file mode 100644 index 000000000..cc07318a3 --- /dev/null +++ b/desafio-fullstack-front/src/app/course/course.component.css @@ -0,0 +1,83 @@ +.main { + display: flex; + justify-content: center !important; + align-items: center !important; + width: 100% !important; +} + +.grid-container { + display: grid; + grid-template-columns: 10% 80% 10%; +} + +.grid-list-courses { + display: grid; + grid-template-columns: 50% 50%; +} + +.grid-content-course { + display: grid; + grid-template-columns: auto auto; +} + +.grid-item { + text-align: center; +} + +.left { + text-align: left !important; +} + +.right { + text-align: right !important; +} + +.grid-container .grid-item img { + margin-top: 14px; +} + +.container-center { + width: 100% !important; +} + +.container-content { + padding: 40px; +} + +.teachers { + text-align: left; + margin: 0; +} + +.classrooms { + margin: 0; +} + +button { + background: none; + border: none; +} + +.schedule { + margin: 0; +} + +.card { + margin: 10px; + padding: 20px; + border: 2px black solid; + border-radius: 5px; +} + +.container-header { + text-align: center; + background-color: #bdbdbd; + width: 100% !important; +} + +.container-header h1 { + text-align: center; +} + +@media only screen and (max-width: 600px) { +} diff --git a/desafio-fullstack-front/src/app/course/course.component.html b/desafio-fullstack-front/src/app/course/course.component.html new file mode 100644 index 000000000..6c2ac52fb --- /dev/null +++ b/desafio-fullstack-front/src/app/course/course.component.html @@ -0,0 +1,56 @@ +
+
+
+
+
+
+

Cursos

+
+
+ +
+
+
+
+
+
+
+
+
+ {{course.name}} +
+
+ +
+
+
+

+ + Prof. {{teacher.name}} + {{ i == (course.teachers.length - 1) ? '' : course.teachers.length > 1 && course.teachers.length < 3 + ? ' e ' : course.teachers.length> 2 ? ', ' : '' }} + +

+
+
+

+ + {{classroom.name}} + {{ i == (course.classrooms.length - 1) ? '' : course.classrooms.length > 1 && + course.classrooms.length < 3 ? ' e ' : course.classrooms.length> 2 ? ', ' : '' }} + +

+
+
+

+ {{ course.startTime }} às {{ course.endTime }} +

+
+
+
+
+
+
+
+
\ No newline at end of file diff --git a/desafio-fullstack-front/src/app/course/course.component.ts b/desafio-fullstack-front/src/app/course/course.component.ts new file mode 100644 index 000000000..35a3a311d --- /dev/null +++ b/desafio-fullstack-front/src/app/course/course.component.ts @@ -0,0 +1,36 @@ +import { Component, OnInit } from '@angular/core'; +import { CourseService } from '../services/course.service'; +import Swal from 'sweetalert2'; +import { Course } from '../models/course.model'; + +@Component({ + selector: 'app-course', + templateUrl: './course.component.html', + styleUrls: ['./course.component.css'] +}) +export class CourseComponent implements OnInit { + + courses: Course[] + + constructor(private courseService: CourseService) { } + + ngOnInit() { + this.loadData() + } + + async loadData() { + const courses: any = await this.courseService.getAll(); + this.courses = courses + } + + async removeCourse(id) { + try { + await this.courseService.delete(id); + await Swal.fire('Sucesso', `Curso removido com sucesso`, 'success'); + this.loadData(); + } catch (error) { + Swal.fire('Erro', `Ocorreu um erro ao remover o curso`, 'error'); + } + } + +} diff --git a/desafio-fullstack-front/src/app/login/login.component.css b/desafio-fullstack-front/src/app/login/login.component.css new file mode 100644 index 000000000..4ffbf538f --- /dev/null +++ b/desafio-fullstack-front/src/app/login/login.component.css @@ -0,0 +1,49 @@ +.main { + display: flex; + justify-content: center !important; + align-items: center !important; +} + +.login { + text-align: center; + width: 400px; +} + +.login h1 { + text-align: center; +} + +.input-container { + padding-top: 10px; + padding-bottom: 10px; +} + +.input-container input { + width: 400px; + height: 30px; + background-color: #fff !important; + box-shadow: none !important; +} + +.button-container { + padding-top: 10px; + padding-bottom: 10px; +} + +.button-container button { + height: 40px; + width: 150px; + background-color: black; + color: #fff; +} + +@media only screen and (max-width: 600px) { + .login { + text-align: center; + width: 250px; + } + + .input-container input { + width: 250px; + } +} diff --git a/desafio-fullstack-front/src/app/login/login.component.html b/desafio-fullstack-front/src/app/login/login.component.html new file mode 100644 index 000000000..5dc795fee --- /dev/null +++ b/desafio-fullstack-front/src/app/login/login.component.html @@ -0,0 +1,18 @@ +
+
+ +
+
\ No newline at end of file diff --git a/desafio-fullstack-front/src/app/login/login.component.ts b/desafio-fullstack-front/src/app/login/login.component.ts new file mode 100644 index 000000000..f56a8db41 --- /dev/null +++ b/desafio-fullstack-front/src/app/login/login.component.ts @@ -0,0 +1,61 @@ +import { Component, OnInit } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { AuthService } from '../services/auth.service'; +import Swal from 'sweetalert2'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-login', + templateUrl: './login.component.html', + styleUrls: ['./login.component.css'] +}) +export class LoginComponent implements OnInit { + + formGroup: FormGroup; + loading: boolean = false; + + constructor(private fb: FormBuilder, private authService: AuthService, private router: Router) { } + + ngOnInit() { + this.createFormGroup() + } + + createFormGroup() { + this.formGroup = this.fb.group({ + email: ['', [Validators.required, Validators.email]], + password: ['', Validators.required] + }) + } + + async login() { + try { + + if (!this.formGroup.valid) { + return Swal.fire('Erro', 'É necessário informar email e senha para continuar.', 'error'); + } + + this.loading = true; + + const data = { + email: this.formGroup.get('email').value, + password: this.formGroup.get('password').value + } + + await this.authService.login(data); + + this.router.navigate(['/course']) + } catch (error) { + + let msg = 'Ocorreu um erro ao realizar o login, tente novamente.'; + + if (error.status === 403) { + msg = 'Email e/ou senha inválido(s)'; + } + + Swal.fire('Erro', msg, 'error'); + } finally { + this.loading = false; + } + } + +} diff --git a/desafio-fullstack-front/src/app/models/classroom.model.ts b/desafio-fullstack-front/src/app/models/classroom.model.ts new file mode 100644 index 000000000..2501544bb --- /dev/null +++ b/desafio-fullstack-front/src/app/models/classroom.model.ts @@ -0,0 +1,6 @@ +export interface Classroom { + + id: number; + name: string; + +} \ No newline at end of file diff --git a/desafio-fullstack-front/src/app/models/course.model.ts b/desafio-fullstack-front/src/app/models/course.model.ts new file mode 100644 index 000000000..dbf9fd347 --- /dev/null +++ b/desafio-fullstack-front/src/app/models/course.model.ts @@ -0,0 +1,13 @@ +import { Classroom } from "./classroom.model"; +import { Teacher } from "./teacher.model"; + +export interface Course { + + id: number; + name: string; + startTime: string; + endTime: string; + teachers: Teacher[]; + classrooms: Classroom[]; + +} \ No newline at end of file diff --git a/desafio-fullstack-front/src/app/models/teacher.model.ts b/desafio-fullstack-front/src/app/models/teacher.model.ts new file mode 100644 index 000000000..3689714cc --- /dev/null +++ b/desafio-fullstack-front/src/app/models/teacher.model.ts @@ -0,0 +1,6 @@ +export interface Teacher { + + id: number; + name: string; + +} \ No newline at end of file diff --git a/desafio-fullstack-front/src/app/services/auth.service.ts b/desafio-fullstack-front/src/app/services/auth.service.ts new file mode 100644 index 000000000..e9c0b1040 --- /dev/null +++ b/desafio-fullstack-front/src/app/services/auth.service.ts @@ -0,0 +1,15 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; + +@Injectable({ + providedIn: 'root' +}) +export class AuthService { + + constructor(private http: HttpClient) { } + + login(data) { + return this.http.post(`${environment.baseUrl}/auth/login`, { ...data }).toPromise() + } +} diff --git a/desafio-fullstack-front/src/app/services/classroom.service.ts b/desafio-fullstack-front/src/app/services/classroom.service.ts new file mode 100644 index 000000000..69f1ce6b4 --- /dev/null +++ b/desafio-fullstack-front/src/app/services/classroom.service.ts @@ -0,0 +1,17 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import { Classroom } from '../models/classroom.model'; + +@Injectable({ + providedIn: 'root' +}) +export class ClassroomService { + + constructor(private http: HttpClient) { } + + getAll(): Promise { + return this.http.get(`${environment.baseUrl}/classroom`).toPromise() + } + +} diff --git a/desafio-fullstack-front/src/app/services/course.service.ts b/desafio-fullstack-front/src/app/services/course.service.ts new file mode 100644 index 000000000..1aa4dd98a --- /dev/null +++ b/desafio-fullstack-front/src/app/services/course.service.ts @@ -0,0 +1,32 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import { Course } from '../models/course.model'; + +@Injectable({ + providedIn: 'root' +}) +export class CourseService { + + constructor(private http: HttpClient) { } + + getAll() { + return this.http.get(`${environment.baseUrl}/course`).toPromise() + } + + getById(id) { + return this.http.get(`${environment.baseUrl}/course/${id}`).toPromise() + } + + update(id, course) { + return this.http.put(`${environment.baseUrl}/course/${id}`, { ...course }).toPromise(); + } + + save(course) { + return this.http.post(`${environment.baseUrl}/course`, { ...course }).toPromise() + } + + delete(id) { + return this.http.delete(`${environment.baseUrl}/course/${id}`).toPromise() + } +} diff --git a/desafio-fullstack-front/src/app/services/teacher.service.ts b/desafio-fullstack-front/src/app/services/teacher.service.ts new file mode 100644 index 000000000..773a4b4c6 --- /dev/null +++ b/desafio-fullstack-front/src/app/services/teacher.service.ts @@ -0,0 +1,17 @@ +import { HttpClient } from '@angular/common/http'; +import { Injectable } from '@angular/core'; +import { environment } from 'src/environments/environment'; +import { Teacher } from '../models/teacher.model'; + +@Injectable({ + providedIn: 'root' +}) +export class TeacherService { + + constructor(private http: HttpClient) { } + + getAll(): Promise { + return this.http.get(`${environment.baseUrl}/teacher`).toPromise() + } + +} diff --git a/desafio-fullstack-front/src/assets/.gitkeep b/desafio-fullstack-front/src/assets/.gitkeep new file mode 100644 index 000000000..e69de29bb diff --git a/desafio-fullstack-front/src/assets/images/add-outline.svg b/desafio-fullstack-front/src/assets/images/add-outline.svg new file mode 100644 index 000000000..e66e1656e --- /dev/null +++ b/desafio-fullstack-front/src/assets/images/add-outline.svg @@ -0,0 +1 @@ +Add \ No newline at end of file diff --git a/desafio-fullstack-front/src/assets/images/trash-outline.svg b/desafio-fullstack-front/src/assets/images/trash-outline.svg new file mode 100644 index 000000000..4920b56a6 --- /dev/null +++ b/desafio-fullstack-front/src/assets/images/trash-outline.svg @@ -0,0 +1 @@ +Trash \ No newline at end of file diff --git a/desafio-fullstack-front/src/browserslist b/desafio-fullstack-front/src/browserslist new file mode 100644 index 000000000..8e09ab492 --- /dev/null +++ b/desafio-fullstack-front/src/browserslist @@ -0,0 +1,9 @@ +# This file is currently used by autoprefixer to adjust CSS to support the below specified browsers +# For additional information regarding the format and rule options, please see: +# https://github.com/browserslist/browserslist#queries +# For IE 9-11 support, please uncomment the last line of the file and adjust as needed +> 0.5% +last 2 versions +Firefox ESR +not dead +# IE 9-11 \ No newline at end of file diff --git a/desafio-fullstack-front/src/environments/environment.prod.ts b/desafio-fullstack-front/src/environments/environment.prod.ts new file mode 100644 index 000000000..3612073bc --- /dev/null +++ b/desafio-fullstack-front/src/environments/environment.prod.ts @@ -0,0 +1,3 @@ +export const environment = { + production: true +}; diff --git a/desafio-fullstack-front/src/environments/environment.ts b/desafio-fullstack-front/src/environments/environment.ts new file mode 100644 index 000000000..3a51f5b53 --- /dev/null +++ b/desafio-fullstack-front/src/environments/environment.ts @@ -0,0 +1,17 @@ +// This file can be replaced during build by using the `fileReplacements` array. +// `ng build ---prod` replaces `environment.ts` with `environment.prod.ts`. +// The list of file replacements can be found in `angular.json`. + +export const environment = { + production: false, + + baseUrl: 'http://192.168.0.107:3000' +}; + +/* + * In development mode, to ignore zone related error stack frames such as + * `zone.run`, `zoneDelegate.invokeTask` for easier debugging, you can + * import the following file, but please comment it out in production mode + * because it will have performance impact when throw error + */ +// import 'zone.js/dist/zone-error'; // Included with Angular CLI. diff --git a/desafio-fullstack-front/src/favicon.ico b/desafio-fullstack-front/src/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..8081c7ceaf2be08bf59010158c586170d9d2d517 GIT binary patch literal 5430 zcmc(je{54#6vvCoAI3i*G5%$U7!sA3wtMZ$fH6V9C`=eXGJb@R1%(I_{vnZtpD{6n z5Pl{DmxzBDbrB>}`90e12m8T*36WoeDLA&SD_hw{H^wM!cl_RWcVA!I+x87ee975; z@4kD^=bYPn&pmG@(+JZ`rqQEKxW<}RzhW}I!|ulN=fmjVi@x{p$cC`)5$a!)X&U+blKNvN5tg=uLvuLnuqRM;Yc*swiexsoh#XPNu{9F#c`G zQLe{yWA(Y6(;>y|-efAy11k<09(@Oo1B2@0`PtZSkqK&${ zgEY}`W@t{%?9u5rF?}Y7OL{338l*JY#P!%MVQY@oqnItpZ}?s z!r?*kwuR{A@jg2Chlf0^{q*>8n5Ir~YWf*wmsh7B5&EpHfd5@xVaj&gqsdui^spyL zB|kUoblGoO7G(MuKTfa9?pGH0@QP^b#!lM1yHWLh*2iq#`C1TdrnO-d#?Oh@XV2HK zKA{`eo{--^K&MW66Lgsktfvn#cCAc*(}qsfhrvOjMGLE?`dHVipu1J3Kgr%g?cNa8 z)pkmC8DGH~fG+dlrp(5^-QBeEvkOvv#q7MBVLtm2oD^$lJZx--_=K&Ttd=-krx(Bb zcEoKJda@S!%%@`P-##$>*u%T*mh+QjV@)Qa=Mk1?#zLk+M4tIt%}wagT{5J%!tXAE;r{@=bb%nNVxvI+C+$t?!VJ@0d@HIyMJTI{vEw0Ul ze(ha!e&qANbTL1ZneNl45t=#Ot??C0MHjjgY8%*mGisN|S6%g3;Hlx#fMNcL<87MW zZ>6moo1YD?P!fJ#Jb(4)_cc50X5n0KoDYfdPoL^iV`k&o{LPyaoqMqk92wVM#_O0l z09$(A-D+gVIlq4TA&{1T@BsUH`Bm=r#l$Z51J-U&F32+hfUP-iLo=jg7Xmy+WLq6_tWv&`wDlz#`&)Jp~iQf zZP)tu>}pIIJKuw+$&t}GQuqMd%Z>0?t%&BM&Wo^4P^Y z)c6h^f2R>X8*}q|bblAF?@;%?2>$y+cMQbN{X$)^R>vtNq_5AB|0N5U*d^T?X9{xQnJYeU{ zoZL#obI;~Pp95f1`%X3D$Mh*4^?O?IT~7HqlWguezmg?Ybq|7>qQ(@pPHbE9V?f|( z+0xo!#m@Np9PljsyxBY-UA*{U*la#8Wz2sO|48_-5t8%_!n?S$zlGe+NA%?vmxjS- zHE5O3ZarU=X}$7>;Okp(UWXJxI%G_J-@IH;%5#Rt$(WUX?6*Ux!IRd$dLP6+SmPn= z8zjm4jGjN772R{FGkXwcNv8GBcZI#@Y2m{RNF_w8(Z%^A*!bS*!}s6sh*NnURytky humW;*g7R+&|Ledvc- + + + + DesafioFullstackFront + + + + + + + + + diff --git a/desafio-fullstack-front/src/karma.conf.js b/desafio-fullstack-front/src/karma.conf.js new file mode 100644 index 000000000..b6e00421c --- /dev/null +++ b/desafio-fullstack-front/src/karma.conf.js @@ -0,0 +1,31 @@ +// 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'), + reports: ['html', 'lcovonly'], + fixWebpackSourcePaths: true + }, + reporters: ['progress', 'kjhtml'], + port: 9876, + colors: true, + logLevel: config.LOG_INFO, + autoWatch: true, + browsers: ['Chrome'], + singleRun: false + }); +}; \ No newline at end of file diff --git a/desafio-fullstack-front/src/main.ts b/desafio-fullstack-front/src/main.ts new file mode 100644 index 000000000..91ec6da5f --- /dev/null +++ b/desafio-fullstack-front/src/main.ts @@ -0,0 +1,12 @@ +import { enableProdMode } from '@angular/core'; +import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; + +import { AppModule } from './app/app.module'; +import { environment } from './environments/environment'; + +if (environment.production) { + enableProdMode(); +} + +platformBrowserDynamic().bootstrapModule(AppModule) + .catch(err => console.log(err)); diff --git a/desafio-fullstack-front/src/polyfills.ts b/desafio-fullstack-front/src/polyfills.ts new file mode 100644 index 000000000..d310405a6 --- /dev/null +++ b/desafio-fullstack-front/src/polyfills.ts @@ -0,0 +1,80 @@ +/** + * This file includes polyfills needed by Angular and is loaded before the app. + * You can add your own extra polyfills to this file. + * + * This file is divided into 2 sections: + * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. + * 2. Application imports. Files imported after ZoneJS that should be loaded before your main + * file. + * + * The current setup is for so-called "evergreen" browsers; the last versions of browsers that + * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), + * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. + * + * Learn more in https://angular.io/docs/ts/latest/guide/browser-support.html + */ + +/*************************************************************************************************** + * BROWSER POLYFILLS + */ + +/** IE9, IE10 and IE11 requires all of the following polyfills. **/ +// import 'core-js/es6/symbol'; +// import 'core-js/es6/object'; +// import 'core-js/es6/function'; +// import 'core-js/es6/parse-int'; +// import 'core-js/es6/parse-float'; +// import 'core-js/es6/number'; +// import 'core-js/es6/math'; +// import 'core-js/es6/string'; +// import 'core-js/es6/date'; +// import 'core-js/es6/array'; +// import 'core-js/es6/regexp'; +// import 'core-js/es6/map'; +// import 'core-js/es6/weak-map'; +// import 'core-js/es6/set'; + +/** IE10 and IE11 requires the following for NgClass support on SVG elements */ +// import 'classlist.js'; // Run `npm install --save classlist.js`. + +/** IE10 and IE11 requires the following for the Reflect API. */ +// import 'core-js/es6/reflect'; + + +/** Evergreen browsers require these. **/ +// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. +import 'core-js/es7/reflect'; + + +/** + * Web Animations `@angular/platform-browser/animations` + * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. + * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). + **/ +// import 'web-animations-js'; // Run `npm install --save web-animations-js`. + +/** + * By default, zone.js will patch all possible macroTask and DomEvents + * user can disable parts of macroTask/DomEvents patch by setting following flags + */ + + // (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame + // (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick + // (window as any).__zone_symbol__BLACK_LISTED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames + + /* + * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js + * with the following flag, it will bypass `zone.js` patch for IE/Edge + */ +// (window as any).__Zone_enable_cross_context_check = true; + +/*************************************************************************************************** + * Zone JS is required by default for Angular itself. + */ +import 'zone.js/dist/zone'; // Included with Angular CLI. + + + +/*************************************************************************************************** + * APPLICATION IMPORTS + */ diff --git a/desafio-fullstack-front/src/styles.css b/desafio-fullstack-front/src/styles.css new file mode 100644 index 000000000..421e573c4 --- /dev/null +++ b/desafio-fullstack-front/src/styles.css @@ -0,0 +1,2 @@ +/* You can add global styles to this file, and also import other style files */ +@import "~@ng-select/ng-select/themes/default.theme.css"; \ No newline at end of file diff --git a/desafio-fullstack-front/src/test.ts b/desafio-fullstack-front/src/test.ts new file mode 100644 index 000000000..16317897b --- /dev/null +++ b/desafio-fullstack-front/src/test.ts @@ -0,0 +1,20 @@ +// This file is required by karma.conf.js and loads recursively all the .spec and framework files + +import 'zone.js/dist/zone-testing'; +import { getTestBed } from '@angular/core/testing'; +import { + BrowserDynamicTestingModule, + platformBrowserDynamicTesting +} from '@angular/platform-browser-dynamic/testing'; + +declare const require: any; + +// First, initialize the Angular testing environment. +getTestBed().initTestEnvironment( + BrowserDynamicTestingModule, + platformBrowserDynamicTesting() +); +// Then we find all the tests. +const context = require.context('./', true, /\.spec\.ts$/); +// And load the modules. +context.keys().map(context); diff --git a/desafio-fullstack-front/src/tsconfig.app.json b/desafio-fullstack-front/src/tsconfig.app.json new file mode 100644 index 000000000..8ea061ea1 --- /dev/null +++ b/desafio-fullstack-front/src/tsconfig.app.json @@ -0,0 +1,11 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/app", + "types": [] + }, + "exclude": [ + "src/test.ts", + "**/*.spec.ts" + ] +} diff --git a/desafio-fullstack-front/src/tsconfig.spec.json b/desafio-fullstack-front/src/tsconfig.spec.json new file mode 100644 index 000000000..de7733630 --- /dev/null +++ b/desafio-fullstack-front/src/tsconfig.spec.json @@ -0,0 +1,18 @@ +{ + "extends": "../tsconfig.json", + "compilerOptions": { + "outDir": "../out-tsc/spec", + "types": [ + "jasmine", + "node" + ] + }, + "files": [ + "test.ts", + "polyfills.ts" + ], + "include": [ + "**/*.spec.ts", + "**/*.d.ts" + ] +} diff --git a/desafio-fullstack-front/src/tslint.json b/desafio-fullstack-front/src/tslint.json new file mode 100644 index 000000000..52e2c1a5a --- /dev/null +++ b/desafio-fullstack-front/src/tslint.json @@ -0,0 +1,17 @@ +{ + "extends": "../tslint.json", + "rules": { + "directive-selector": [ + true, + "attribute", + "app", + "camelCase" + ], + "component-selector": [ + true, + "element", + "app", + "kebab-case" + ] + } +} diff --git a/desafio-fullstack-front/tsconfig.json b/desafio-fullstack-front/tsconfig.json new file mode 100644 index 000000000..916247e4c --- /dev/null +++ b/desafio-fullstack-front/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compileOnSave": false, + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist/out-tsc", + "sourceMap": true, + "declaration": false, + "module": "es2015", + "moduleResolution": "node", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "target": "es5", + "typeRoots": [ + "node_modules/@types" + ], + "lib": [ + "es2017", + "dom" + ] + } +} diff --git a/desafio-fullstack-front/tslint.json b/desafio-fullstack-front/tslint.json new file mode 100644 index 000000000..3ea984c77 --- /dev/null +++ b/desafio-fullstack-front/tslint.json @@ -0,0 +1,130 @@ +{ + "rulesDirectory": [ + "node_modules/codelyzer" + ], + "rules": { + "arrow-return-shorthand": true, + "callable-types": true, + "class-name": true, + "comment-format": [ + true, + "check-space" + ], + "curly": true, + "deprecation": { + "severity": "warn" + }, + "eofline": true, + "forin": true, + "import-blacklist": [ + true, + "rxjs/Rx" + ], + "import-spacing": true, + "indent": [ + true, + "spaces" + ], + "interface-over-type-literal": true, + "label-position": true, + "max-line-length": [ + true, + 140 + ], + "member-access": false, + "member-ordering": [ + true, + { + "order": [ + "static-field", + "instance-field", + "static-method", + "instance-method" + ] + } + ], + "no-arg": true, + "no-bitwise": true, + "no-console": [ + true, + "debug", + "info", + "time", + "timeEnd", + "trace" + ], + "no-construct": true, + "no-debugger": true, + "no-duplicate-super": true, + "no-empty": false, + "no-empty-interface": true, + "no-eval": true, + "no-inferrable-types": [ + true, + "ignore-params" + ], + "no-misused-new": true, + "no-non-null-assertion": true, + "no-shadowed-variable": true, + "no-string-literal": false, + "no-string-throw": true, + "no-switch-case-fall-through": true, + "no-trailing-whitespace": true, + "no-unnecessary-initializer": true, + "no-unused-expression": true, + "no-use-before-declare": true, + "no-var-keyword": true, + "object-literal-sort-keys": false, + "one-line": [ + true, + "check-open-brace", + "check-catch", + "check-else", + "check-whitespace" + ], + "prefer-const": true, + "quotemark": [ + true, + "single" + ], + "radix": true, + "semicolon": [ + true, + "always" + ], + "triple-equals": [ + true, + "allow-null-check" + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + } + ], + "unified-signatures": true, + "variable-name": false, + "whitespace": [ + true, + "check-branch", + "check-decl", + "check-operator", + "check-separator", + "check-type" + ], + "no-output-on-prefix": true, + "use-input-property-decorator": true, + "use-output-property-decorator": true, + "use-host-property-decorator": true, + "no-input-rename": true, + "no-output-rename": true, + "use-life-cycle-interface": true, + "use-pipe-transform-interface": true, + "component-class-suffix": true, + "directive-class-suffix": true + } +} From 34e07d7180df272464c3c64b8735e6c31be515af Mon Sep 17 00:00:00 2001 From: Gabriel Masiero Date: Thu, 27 May 2021 16:58:33 -0300 Subject: [PATCH 3/8] commit backend project --- desafio-fullstack-api | 1 - desafio-fullstack-backend/.eslintrc.js | 24 +++++ desafio-fullstack-backend/.gitignore | 39 ++++++++ desafio-fullstack-backend/.prettierrc | 4 + desafio-fullstack-backend/Diagrama ER.png | Bin 0 -> 151421 bytes desafio-fullstack-backend/README.md | 73 +++++++++++++++ desafio-fullstack-backend/create-database.sql | 84 ++++++++++++++++++ desafio-fullstack-backend/nest-cli.json | 4 + desafio-fullstack-backend/package.json | 77 ++++++++++++++++ .../src/app.controller.spec.ts | 22 +++++ .../src/app.controller.ts | 12 +++ desafio-fullstack-backend/src/app.module.ts | 38 ++++++++ desafio-fullstack-backend/src/app.service.ts | 8 ++ .../src/auth/auth.controller.ts | 26 ++++++ .../src/auth/auth.module.ts | 11 +++ .../src/auth/auth.service.ts | 21 +++++ .../src/auth/dto/login.dto.ts | 6 ++ .../src/classroom/classroom.controller.ts | 15 ++++ .../src/classroom/classroom.module.ts | 13 +++ .../src/classroom/classroom.service.ts | 15 ++++ .../src/classroom/dto/classroom.dto.ts | 6 ++ .../src/classroom/entity/classroom.entity.ts | 16 ++++ .../src/course/course.controller.ts | 43 +++++++++ .../src/course/course.module.ts | 12 +++ .../src/course/course.service.ts | 31 +++++++ .../src/course/dto/course.dto.ts | 9 ++ .../src/course/entity/course.entity.ts | 36 ++++++++ desafio-fullstack-backend/src/main.ts | 8 ++ .../src/teacher/dto/teacher.dto.ts | 6 ++ .../src/teacher/entity/teacher.entity.ts | 16 ++++ .../src/teacher/teacher.controller.ts | 15 ++++ .../src/teacher/teacher.module.ts | 12 +++ .../src/teacher/teacher.service.ts | 15 ++++ .../src/user/dto/user.dto.ts | 7 ++ .../src/user/entity/user.entity.ts | 15 ++++ .../src/user/user.controller.ts | 4 + .../src/user/user.module.ts | 13 +++ .../src/user/user.service.ts | 16 ++++ desafio-fullstack-backend/tsconfig.build.json | 4 + desafio-fullstack-backend/tsconfig.json | 15 ++++ 40 files changed, 791 insertions(+), 1 deletion(-) delete mode 160000 desafio-fullstack-api create mode 100644 desafio-fullstack-backend/.eslintrc.js create mode 100644 desafio-fullstack-backend/.gitignore create mode 100644 desafio-fullstack-backend/.prettierrc create mode 100644 desafio-fullstack-backend/Diagrama ER.png create mode 100644 desafio-fullstack-backend/README.md create mode 100644 desafio-fullstack-backend/create-database.sql create mode 100644 desafio-fullstack-backend/nest-cli.json create mode 100644 desafio-fullstack-backend/package.json create mode 100644 desafio-fullstack-backend/src/app.controller.spec.ts create mode 100644 desafio-fullstack-backend/src/app.controller.ts create mode 100644 desafio-fullstack-backend/src/app.module.ts create mode 100644 desafio-fullstack-backend/src/app.service.ts create mode 100644 desafio-fullstack-backend/src/auth/auth.controller.ts create mode 100644 desafio-fullstack-backend/src/auth/auth.module.ts create mode 100644 desafio-fullstack-backend/src/auth/auth.service.ts create mode 100644 desafio-fullstack-backend/src/auth/dto/login.dto.ts create mode 100644 desafio-fullstack-backend/src/classroom/classroom.controller.ts create mode 100644 desafio-fullstack-backend/src/classroom/classroom.module.ts create mode 100644 desafio-fullstack-backend/src/classroom/classroom.service.ts create mode 100644 desafio-fullstack-backend/src/classroom/dto/classroom.dto.ts create mode 100644 desafio-fullstack-backend/src/classroom/entity/classroom.entity.ts create mode 100644 desafio-fullstack-backend/src/course/course.controller.ts create mode 100644 desafio-fullstack-backend/src/course/course.module.ts create mode 100644 desafio-fullstack-backend/src/course/course.service.ts create mode 100644 desafio-fullstack-backend/src/course/dto/course.dto.ts create mode 100644 desafio-fullstack-backend/src/course/entity/course.entity.ts create mode 100644 desafio-fullstack-backend/src/main.ts create mode 100644 desafio-fullstack-backend/src/teacher/dto/teacher.dto.ts create mode 100644 desafio-fullstack-backend/src/teacher/entity/teacher.entity.ts create mode 100644 desafio-fullstack-backend/src/teacher/teacher.controller.ts create mode 100644 desafio-fullstack-backend/src/teacher/teacher.module.ts create mode 100644 desafio-fullstack-backend/src/teacher/teacher.service.ts create mode 100644 desafio-fullstack-backend/src/user/dto/user.dto.ts create mode 100644 desafio-fullstack-backend/src/user/entity/user.entity.ts create mode 100644 desafio-fullstack-backend/src/user/user.controller.ts create mode 100644 desafio-fullstack-backend/src/user/user.module.ts create mode 100644 desafio-fullstack-backend/src/user/user.service.ts create mode 100644 desafio-fullstack-backend/tsconfig.build.json create mode 100644 desafio-fullstack-backend/tsconfig.json diff --git a/desafio-fullstack-api b/desafio-fullstack-api deleted file mode 160000 index 31bff9fa9..000000000 --- a/desafio-fullstack-api +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 31bff9fa9d76309676c059a15479e37acd73c88a diff --git a/desafio-fullstack-backend/.eslintrc.js b/desafio-fullstack-backend/.eslintrc.js new file mode 100644 index 000000000..f6c62bee2 --- /dev/null +++ b/desafio-fullstack-backend/.eslintrc.js @@ -0,0 +1,24 @@ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/recommended', + 'plugin:prettier/recommended', + ], + root: true, + env: { + node: true, + jest: true, + }, + ignorePatterns: ['.eslintrc.js'], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; diff --git a/desafio-fullstack-backend/.gitignore b/desafio-fullstack-backend/.gitignore new file mode 100644 index 000000000..c4f0a9bb6 --- /dev/null +++ b/desafio-fullstack-backend/.gitignore @@ -0,0 +1,39 @@ +# compiled output +/dist +/node_modules + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# OS +.DS_Store + +.env + +package-lock.json +yarn.lock + +# Tests +/coverage +/.nyc_output + +# 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 \ No newline at end of file diff --git a/desafio-fullstack-backend/.prettierrc b/desafio-fullstack-backend/.prettierrc new file mode 100644 index 000000000..dcb72794f --- /dev/null +++ b/desafio-fullstack-backend/.prettierrc @@ -0,0 +1,4 @@ +{ + "singleQuote": true, + "trailingComma": "all" +} \ No newline at end of file diff --git a/desafio-fullstack-backend/Diagrama ER.png b/desafio-fullstack-backend/Diagrama ER.png new file mode 100644 index 0000000000000000000000000000000000000000..c8e41634e0e870eecf625f83de912f13e3b95c36 GIT binary patch literal 151421 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 P!N+ltv;C!oK8OAW!D&~4 literal 0 HcmV?d00001 diff --git a/desafio-fullstack-backend/README.md b/desafio-fullstack-backend/README.md new file mode 100644 index 000000000..9fe8812ff --- /dev/null +++ b/desafio-fullstack-backend/README.md @@ -0,0 +1,73 @@ +

+ Nest Logo +

+ +[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 +[circleci-url]: https://circleci.com/gh/nestjs/nest + +

A progressive Node.js framework for building efficient and scalable server-side applications.

+

+NPM Version +Package License +NPM Downloads +CircleCI +Coverage +Discord +Backers on Open Collective +Sponsors on Open Collective + + Support us + +

+ + +## Description + +[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. + +## Installation + +```bash +$ npm install +``` + +## Running the app + +```bash +# development +$ npm run start + +# watch mode +$ npm run start:dev + +# production mode +$ npm run start:prod +``` + +## Test + +```bash +# unit tests +$ npm run test + +# e2e tests +$ npm run test:e2e + +# test coverage +$ npm run test:cov +``` + +## Support + +Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). + +## Stay in touch + +- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) +- Website - [https://nestjs.com](https://nestjs.com/) +- Twitter - [@nestframework](https://twitter.com/nestframework) + +## License + +Nest is [MIT licensed](LICENSE). diff --git a/desafio-fullstack-backend/create-database.sql b/desafio-fullstack-backend/create-database.sql new file mode 100644 index 000000000..3e23de119 --- /dev/null +++ b/desafio-fullstack-backend/create-database.sql @@ -0,0 +1,84 @@ +BEGIN; + + +CREATE TABLE public.classroom +( + id integer NOT NULL, + name character varying NOT NULL, + PRIMARY KEY (id) +); + +INSERT INTO public.classroom( + id, name) + VALUES (1, 'Sala 402'); + +CREATE TABLE public.course +( + id integer NOT NULL, + name character varying NOT NULL, + "startTime" character varying NOT NULL, + "endTime" character varying NOT NULL, + PRIMARY KEY (id) +); + +CREATE TABLE public.course_classroom +( + "courseId" integer NOT NULL, + "classroomId" integer NOT NULL, + PRIMARY KEY ("courseId", "classroomId") +); + +CREATE TABLE public.course_teacher +( + "courseId" integer NOT NULL, + "teacherId" integer NOT NULL, + PRIMARY KEY ("courseId", "teacherId") +); + +CREATE TABLE public.teacher +( + id integer NOT NULL, + name character varying NOT NULL, + PRIMARY KEY (id) +); + +INSERT INTO public.teacher( + id, name) + VALUES (1, 'Pedro Henrique'); + +CREATE TABLE public."user" +( + id integer NOT NULL, + email character varying NOT NULL, + password character varying NOT NULL, + PRIMARY KEY (id) +); + +INSERT INTO public."user"( + id, email, password) + VALUES (1, 'user@test.com', 'testpass'); + +ALTER TABLE public.course_classroom + ADD FOREIGN KEY ("classroomId") + REFERENCES public.classroom (id) + NOT VALID; + + +ALTER TABLE public.course_classroom + ADD FOREIGN KEY ("courseId") + REFERENCES public.course (id) + NOT VALID; + + +ALTER TABLE public.course_teacher + ADD FOREIGN KEY ("teacherId") + REFERENCES public.teacher (id) + NOT VALID; + + +ALTER TABLE public.course_teacher + ADD FOREIGN KEY ("courseId") + REFERENCES public.course (id) + NOT VALID; + +END; \ No newline at end of file diff --git a/desafio-fullstack-backend/nest-cli.json b/desafio-fullstack-backend/nest-cli.json new file mode 100644 index 000000000..56167b36a --- /dev/null +++ b/desafio-fullstack-backend/nest-cli.json @@ -0,0 +1,4 @@ +{ + "collection": "@nestjs/schematics", + "sourceRoot": "src" +} diff --git a/desafio-fullstack-backend/package.json b/desafio-fullstack-backend/package.json new file mode 100644 index 000000000..f1f4ee09c --- /dev/null +++ b/desafio-fullstack-backend/package.json @@ -0,0 +1,77 @@ +{ + "name": "desafio-fullstack-api", + "version": "0.0.1", + "description": "", + "author": "", + "private": true, + "license": "UNLICENSED", + "scripts": { + "prebuild": "rimraf dist", + "build": "nest build", + "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", + "start": "nest start", + "start:dev": "nest start --watch", + "start:debug": "nest start --debug --watch", + "start:prod": "node dist/main", + "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", + "test": "jest", + "test:watch": "jest --watch", + "test:cov": "jest --coverage", + "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand", + "test:e2e": "jest --config ./test/jest-e2e.json" + }, + "dependencies": { + "@nestjs/common": "^7.6.15", + "@nestjs/config": "^0.6.3", + "@nestjs/core": "^7.6.15", + "@nestjs/mapped-types": "*", + "@nestjs/platform-express": "^7.6.15", + "@nestjs/typeorm": "^7.1.5", + "@types/passport": "^1.0.6", + "dotenv": "^10.0.0", + "pg": "^8.6.0", + "reflect-metadata": "^0.1.13", + "rimraf": "^3.0.2", + "rxjs": "^6.6.6", + "typeorm": "^0.2.32" + }, + "devDependencies": { + "@nestjs/cli": "^7.6.0", + "@nestjs/schematics": "^7.3.0", + "@nestjs/testing": "^7.6.15", + "@types/express": "^4.17.11", + "@types/jest": "^26.0.22", + "@types/node": "^14.14.36", + "@types/supertest": "^2.0.10", + "@typescript-eslint/eslint-plugin": "^4.19.0", + "@typescript-eslint/parser": "^4.19.0", + "eslint": "^7.22.0", + "eslint-config-prettier": "^8.1.0", + "eslint-plugin-prettier": "^3.3.1", + "jest": "^26.6.3", + "prettier": "^2.2.1", + "supertest": "^6.1.3", + "ts-jest": "^26.5.4", + "ts-loader": "^8.0.18", + "ts-node": "^9.1.1", + "tsconfig-paths": "^3.9.0", + "typescript": "^4.2.3" + }, + "jest": { + "moduleFileExtensions": [ + "js", + "json", + "ts" + ], + "rootDir": "src", + "testRegex": ".*\\.spec\\.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": [ + "**/*.(t|j)s" + ], + "coverageDirectory": "../coverage", + "testEnvironment": "node" + } +} diff --git a/desafio-fullstack-backend/src/app.controller.spec.ts b/desafio-fullstack-backend/src/app.controller.spec.ts new file mode 100644 index 000000000..d22f3890a --- /dev/null +++ b/desafio-fullstack-backend/src/app.controller.spec.ts @@ -0,0 +1,22 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; + +describe('AppController', () => { + let appController: AppController; + + beforeEach(async () => { + const app: TestingModule = await Test.createTestingModule({ + controllers: [AppController], + providers: [AppService], + }).compile(); + + appController = app.get(AppController); + }); + + describe('root', () => { + it('should return "Hello World!"', () => { + expect(appController.getHello()).toBe('Hello World!'); + }); + }); +}); diff --git a/desafio-fullstack-backend/src/app.controller.ts b/desafio-fullstack-backend/src/app.controller.ts new file mode 100644 index 000000000..cce879ee6 --- /dev/null +++ b/desafio-fullstack-backend/src/app.controller.ts @@ -0,0 +1,12 @@ +import { Controller, Get } from '@nestjs/common'; +import { AppService } from './app.service'; + +@Controller() +export class AppController { + constructor(private readonly appService: AppService) {} + + @Get() + getHello(): string { + return this.appService.getHello(); + } +} diff --git a/desafio-fullstack-backend/src/app.module.ts b/desafio-fullstack-backend/src/app.module.ts new file mode 100644 index 000000000..893d124a6 --- /dev/null +++ b/desafio-fullstack-backend/src/app.module.ts @@ -0,0 +1,38 @@ +import { Module } from '@nestjs/common'; +import { AppController } from './app.controller'; +import { AppService } from './app.service'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { AuthModule } from './auth/auth.module'; +import { UserModule } from './user/user.module'; +import { UserEntity } from './user/entity/user.entity'; +import { CourseModule } from './course/course.module'; +import { TeacherModule } from './teacher/teacher.module'; +import { TeacherEntity } from './teacher/entity/teacher.entity'; +import { ClassroomModule } from './classroom/classroom.module'; +import { ClassroomEntity } from './classroom/entity/classroom.entity'; +import { CourseEntity } from './course/entity/course.entity'; +import { ConfigModule } from '@nestjs/config'; + +@Module({ + imports: [ + ConfigModule.forRoot(), + TypeOrmModule.forRoot({ + type: 'postgres', + host: process.env.DATABASE_HOST, + port: parseInt(process.env.DATABASE_PORT), + username: process.env.DATABASE_USERNAME, + password: process.env.DATABASE_PASSWORD, + database: process.env.DATABASE_NAME, + synchronize: true, + entities: [UserEntity, TeacherEntity, ClassroomEntity, CourseEntity] + }), + AuthModule, + UserModule, + CourseModule, + TeacherModule, + ClassroomModule, + ], + controllers: [AppController], + providers: [AppService], +}) +export class AppModule { } diff --git a/desafio-fullstack-backend/src/app.service.ts b/desafio-fullstack-backend/src/app.service.ts new file mode 100644 index 000000000..927d7cca0 --- /dev/null +++ b/desafio-fullstack-backend/src/app.service.ts @@ -0,0 +1,8 @@ +import { Injectable } from '@nestjs/common'; + +@Injectable() +export class AppService { + getHello(): string { + return 'Hello World!'; + } +} diff --git a/desafio-fullstack-backend/src/auth/auth.controller.ts b/desafio-fullstack-backend/src/auth/auth.controller.ts new file mode 100644 index 000000000..9af98f9a8 --- /dev/null +++ b/desafio-fullstack-backend/src/auth/auth.controller.ts @@ -0,0 +1,26 @@ +import { Body, Controller, HttpStatus, Post, Res } from '@nestjs/common'; + +import { AuthService } from './auth.service'; +import { LoginDto } from './dto/login.dto'; + +@Controller('auth') +export class AuthController { + + constructor(private authService: AuthService) { } + + @Post('/login') + async login(@Body() loginDto: LoginDto, @Res() response) { + + try { + const result = await this.authService.login(loginDto) + if (!result) { + return response.status(HttpStatus.FORBIDDEN).send('invalid credentials') + } + + return response.status(HttpStatus.OK).send(result); + } catch (error) { + return response.status(HttpStatus.INTERNAL_SERVER_ERROR).send(error); + } + } + +} diff --git a/desafio-fullstack-backend/src/auth/auth.module.ts b/desafio-fullstack-backend/src/auth/auth.module.ts new file mode 100644 index 000000000..33596fad7 --- /dev/null +++ b/desafio-fullstack-backend/src/auth/auth.module.ts @@ -0,0 +1,11 @@ +import { Module } from '@nestjs/common'; +import { AuthService } from './auth.service'; +import { AuthController } from './auth.controller'; +import { UserModule } from 'src/user/user.module'; + +@Module({ + imports: [UserModule], + providers: [AuthService], + controllers: [AuthController] +}) +export class AuthModule {} diff --git a/desafio-fullstack-backend/src/auth/auth.service.ts b/desafio-fullstack-backend/src/auth/auth.service.ts new file mode 100644 index 000000000..c46a34ddc --- /dev/null +++ b/desafio-fullstack-backend/src/auth/auth.service.ts @@ -0,0 +1,21 @@ +import { Injectable } from '@nestjs/common'; +import { UserDto } from 'src/user/dto/user.dto'; +import { UserService } from 'src/user/user.service'; + +import { LoginDto } from './dto/login.dto'; + +@Injectable() +export class AuthService { + + constructor(private userService: UserService) { } + + async login(loginDto: LoginDto): Promise { + const user = await this.userService.findOne(loginDto.email); + if (user && user.password === loginDto.password) { + delete user.password; + return user; + } + return null; + } + +} diff --git a/desafio-fullstack-backend/src/auth/dto/login.dto.ts b/desafio-fullstack-backend/src/auth/dto/login.dto.ts new file mode 100644 index 000000000..4616492fd --- /dev/null +++ b/desafio-fullstack-backend/src/auth/dto/login.dto.ts @@ -0,0 +1,6 @@ +export class LoginDto { + + email: string; + password: string; + +} diff --git a/desafio-fullstack-backend/src/classroom/classroom.controller.ts b/desafio-fullstack-backend/src/classroom/classroom.controller.ts new file mode 100644 index 000000000..e89e231c4 --- /dev/null +++ b/desafio-fullstack-backend/src/classroom/classroom.controller.ts @@ -0,0 +1,15 @@ +import { Controller, Get } from '@nestjs/common'; +import { ClassroomService } from './classroom.service'; +import { ClassroomDto } from './dto/classroom.dto'; + +@Controller('classroom') +export class ClassroomController { + + constructor(private classroomService: ClassroomService) { } + + @Get('/') + findAll(): Promise { + return this.classroomService.findAll(); + } + +} diff --git a/desafio-fullstack-backend/src/classroom/classroom.module.ts b/desafio-fullstack-backend/src/classroom/classroom.module.ts new file mode 100644 index 000000000..d68297ea9 --- /dev/null +++ b/desafio-fullstack-backend/src/classroom/classroom.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { ClassroomService } from './classroom.service'; +import { ClassroomController } from './classroom.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { ClassroomEntity } from './entity/classroom.entity'; + +@Module({ + imports: [TypeOrmModule.forFeature([ClassroomEntity])], + exports: [ClassroomService], + providers: [ClassroomService], + controllers: [ClassroomController] +}) +export class ClassroomModule {} diff --git a/desafio-fullstack-backend/src/classroom/classroom.service.ts b/desafio-fullstack-backend/src/classroom/classroom.service.ts new file mode 100644 index 000000000..880ec9b34 --- /dev/null +++ b/desafio-fullstack-backend/src/classroom/classroom.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { ClassroomEntity } from './entity/classroom.entity'; + +@Injectable() +export class ClassroomService { + + constructor(@InjectRepository(ClassroomEntity) private classroomRepository: Repository) { } + + findAll(): Promise { + return this.classroomRepository.find() + } + +} diff --git a/desafio-fullstack-backend/src/classroom/dto/classroom.dto.ts b/desafio-fullstack-backend/src/classroom/dto/classroom.dto.ts new file mode 100644 index 000000000..ad0fd20c8 --- /dev/null +++ b/desafio-fullstack-backend/src/classroom/dto/classroom.dto.ts @@ -0,0 +1,6 @@ +export class ClassroomDto { + + id: number; + name: string; + +} diff --git a/desafio-fullstack-backend/src/classroom/entity/classroom.entity.ts b/desafio-fullstack-backend/src/classroom/entity/classroom.entity.ts new file mode 100644 index 000000000..7a139b00d --- /dev/null +++ b/desafio-fullstack-backend/src/classroom/entity/classroom.entity.ts @@ -0,0 +1,16 @@ +import { CourseEntity } from "src/course/entity/course.entity"; +import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from "typeorm"; + +@Entity('classroom') +export class ClassroomEntity { + + @PrimaryGeneratedColumn() + id: number; + + @Column({ nullable: false }) + name: string; + + @ManyToMany(() => CourseEntity, course => course.classrooms) + courses: CourseEntity[]; + +} diff --git a/desafio-fullstack-backend/src/course/course.controller.ts b/desafio-fullstack-backend/src/course/course.controller.ts new file mode 100644 index 000000000..07c8e1341 --- /dev/null +++ b/desafio-fullstack-backend/src/course/course.controller.ts @@ -0,0 +1,43 @@ +import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common'; +import { CourseService } from './course.service'; +import { CourseDto } from './dto/course.dto'; + +@Controller('course') +export class CourseController { + + constructor(private courseService: CourseService) { } + + @Post('/') + async create(@Body() courseDto: CourseDto) { + try { + const result = await this.courseService.create(courseDto); + + console.log('result ', result); + } catch (error) { + console.log('error ', error); + } + + return true; + } + + @Put('/:id') + async update(@Param('id') id, @Body() courseDto: CourseDto) { + return this.courseService.update(id, courseDto); + } + + @Get('/') + findAll() { + return this.courseService.findAll(); + } + + @Get('/:id') + findOne(@Param('id') id) { + return this.courseService.findOne(id); + } + + @Delete('/:id') + delete(@Param('id') id) { + return this.courseService.delete(id); + } + +} diff --git a/desafio-fullstack-backend/src/course/course.module.ts b/desafio-fullstack-backend/src/course/course.module.ts new file mode 100644 index 000000000..53322bae4 --- /dev/null +++ b/desafio-fullstack-backend/src/course/course.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { CourseController } from './course.controller'; +import { CourseService } from './course.service'; +import { CourseEntity } from './entity/course.entity'; + +@Module({ + imports: [TypeOrmModule.forFeature([CourseEntity])], + providers: [CourseService], + controllers: [CourseController] +}) +export class CourseModule { } \ No newline at end of file diff --git a/desafio-fullstack-backend/src/course/course.service.ts b/desafio-fullstack-backend/src/course/course.service.ts new file mode 100644 index 000000000..1be751fc6 --- /dev/null +++ b/desafio-fullstack-backend/src/course/course.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { CourseDto } from './dto/course.dto'; +import { CourseEntity } from './entity/course.entity'; + +@Injectable() +export class CourseService { + + constructor(@InjectRepository(CourseEntity) private courseRepository: Repository) { } + + findAll(): Promise { + return this.courseRepository.find({ relations: ['classrooms', 'teachers'] }) + } + + findOne(id): Promise { + return this.courseRepository.findOne(id, { relations: ['classrooms', 'teachers'] }); + } + + update(id, courseDto: CourseDto) { + return this.courseRepository.save({ id: parseInt(id), ...courseDto }, { reload: true }) + } + + create(courseDto: CourseDto) { + return this.courseRepository.save({ ...courseDto }); + } + + delete(id: number) { + return this.courseRepository.delete(id); + } +} diff --git a/desafio-fullstack-backend/src/course/dto/course.dto.ts b/desafio-fullstack-backend/src/course/dto/course.dto.ts new file mode 100644 index 000000000..404dc7875 --- /dev/null +++ b/desafio-fullstack-backend/src/course/dto/course.dto.ts @@ -0,0 +1,9 @@ +export class CourseDto { + + id: number; + startTime: string; + endTime: string; + teachers: any[]; + classrooms: any[]; + +} diff --git a/desafio-fullstack-backend/src/course/entity/course.entity.ts b/desafio-fullstack-backend/src/course/entity/course.entity.ts new file mode 100644 index 000000000..e987622e9 --- /dev/null +++ b/desafio-fullstack-backend/src/course/entity/course.entity.ts @@ -0,0 +1,36 @@ +import { ClassroomEntity } from "src/classroom/entity/classroom.entity"; +import { TeacherEntity } from "src/teacher/entity/teacher.entity"; +import { Column, Entity, JoinTable, ManyToMany, PrimaryGeneratedColumn } from "typeorm"; + +@Entity('course') +export class CourseEntity { + + @PrimaryGeneratedColumn() + id: number; + + @Column({ nullable: false, unique: true }) + name: string; + + @Column({ nullable: false }) + startTime: string; + + @Column({ nullable: false }) + endTime: string; + + @ManyToMany(() => TeacherEntity, teacher => teacher.courses, { cascade: true }) + @JoinTable({ + name: 'course_teacher', + joinColumn: { name: 'courseId', referencedColumnName: 'id' }, + inverseJoinColumn: { name: 'teacherId', referencedColumnName: 'id' }, + }) + teachers: TeacherEntity[]; + + @ManyToMany(() => ClassroomEntity, classroom => classroom.courses, { cascade: true }) + @JoinTable({ + name: 'course_classroom', + joinColumn: { name: 'courseId', referencedColumnName: 'id' }, + inverseJoinColumn: { name: 'classroomId', referencedColumnName: 'id' }, + }) + classrooms: ClassroomEntity[]; + +} diff --git a/desafio-fullstack-backend/src/main.ts b/desafio-fullstack-backend/src/main.ts new file mode 100644 index 000000000..8d9718c07 --- /dev/null +++ b/desafio-fullstack-backend/src/main.ts @@ -0,0 +1,8 @@ +import { NestFactory } from '@nestjs/core'; +import { AppModule } from './app.module'; + +async function bootstrap() { + const app = await NestFactory.create(AppModule, { cors: true }); + await app.listen(3000); +} +bootstrap(); diff --git a/desafio-fullstack-backend/src/teacher/dto/teacher.dto.ts b/desafio-fullstack-backend/src/teacher/dto/teacher.dto.ts new file mode 100644 index 000000000..877b8a407 --- /dev/null +++ b/desafio-fullstack-backend/src/teacher/dto/teacher.dto.ts @@ -0,0 +1,6 @@ +export class TeacherDto { + + id: number; + name: string; + +} diff --git a/desafio-fullstack-backend/src/teacher/entity/teacher.entity.ts b/desafio-fullstack-backend/src/teacher/entity/teacher.entity.ts new file mode 100644 index 000000000..f0e3880be --- /dev/null +++ b/desafio-fullstack-backend/src/teacher/entity/teacher.entity.ts @@ -0,0 +1,16 @@ +import { CourseEntity } from "src/course/entity/course.entity"; +import { Column, Entity, ManyToMany, PrimaryGeneratedColumn } from "typeorm"; + +@Entity('teacher') +export class TeacherEntity { + + @PrimaryGeneratedColumn() + id: number; + + @Column({ nullable: false }) + name: string; + + @ManyToMany(() => CourseEntity, course => course.teachers) + courses: CourseEntity[]; + +} diff --git a/desafio-fullstack-backend/src/teacher/teacher.controller.ts b/desafio-fullstack-backend/src/teacher/teacher.controller.ts new file mode 100644 index 000000000..e57cb034a --- /dev/null +++ b/desafio-fullstack-backend/src/teacher/teacher.controller.ts @@ -0,0 +1,15 @@ +import { Controller, Get } from '@nestjs/common'; +import { TeacherDto } from './dto/teacher.dto'; +import { TeacherService } from './teacher.service'; + +@Controller('teacher') +export class TeacherController { + + constructor(private teacherService: TeacherService) { } + + @Get('/') + findAll(): Promise { + return this.teacherService.findAll(); + } + +} diff --git a/desafio-fullstack-backend/src/teacher/teacher.module.ts b/desafio-fullstack-backend/src/teacher/teacher.module.ts new file mode 100644 index 000000000..d3780c43b --- /dev/null +++ b/desafio-fullstack-backend/src/teacher/teacher.module.ts @@ -0,0 +1,12 @@ +import { Module } from '@nestjs/common'; +import { TeacherService } from './teacher.service'; +import { TeacherController } from './teacher.controller'; +import { TeacherEntity } from './entity/teacher.entity'; +import { TypeOrmModule } from '@nestjs/typeorm'; + +@Module({ + imports: [TypeOrmModule.forFeature([TeacherEntity])], + providers: [TeacherService], + controllers: [TeacherController] +}) +export class TeacherModule {} diff --git a/desafio-fullstack-backend/src/teacher/teacher.service.ts b/desafio-fullstack-backend/src/teacher/teacher.service.ts new file mode 100644 index 000000000..a2997e6b6 --- /dev/null +++ b/desafio-fullstack-backend/src/teacher/teacher.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { TeacherEntity } from './entity/teacher.entity'; + +@Injectable() +export class TeacherService { + + constructor(@InjectRepository(TeacherEntity) private teacherRepository: Repository) { } + + findAll(): Promise { + return this.teacherRepository.find() + } + +} diff --git a/desafio-fullstack-backend/src/user/dto/user.dto.ts b/desafio-fullstack-backend/src/user/dto/user.dto.ts new file mode 100644 index 000000000..dfe8a8bf4 --- /dev/null +++ b/desafio-fullstack-backend/src/user/dto/user.dto.ts @@ -0,0 +1,7 @@ +export class UserDto { + + id: number; + email: string; + password: string; + +} diff --git a/desafio-fullstack-backend/src/user/entity/user.entity.ts b/desafio-fullstack-backend/src/user/entity/user.entity.ts new file mode 100644 index 000000000..e11295566 --- /dev/null +++ b/desafio-fullstack-backend/src/user/entity/user.entity.ts @@ -0,0 +1,15 @@ +import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; + +@Entity('user') +export class UserEntity { + + @PrimaryGeneratedColumn('increment') + id: number; + + @Column({ nullable: false, unique: true }) + email: string; + + @Column({ nullable: false }) + password: string; + +} diff --git a/desafio-fullstack-backend/src/user/user.controller.ts b/desafio-fullstack-backend/src/user/user.controller.ts new file mode 100644 index 000000000..1d11659ba --- /dev/null +++ b/desafio-fullstack-backend/src/user/user.controller.ts @@ -0,0 +1,4 @@ +import { Controller, Get } from '@nestjs/common'; + +@Controller('user') +export class UserController { } \ No newline at end of file diff --git a/desafio-fullstack-backend/src/user/user.module.ts b/desafio-fullstack-backend/src/user/user.module.ts new file mode 100644 index 000000000..8e2ecfe61 --- /dev/null +++ b/desafio-fullstack-backend/src/user/user.module.ts @@ -0,0 +1,13 @@ +import { Module } from '@nestjs/common'; +import { UserService } from './user.service'; +import { UserController } from './user.controller'; +import { TypeOrmModule } from '@nestjs/typeorm'; +import { UserEntity } from './entity/user.entity'; + +@Module({ + imports: [TypeOrmModule.forFeature([UserEntity])], + providers: [UserService], + exports: [UserService], + controllers: [UserController] +}) +export class UserModule { } \ No newline at end of file diff --git a/desafio-fullstack-backend/src/user/user.service.ts b/desafio-fullstack-backend/src/user/user.service.ts new file mode 100644 index 000000000..3750aa84d --- /dev/null +++ b/desafio-fullstack-backend/src/user/user.service.ts @@ -0,0 +1,16 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Repository } from 'typeorm'; +import { UserDto } from './dto/user.dto'; +import { UserEntity } from './entity/user.entity'; + +@Injectable() +export class UserService { + + constructor(@InjectRepository(UserEntity) private userRepository: Repository) { } + + findOne(email: string): Promise { + return this.userRepository.findOne({ email }) + } + +} diff --git a/desafio-fullstack-backend/tsconfig.build.json b/desafio-fullstack-backend/tsconfig.build.json new file mode 100644 index 000000000..64f86c6bd --- /dev/null +++ b/desafio-fullstack-backend/tsconfig.build.json @@ -0,0 +1,4 @@ +{ + "extends": "./tsconfig.json", + "exclude": ["node_modules", "test", "dist", "**/*spec.ts"] +} diff --git a/desafio-fullstack-backend/tsconfig.json b/desafio-fullstack-backend/tsconfig.json new file mode 100644 index 000000000..bf10a2398 --- /dev/null +++ b/desafio-fullstack-backend/tsconfig.json @@ -0,0 +1,15 @@ +{ + "compilerOptions": { + "module": "commonjs", + "declaration": true, + "removeComments": true, + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "target": "es2017", + "sourceMap": true, + "outDir": "./dist", + "baseUrl": "./", + "incremental": true + } +} From 7cde06a03c0f8d577521504e1a791d29398cdfad Mon Sep 17 00:00:00 2001 From: Gabriel Masiero <34697315+CHIODELLIz@users.noreply.github.com> Date: Thu, 27 May 2021 17:00:16 -0300 Subject: [PATCH 4/8] Update README.md --- desafio-fullstack-front/README.md | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/desafio-fullstack-front/README.md b/desafio-fullstack-front/README.md index 966590328..af6811dd6 100644 --- a/desafio-fullstack-front/README.md +++ b/desafio-fullstack-front/README.md @@ -1,27 +1,5 @@ # DesafioFullstackFront -This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.1.1. +## Inicialização -## Development server - -Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files. - -## Code scaffolding - -Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`. - -## Build - -Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build. - -## Running unit tests - -Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io). - -## Running end-to-end tests - -Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/). - -## Further help - -To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md). +- Inicializar o projeto utilize o comando `ng serve` From 30b76cb08329b69814b67e64bc7b2280efcd0d8f Mon Sep 17 00:00:00 2001 From: Gabriel Masiero <34697315+CHIODELLIz@users.noreply.github.com> Date: Thu, 27 May 2021 17:01:35 -0300 Subject: [PATCH 5/8] Update environment.ts --- desafio-fullstack-front/src/environments/environment.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desafio-fullstack-front/src/environments/environment.ts b/desafio-fullstack-front/src/environments/environment.ts index 3a51f5b53..5193b0038 100644 --- a/desafio-fullstack-front/src/environments/environment.ts +++ b/desafio-fullstack-front/src/environments/environment.ts @@ -5,7 +5,7 @@ export const environment = { production: false, - baseUrl: 'http://192.168.0.107:3000' + baseUrl: 'Adicione a URL da API' }; /* From 59cb9e5bae46dc0547c7dede135a8ee16ec3e6b4 Mon Sep 17 00:00:00 2001 From: Gabriel Masiero <34697315+CHIODELLIz@users.noreply.github.com> Date: Thu, 27 May 2021 17:04:41 -0300 Subject: [PATCH 6/8] Update README.md --- desafio-fullstack-front/README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/desafio-fullstack-front/README.md b/desafio-fullstack-front/README.md index af6811dd6..ac80c00a6 100644 --- a/desafio-fullstack-front/README.md +++ b/desafio-fullstack-front/README.md @@ -3,3 +3,7 @@ ## Inicialização - Inicializar o projeto utilize o comando `ng serve` + +## Conexão com a API + +- No caminho `desafio-fullstack-front/src/environments/environment.ts`, altere o campo chamado `baseUrl` e informe o IP da API. From 1885c90409bc9f966e76d8d6ab0376633c7ac21a Mon Sep 17 00:00:00 2001 From: Gabriel Masiero <34697315+CHIODELLIz@users.noreply.github.com> Date: Thu, 27 May 2021 17:14:59 -0300 Subject: [PATCH 7/8] Update README.md --- desafio-fullstack-backend/README.md | 78 ++++++++--------------------- 1 file changed, 21 insertions(+), 57 deletions(-) diff --git a/desafio-fullstack-backend/README.md b/desafio-fullstack-backend/README.md index 9fe8812ff..e7c48acff 100644 --- a/desafio-fullstack-backend/README.md +++ b/desafio-fullstack-backend/README.md @@ -1,73 +1,37 @@ -

- Nest Logo -

+# DesafioFullstackBackend -[circleci-image]: https://img.shields.io/circleci/build/github/nestjs/nest/master?token=abc123def456 -[circleci-url]: https://circleci.com/gh/nestjs/nest - -

A progressive Node.js framework for building efficient and scalable server-side applications.

-

-NPM Version -Package License -NPM Downloads -CircleCI -Coverage -Discord -Backers on Open Collective -Sponsors on Open Collective - - Support us - -

- - -## Description - -[Nest](https://github.com/nestjs/nest) framework TypeScript starter repository. - -## Installation +## Instalação ```bash $ npm install ``` -## Running the app +## Inicialização ```bash # development $ npm run start - -# watch mode -$ npm run start:dev - -# production mode -$ npm run start:prod ``` -## Test +## Conexão com o banco de dados +- Crie um arquivo `.env` +- Adicione as seguintes configurações: ```bash -# unit tests -$ npm run test - -# e2e tests -$ npm run test:e2e - -# test coverage -$ npm run test:cov +DATABASE_HOST= +DATABASE_PORT= +DATABASE_USERNAME= +DATABASE_PASSWORD= +DATABASE_NAME= ``` -## Support - -Nest is an MIT-licensed open source project. It can grow thanks to the sponsors and support by the amazing backers. If you'd like to join them, please [read more here](https://docs.nestjs.com/support). - -## Stay in touch - -- Author - [Kamil Myśliwiec](https://kamilmysliwiec.com) -- Website - [https://nestjs.com](https://nestjs.com/) -- Twitter - [@nestframework](https://twitter.com/nestframework) - -## License - -Nest is [MIT licensed](LICENSE). +## Criar banco de dados +- Automático +```bash +Ao iniciar o projeto, as tabelas vão ser automaticamente criadas. +``` +- Manual +```bash +Importe o arquivo create-database.sql em seu pgadmin (ou algum outro que esteja utilizando). +``` +[Arquivo para criar banco de dado](./create-database.sql) From 210316d510a9b411bcbcf9cfae4145f5addbbb80 Mon Sep 17 00:00:00 2001 From: Gabriel Masiero <34697315+CHIODELLIz@users.noreply.github.com> Date: Thu, 27 May 2021 17:17:10 -0300 Subject: [PATCH 8/8] Update README.md --- desafio-fullstack-front/README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/desafio-fullstack-front/README.md b/desafio-fullstack-front/README.md index ac80c00a6..6d8592bde 100644 --- a/desafio-fullstack-front/README.md +++ b/desafio-fullstack-front/README.md @@ -1,9 +1,22 @@ # DesafioFullstackFront +## Instalação + +```bash +$ npm install +``` + ## Inicialização +```bash +# development +$ ng serve +``` - Inicializar o projeto utilize o comando `ng serve` ## Conexão com a API -- No caminho `desafio-fullstack-front/src/environments/environment.ts`, altere o campo chamado `baseUrl` e informe o IP da API. +```bash +Acesse o arquivo `environment.ts`, e informe o IP da API no campo `baseUrl`. +``` +[Arquivo environment](./src/environments/environment.ts)