├── src ├── assets │ └── .gitkeep ├── app │ ├── app.component.css │ ├── components │ │ ├── car │ │ │ ├── car.component.css │ │ │ ├── car.component.spec.ts │ │ │ ├── car.component.ts │ │ │ └── car.component.html │ │ ├── navi │ │ │ ├── navi.component.css │ │ │ ├── navi.component.spec.ts │ │ │ ├── navi.component.ts │ │ │ └── navi.component.html │ │ ├── brand │ │ │ ├── brand.component.css │ │ │ ├── brand.component.spec.ts │ │ │ ├── brand.component.ts │ │ │ └── brand.component.html │ │ ├── color │ │ │ ├── color.component.css │ │ │ ├── color.component.spec.ts │ │ │ ├── color.component.ts │ │ │ └── color.component.html │ │ ├── payment │ │ │ ├── payment.component.css │ │ │ ├── payment.component.spec.ts │ │ │ ├── payment.component.html │ │ │ └── payment.component.ts │ │ ├── rental │ │ │ ├── rental.component.css │ │ │ ├── rental.component.spec.ts │ │ │ ├── rental.component.html │ │ │ └── rental.component.ts │ │ ├── cardetail │ │ │ ├── cardetail.component.css │ │ │ ├── cardetail.component.spec.ts │ │ │ ├── cardetail.component.html │ │ │ └── cardetail.component.ts │ │ ├── customer │ │ │ ├── customer.component.css │ │ │ ├── customer-update │ │ │ │ └── customer-update │ │ │ │ │ ├── customer-update.component.css │ │ │ │ │ ├── customer-update.component.spec.ts │ │ │ │ │ ├── customer-update.component.ts │ │ │ │ │ └── customer-update.component.html │ │ │ ├── customer.component.spec.ts │ │ │ ├── customer.component.html │ │ │ └── customer.component.ts │ │ ├── register │ │ │ ├── register.component.css │ │ │ ├── register.component.spec.ts │ │ │ ├── register.component.html │ │ │ └── register.component.ts │ │ ├── brand-color │ │ │ ├── brand-color.component.css │ │ │ ├── brand-color.component.spec.ts │ │ │ ├── brand-color.component.html │ │ │ └── brand-color.component.ts │ │ ├── onecardetail │ │ │ ├── onecardetail.component.css │ │ │ ├── onecardetail.component.spec.ts │ │ │ ├── onecardetail.component.html │ │ │ └── onecardetail.component.ts │ │ ├── add_operations │ │ │ ├── car-add │ │ │ │ ├── car-add.component.css │ │ │ │ ├── car-add.component.spec.ts │ │ │ │ ├── car-add.component.ts │ │ │ │ └── car-add.component.html │ │ │ ├── brand-add │ │ │ │ ├── brand-add.component.css │ │ │ │ ├── brand-add.component.spec.ts │ │ │ │ ├── brand-add.component.html │ │ │ │ └── brand-add.component.ts │ │ │ └── color-add │ │ │ │ ├── color-add.component.css │ │ │ │ ├── color-add.component.spec.ts │ │ │ │ ├── color-add.component.html │ │ │ │ └── color-add.component.ts │ │ └── login │ │ │ ├── login.component.spec.ts │ │ │ ├── login.component.css │ │ │ ├── login.component.html │ │ │ └── login.component.ts │ ├── models │ │ ├── brand.ts │ │ ├── color.ts │ │ ├── loginModel.ts │ │ ├── tokenModel.ts │ │ ├── findex.ts │ │ ├── responseModel.ts │ │ ├── customer.ts │ │ ├── user.ts │ │ ├── rental.ts │ │ ├── listResponseModel.ts │ │ ├── singleResponseModel.ts │ │ ├── customerDetail.ts │ │ ├── fakeCard.ts │ │ ├── cardetail.ts │ │ └── rentalDetail.ts │ ├── app.component.ts │ ├── app.component.html │ ├── interceptors │ │ ├── auth.interceptor.spec.ts │ │ └── auth.interceptor.ts │ ├── pipes │ │ ├── brand-filter-pipe.pipe.ts │ │ ├── color-filter-pipe.pipe.ts │ │ └── car-filter-pipe.pipe.ts │ ├── services │ │ ├── findex.service.ts │ │ ├── local-storage.service.ts │ │ ├── color.service.ts │ │ ├── brand.service.ts │ │ ├── auth.service.ts │ │ ├── fake-card.service.ts │ │ ├── customer.service.ts │ │ ├── rental.service.ts │ │ └── cardetail.service.ts │ ├── guards │ │ └── login.guard.ts │ ├── app.component.spec.ts │ ├── app-routing.module.ts │ └── app.module.ts ├── favicon.ico ├── styles.css ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── index.html ├── main.ts ├── test.ts └── polyfills.ts ├── e2e ├── src │ ├── app.po.ts │ └── app.e2e-spec.ts ├── tsconfig.json └── protractor.conf.js ├── .editorconfig ├── tsconfig.app.json ├── tsconfig.spec.json ├── .browserslistrc ├── .gitignore ├── tsconfig.json ├── package.json ├── karma.conf.js ├── tslint.json ├── angular.json └── README.md /src/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/car/car.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/navi/navi.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/brand/brand.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/color/color.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/payment/payment.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/rental/rental.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/cardetail/cardetail.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/customer/customer.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/register/register.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/brand-color/brand-color.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/onecardetail/onecardetail.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/add_operations/car-add/car-add.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/add_operations/brand-add/brand-add.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/add_operations/color-add/color-add.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/customer/customer-update/customer-update/customer-update.component.css: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/models/brand.ts: -------------------------------------------------------------------------------- 1 | export interface Brand{ 2 | id:number, 3 | name:string 4 | } -------------------------------------------------------------------------------- /src/app/models/color.ts: -------------------------------------------------------------------------------- 1 | export interface Color{ 2 | id:number, 3 | name:string 4 | } -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Mertcali/RentACar-Frontend/HEAD/src/favicon.ico -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/app/models/loginModel.ts: -------------------------------------------------------------------------------- 1 | export interface LoginModel{ 2 | email:string; 3 | password:string; 4 | } -------------------------------------------------------------------------------- /src/app/models/tokenModel.ts: -------------------------------------------------------------------------------- 1 | export interface TokenModel{ 2 | token:string; 3 | expriration:string; 4 | } -------------------------------------------------------------------------------- /src/app/models/findex.ts: -------------------------------------------------------------------------------- 1 | export interface Findex{ 2 | userId:number, 3 | findexScore:number, 4 | 5 | } -------------------------------------------------------------------------------- /src/app/models/responseModel.ts: -------------------------------------------------------------------------------- 1 | export interface ResponseModel{ 2 | success:boolean, 3 | message:string 4 | } -------------------------------------------------------------------------------- /src/app/models/customer.ts: -------------------------------------------------------------------------------- 1 | export interface Customer{ 2 | Id:number, 3 | userId:number, 4 | companyName:string, 5 | } -------------------------------------------------------------------------------- /src/app/models/user.ts: -------------------------------------------------------------------------------- 1 | export interface User{ 2 | firstName:string, 3 | lastName:string, 4 | email:string, 5 | password:string, 6 | } -------------------------------------------------------------------------------- /src/app/models/rental.ts: -------------------------------------------------------------------------------- 1 | export interface Rental{ 2 | id:number, 3 | carId:number, 4 | userId:number, 5 | rentDate:Date, 6 | returnDate:Date 7 | } -------------------------------------------------------------------------------- /src/app/models/listResponseModel.ts: -------------------------------------------------------------------------------- 1 | import { ResponseModel } from "./responseModel"; 2 | 3 | export interface ListResponseModel extends ResponseModel{ 4 | data:T[] 5 | } -------------------------------------------------------------------------------- /src/app/models/singleResponseModel.ts: -------------------------------------------------------------------------------- 1 | import { ResponseModel } from "./responseModel"; 2 | 3 | export interface SingleResponseModel extends ResponseModel{ 4 | data:T 5 | } -------------------------------------------------------------------------------- /src/app/models/customerDetail.ts: -------------------------------------------------------------------------------- 1 | export class CustomerDetail{ 2 | userId:number 3 | companyName:string 4 | firstName:string 5 | lastName:string 6 | email:string 7 | findexScore:number 8 | } -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | title = 'rentacar'; 10 | } 11 | -------------------------------------------------------------------------------- /src/app/models/fakeCard.ts: -------------------------------------------------------------------------------- 1 | export interface FakeCard{ 2 | id:number, 3 | nameOnCard:string, 4 | lastNameOnCard:string, 5 | cardNumber:string, 6 | cardCVV:string, 7 | expirationDateMonth:string, 8 | expirationDateYear:string, 9 | moneyInCard:number 10 | 11 | } -------------------------------------------------------------------------------- /e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | async navigateTo(): Promise { 5 | return browser.get(browser.baseUrl); 6 | } 7 | 8 | async getTitleText(): Promise { 9 | return element(by.css('app-root .content span')).getText(); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/app/models/cardetail.ts: -------------------------------------------------------------------------------- 1 | export interface CarDetail{ 2 | carId:number, 3 | colorId:number, 4 | brandId:number, 5 | carName:string, 6 | brandName:string, 7 | colorName:string, 8 | imagePath:string, 9 | modelYear:string, 10 | description:string, 11 | dailyPrice:number, 12 | minFindex:number 13 | } -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "../tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "../out-tsc/e2e", 6 | "module": "commonjs", 7 | "target": "es2018", 8 | "types": [ 9 | "jasmine", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.ts] 12 | quote_type = single 13 | 14 | [*.md] 15 | max_line_length = off 16 | trim_trailing_whitespace = false 17 | -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Rentacar 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/app", 6 | "types": [] 7 | }, 8 | "files": [ 9 | "src/main.ts", 10 | "src/polyfills.ts" 11 | ], 12 | "include": [ 13 | "src/**/*.d.ts" 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | 8 | 9 |
10 |
11 | > 12 |
13 |
14 |
15 | -------------------------------------------------------------------------------- /src/app/models/rentalDetail.ts: -------------------------------------------------------------------------------- 1 | export interface RentalDetail{ 2 | id?:number, 3 | carId:number, 4 | userId?:number, 5 | brandName?:string, 6 | colorName:string, 7 | carName?:string, 8 | userName?:string, 9 | customerName?:string, 10 | carDailyPrice:number, 11 | carModelYear:string, 12 | carDescription:string 13 | rentDate:Date, 14 | returnDate?:Date, 15 | } -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "extends": "./tsconfig.json", 4 | "compilerOptions": { 5 | "outDir": "./out-tsc/spec", 6 | "types": [ 7 | "jasmine" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import { enableProdMode } from '@angular/core'; 2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 3 | 4 | import { AppModule } from './app/app.module'; 5 | import { environment } from './environments/environment'; 6 | 7 | if (environment.production) { 8 | enableProdMode(); 9 | } 10 | 11 | platformBrowserDynamic().bootstrapModule(AppModule) 12 | .catch(err => console.error(err)); 13 | -------------------------------------------------------------------------------- /src/app/interceptors/auth.interceptor.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | 3 | import { AuthInterceptor } from './auth.interceptor'; 4 | 5 | describe('AuthInterceptor', () => { 6 | beforeEach(() => TestBed.configureTestingModule({ 7 | providers: [ 8 | AuthInterceptor 9 | ] 10 | })); 11 | 12 | it('should be created', () => { 13 | const interceptor: AuthInterceptor = TestBed.inject(AuthInterceptor); 14 | expect(interceptor).toBeTruthy(); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /src/app/pipes/brand-filter-pipe.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | import { Brand } from '../models/brand'; 3 | 4 | @Pipe({ 5 | name: 'brandFilterPipe' 6 | }) 7 | export class BrandFilterPipePipe implements PipeTransform { 8 | 9 | transform(value: Brand[], filterText: string): Brand[] { 10 | filterText = filterText?filterText.toLocaleLowerCase():"" 11 | return filterText?value.filter((c:Brand)=>c.name.toLocaleLowerCase().indexOf(filterText)!==-1) 12 | :value 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/pipes/color-filter-pipe.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | import { Color } from '../models/color'; 3 | 4 | @Pipe({ 5 | name: 'colorFilterPipe' 6 | }) 7 | export class ColorFilterPipePipe implements PipeTransform { 8 | 9 | transform(value: Color[], filterText: string): Color[] { 10 | filterText = filterText?filterText.toLocaleLowerCase():"" 11 | return filterText?value.filter((c:Color)=>c.name.toLocaleLowerCase().indexOf(filterText)!==-1) 12 | :value 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/pipes/car-filter-pipe.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | import { CarDetail } from '../models/cardetail'; 3 | 4 | @Pipe({ 5 | name: 'carFilterPipe' 6 | }) 7 | export class CarFilterPipePipe implements PipeTransform { 8 | 9 | transform(value: CarDetail[], filterText: string): CarDetail[] { 10 | filterText = filterText?filterText.toLocaleLowerCase():"" 11 | return filterText?value.filter((c:CarDetail)=>(c.carName + c.brandName).toLocaleLowerCase().indexOf(filterText)!==-1) 12 | :value 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/app/interceptors/auth.interceptor.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { 3 | HttpRequest, 4 | HttpHandler, 5 | HttpEvent, 6 | HttpInterceptor 7 | } from '@angular/common/http'; 8 | import { Observable } from 'rxjs'; 9 | 10 | @Injectable() 11 | export class AuthInterceptor implements HttpInterceptor { 12 | 13 | constructor() {} 14 | 15 | intercept(request: HttpRequest, next: HttpHandler): Observable> { 16 | let token = localStorage.getItem("token"); 17 | let newRequest : HttpRequest 18 | newRequest = request.clone({ 19 | headers: request.headers.set("Authorization","Bearer " + token) 20 | }) 21 | return next.handle(newRequest); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/app/components/car/car.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CarComponent } from './car.component'; 4 | 5 | describe('CarComponent', () => { 6 | let component: CarComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CarComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CarComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /src/app/components/navi/navi.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { NaviComponent } from './navi.component'; 4 | 5 | describe('NaviComponent', () => { 6 | let component: NaviComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ NaviComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(NaviComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/brand/brand.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { BrandComponent } from './brand.component'; 4 | 5 | describe('BrandComponent', () => { 6 | let component: BrandComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ BrandComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(BrandComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/color/color.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ColorComponent } from './color.component'; 4 | 5 | describe('ColorComponent', () => { 6 | let component: ColorComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ColorComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ColorComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/login/login.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LoginComponent } from './login.component'; 4 | 5 | describe('LoginComponent', () => { 6 | let component: LoginComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ LoginComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(LoginComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { browser, logging } from 'protractor'; 2 | import { AppPage } from './app.po'; 3 | 4 | describe('workspace-project App', () => { 5 | let page: AppPage; 6 | 7 | beforeEach(() => { 8 | page = new AppPage(); 9 | }); 10 | 11 | it('should display welcome message', async () => { 12 | await page.navigateTo(); 13 | expect(await page.getTitleText()).toEqual('rentacar app is running!'); 14 | }); 15 | 16 | afterEach(async () => { 17 | // Assert that there are no errors emitted from the browser 18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER); 19 | expect(logs).not.toContain(jasmine.objectContaining({ 20 | level: logging.Level.SEVERE, 21 | } as logging.Entry)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /src/app/components/rental/rental.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { RentalComponent } from './rental.component'; 4 | 5 | describe('RentalComponent', () => { 6 | let component: RentalComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ RentalComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(RentalComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /.browserslistrc: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # For the full list of supported browsers by the Angular framework, please see: 6 | # https://angular.io/guide/browser-support 7 | 8 | # You can see what browsers were selected by your queries by running: 9 | # npx browserslist 10 | 11 | last 1 Chrome version 12 | last 1 Firefox version 13 | last 2 Edge major versions 14 | last 2 Safari major versions 15 | last 2 iOS major versions 16 | Firefox ESR 17 | not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line. 18 | -------------------------------------------------------------------------------- /src/app/components/payment/payment.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { PaymentComponent } from './payment.component'; 4 | 5 | describe('PaymentComponent', () => { 6 | let component: PaymentComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ PaymentComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(PaymentComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/add_operations/car-add/car-add.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CarAddComponent } from './car-add.component'; 4 | 5 | describe('CarAddComponent', () => { 6 | let component: CarAddComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CarAddComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CarAddComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/customer/customer.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CustomerComponent } from './customer.component'; 4 | 5 | describe('CustomerComponent', () => { 6 | let component: CustomerComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CustomerComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CustomerComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/register/register.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { RegisterComponent } from './register.component'; 4 | 5 | describe('RegisterComponent', () => { 6 | let component: RegisterComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ RegisterComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(RegisterComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/cardetail/cardetail.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CardetailComponent } from './cardetail.component'; 4 | 5 | describe('CardetailComponent', () => { 6 | let component: CardetailComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CardetailComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CardetailComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/add_operations/brand-add/brand-add.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { BrandAddComponent } from './brand-add.component'; 4 | 5 | describe('BrandAddComponent', () => { 6 | let component: BrandAddComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ BrandAddComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(BrandAddComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/add_operations/color-add/color-add.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { ColorAddComponent } from './color-add.component'; 4 | 5 | describe('ColorAddComponent', () => { 6 | let component: ColorAddComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ ColorAddComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(ColorAddComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/brand-color/brand-color.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { BrandColorComponent } from './brand-color.component'; 4 | 5 | describe('BrandColorComponent', () => { 6 | let component: BrandColorComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ BrandColorComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(BrandColorComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/components/onecardetail/onecardetail.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { OnecardetailComponent } from './onecardetail.component'; 4 | 5 | describe('OnecardetailComponent', () => { 6 | let component: OnecardetailComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ OnecardetailComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(OnecardetailComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: { 11 | context(path: string, deep?: boolean, filter?: RegExp): { 12 | keys(): string[]; 13 | (id: string): T; 14 | }; 15 | }; 16 | 17 | // First, initialize the Angular testing environment. 18 | getTestBed().initTestEnvironment( 19 | BrowserDynamicTestingModule, 20 | platformBrowserDynamicTesting() 21 | ); 22 | // Then we find all the tests. 23 | const context = require.context('./', true, /\.spec\.ts$/); 24 | // And load the modules. 25 | context.keys().map(context); 26 | -------------------------------------------------------------------------------- /src/app/components/customer/customer-update/customer-update/customer-update.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { CustomerUpdateComponent } from './customer-update.component'; 4 | 5 | describe('CustomerUpdateComponent', () => { 6 | let component: CustomerUpdateComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async () => { 10 | await TestBed.configureTestingModule({ 11 | declarations: [ CustomerUpdateComponent ] 12 | }) 13 | .compileComponents(); 14 | }); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(CustomerUpdateComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/services/findex.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { Observable } from 'rxjs'; 4 | import { Findex } from '../models/findex'; 5 | import { ListResponseModel } from '../models/listResponseModel'; 6 | import { SingleResponseModel } from '../models/singleResponseModel'; 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class FindexService { 12 | 13 | apiUrl="https://localhost:44378/api/findex/" 14 | 15 | constructor(private httpClient:HttpClient) { } 16 | 17 | getFindexScoreByUserId(userId:number):Observable>{ 18 | let newPath=this.apiUrl+"getbyuserid?id=" + userId 19 | return this.httpClient.get>(newPath); 20 | 21 | } 22 | 23 | add(findex:Findex){ 24 | return this.httpClient.post>(this.apiUrl+"add",findex) 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/app/services/local-storage.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CustomerDetail } from '../models/customerDetail'; 3 | import { Rental } from '../models/rental'; 4 | import { CustomerService } from './customer.service'; 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | export class LocalStorageService { 10 | 11 | 12 | 13 | constructor() 14 | {} 15 | getItem(key:string){ 16 | return localStorage.getItem(key); 17 | } 18 | 19 | setItem(key:string, value:any){ 20 | localStorage.setItem(key,value); 21 | } 22 | 23 | removeItem(key:string){ 24 | localStorage.removeItem(key); 25 | } 26 | 27 | clear(){ 28 | localStorage.clear(); 29 | } 30 | 31 | setToken(token: string){ 32 | localStorage.setItem("token",token) 33 | } 34 | 35 | removeToken(){ 36 | localStorage.removeItem("token"); 37 | } 38 | 39 | getToken(){ 40 | return localStorage.getItem("token"); 41 | } 42 | 43 | } 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */ 2 | { 3 | "compileOnSave": false, 4 | "compilerOptions": { 5 | "baseUrl": "./", 6 | "outDir": "./dist/out-tsc", 7 | "forceConsistentCasingInFileNames": true, 8 | "strict": true, 9 | "strictNullChecks": false, 10 | "strictPropertyInitialization": false, 11 | "noImplicitReturns": true, 12 | "noFallthroughCasesInSwitch": true, 13 | "sourceMap": true, 14 | "declaration": false, 15 | "downlevelIteration": true, 16 | "experimentalDecorators": true, 17 | "moduleResolution": "node", 18 | "importHelpers": true, 19 | "target": "es2015", 20 | "module": "es2020", 21 | "lib": [ 22 | "es2018", 23 | "dom" 24 | ] 25 | }, 26 | "angularCompilerOptions": { 27 | "enableI18nLegacyMessageIdFormat": false, 28 | "strictInjectionParameters": true, 29 | "strictInputAccessModifiers": true, 30 | "strictTemplates": true 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/app/guards/login.guard.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router'; 3 | import { ToastrService } from 'ngx-toastr'; 4 | import { Observable } from 'rxjs'; 5 | import { AuthService } from '../services/auth.service'; 6 | 7 | @Injectable({ 8 | providedIn: 'root' 9 | }) 10 | export class LoginGuard implements CanActivate { 11 | 12 | constructor(private authService:AuthService, 13 | private toastrService:ToastrService, 14 | private router:Router 15 | ){} 16 | 17 | 18 | canActivate( 19 | route: ActivatedRouteSnapshot, 20 | state: RouterStateSnapshot): Observable | Promise | boolean | UrlTree { 21 | if(this.authService.isAuthenticated()){ 22 | return true; 23 | }else{ 24 | this.router.navigate(["login"]) 25 | this.toastrService.info("Sisteme giriş yapmalısınız") 26 | return false; 27 | } 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/app/services/color.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import {HttpClient} from '@angular/common/http' 3 | import { Observable } from 'rxjs'; 4 | import { ListResponseModel } from '../models/listResponseModel'; 5 | import { Color } from '../models/color'; 6 | import { ResponseModel } from '../models/responseModel'; 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class ColorService { 12 | 13 | apiUrl="https://localhost:44378/api/colors/" 14 | 15 | constructor(private httpClient:HttpClient) { } 16 | 17 | getColors():Observable>{ 18 | let newPath = this.apiUrl +"getall" 19 | return this.httpClient.get>(newPath) 20 | } 21 | add(color:Color):Observable{ 22 | return this.httpClient.post(this.apiUrl+"add",color) 23 | } 24 | 25 | update(color:Color):Observable{ 26 | return this.httpClient.post(this.apiUrl+"update",color) 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /src/app/components/rental/rental.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 7 | 8 |
9 |
10 | 11 |
12 |
13 | 15 | 16 |
17 |
18 |
19 | 20 |
21 | 24 |
25 |
-------------------------------------------------------------------------------- /src/app/services/brand.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import {HttpClient} from '@angular/common/http' 3 | import { Observable } from 'rxjs'; 4 | import { ListResponseModel } from '../models/listResponseModel'; 5 | import { Brand } from '../models/brand'; 6 | import { ResponseModel } from '../models/responseModel'; 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class BrandService { 12 | 13 | apiUrl="https://localhost:44378/api/brands/" 14 | constructor(private httpClient:HttpClient) { } 15 | 16 | 17 | getBrands():Observable>{ 18 | let newPath=this.apiUrl +"getall" 19 | return this.httpClient.get>(newPath) 20 | } 21 | 22 | add(brand:Brand):Observable{ 23 | return this.httpClient.post(this.apiUrl+"add",brand) 24 | } 25 | 26 | update(brand:Brand):Observable{ 27 | return this.httpClient.post(this.apiUrl+"update",brand) 28 | } 29 | 30 | } 31 | 32 | 33 | -------------------------------------------------------------------------------- /e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Protractor configuration file, see link for more information 3 | // https://github.com/angular/protractor/blob/master/lib/config.ts 4 | 5 | const { SpecReporter, StacktraceOption } = require('jasmine-spec-reporter'); 6 | 7 | /** 8 | * @type { import("protractor").Config } 9 | */ 10 | exports.config = { 11 | allScriptsTimeout: 11000, 12 | specs: [ 13 | './src/**/*.e2e-spec.ts' 14 | ], 15 | capabilities: { 16 | browserName: 'chrome' 17 | }, 18 | directConnect: true, 19 | SELENIUM_PROMISE_MANAGER: false, 20 | baseUrl: 'http://localhost:4200/', 21 | framework: 'jasmine', 22 | jasmineNodeOpts: { 23 | showColors: true, 24 | defaultTimeoutInterval: 30000, 25 | print: function() {} 26 | }, 27 | onPrepare() { 28 | require('ts-node').register({ 29 | project: require('path').join(__dirname, './tsconfig.json') 30 | }); 31 | jasmine.getEnv().addReporter(new SpecReporter({ 32 | spec: { 33 | displayStacktrace: StacktraceOption.PRETTY 34 | } 35 | })); 36 | } 37 | }; -------------------------------------------------------------------------------- /src/app/services/auth.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { LoginModel } from '../models/loginModel'; 4 | import { SingleResponseModel } from '../models/singleResponseModel'; 5 | import { TokenModel } from '../models/tokenModel'; 6 | import { User } from '../models/user'; 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class AuthService { 12 | 13 | 14 | 15 | apiUrl="https://localhost:44378/api/auth/" 16 | constructor(private httpClient:HttpClient) { } 17 | 18 | login(user:LoginModel){ 19 | return this.httpClient.post>(this.apiUrl+"login", user) 20 | } 21 | 22 | isAuthenticated(){ 23 | if(localStorage.getItem("token")){ 24 | return true; 25 | }else{ 26 | return false; 27 | } 28 | } 29 | 30 | register(user:User){ 31 | return this.httpClient.post>(this.apiUrl+"register", user) 32 | } 33 | 34 | logout(){ 35 | localStorage.clear(); 36 | } 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/app/components/customer/customer.component.html: -------------------------------------------------------------------------------- 1 |
2 | ... 3 |
4 |
Profil Görünümü
5 |

Burada başka biri profilinize girdiğinde nasıl göründüğünü görüp, düzenleme yapabilirsiniz.

6 |
7 |
    8 |
  • Ad: {{user.firstName}}
  • 9 |
  • Soyadı: {{user.lastName}}
  • 10 |
  • Şirket: {{user.companyName}}
  • 11 |
  • Mail: {{user.email}}
  • 12 |
  • Findeks: {{user.findexScore}}
  • 13 |
14 |
15 | Profili Ayarla 16 |
17 |
-------------------------------------------------------------------------------- /src/app/components/login/login.component.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | display: flex; 8 | align-items: center; 9 | padding-top: 40px; 10 | padding-bottom: 40px; 11 | } 12 | 13 | .form-signin { 14 | width: 100%; 15 | max-width: 330px; 16 | padding: 15px; 17 | margin: auto; 18 | } 19 | 20 | .form-signin .checkbox { 21 | font-weight: 400; 22 | } 23 | 24 | .form-signin .form-floating:focus-within { 25 | z-index: 2; 26 | } 27 | 28 | .form-signin input[type="email"] { 29 | margin-bottom: -1px; 30 | border-bottom-right-radius: 0; 31 | border-bottom-left-radius: 0; 32 | } 33 | 34 | .form-signin input[type="password"] { 35 | margin-bottom: 10px; 36 | border-top-left-radius: 0; 37 | border-top-right-radius: 0; 38 | } 39 | 40 | .bd-placeholder-img { 41 | font-size: 1.125rem; 42 | text-anchor: middle; 43 | -webkit-user-select: none; 44 | -moz-user-select: none; 45 | user-select: none; 46 | } 47 | 48 | @media (min-width: 768px) { 49 | .bd-placeholder-img-lg { 50 | font-size: 3.5rem; 51 | } 52 | } -------------------------------------------------------------------------------- /src/app/components/cardetail/cardetail.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | thumbnail 5 |
6 |
{{cardetail.brandName}} {{cardetail.carName}}
7 |

{{cardetail.description}}

8 |
9 |
    10 |
  • Renk: {{cardetail.colorName}}
  • 11 |
  • Model: {{cardetail.modelYear}}
  • 12 |
  • Günlük Fiyat: {{cardetail.dailyPrice}}
  • 13 |
14 |
15 |
16 | 17 |
18 |
19 |
20 |
21 |
22 | 23 | -------------------------------------------------------------------------------- /src/app/components/brand-color/brand-color.component.html: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 |
5 | 13 |
14 |
15 | 23 |
24 |
25 | 26 |
27 |
-------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async () => { 7 | await TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule 10 | ], 11 | declarations: [ 12 | AppComponent 13 | ], 14 | }).compileComponents(); 15 | }); 16 | 17 | it('should create the app', () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.componentInstance; 20 | expect(app).toBeTruthy(); 21 | }); 22 | 23 | it(`should have as title 'rentacar'`, () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | const app = fixture.componentInstance; 26 | expect(app.title).toEqual('rentacar'); 27 | }); 28 | 29 | it('should render title', () => { 30 | const fixture = TestBed.createComponent(AppComponent); 31 | fixture.detectChanges(); 32 | const compiled = fixture.nativeElement; 33 | expect(compiled.querySelector('.content span').textContent).toContain('rentacar app is running!'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /src/app/services/fake-card.service.ts: -------------------------------------------------------------------------------- 1 | import { HttpClient } from '@angular/common/http'; 2 | import { Injectable } from '@angular/core'; 3 | import { Observable } from 'rxjs'; 4 | import { FakeCard } from '../models/fakeCard'; 5 | import { ListResponseModel } from '../models/listResponseModel'; 6 | import { ResponseModel } from '../models/responseModel'; 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class FakeCardService { 12 | 13 | constructor(private httpClient:HttpClient) { } 14 | 15 | apiUrl="https://localhost:44378/api/fakecards/" 16 | 17 | isCardExist(fakeCard:FakeCard):Observable{ 18 | let newPath = this.apiUrl+"iscardexist"; 19 | return this.httpClient.post(newPath,fakeCard) 20 | } 21 | 22 | getCardByUserId(userId:number):Observable>{ 23 | let newPath = this.apiUrl+"getbyuserid?id="+userId; 24 | return this.httpClient.get>(newPath) 25 | } 26 | 27 | add(fakeCard:FakeCard):Observable{ 28 | return this.httpClient.post(this.apiUrl+"add",fakeCard) 29 | } 30 | 31 | getCardByNumber(cardNumber:string):Observable>{ 32 | let newPath = this.apiUrl+"getbycardnumber?id="+cardNumber 33 | return this.httpClient.get>(newPath) 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/app/components/color/color.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Color } from 'src/app/models/color'; 3 | import { ColorService } from 'src/app/services/color.service'; 4 | 5 | @Component({ 6 | selector: 'app-color', 7 | templateUrl: './color.component.html', 8 | styleUrls: ['./color.component.css'] 9 | }) 10 | export class ColorComponent implements OnInit { 11 | 12 | colors:Color[]=[] 13 | currentColor:Color; 14 | nullColor:Color; 15 | filterText=""; 16 | dataLoaded=false; 17 | 18 | constructor(private colorService:ColorService) { } 19 | 20 | ngOnInit(): void { 21 | this.getColors() 22 | } 23 | 24 | getColors(){ 25 | this.colorService.getColors().subscribe(response=>{ 26 | this.colors=response.data 27 | this.dataLoaded=true; 28 | }) 29 | 30 | } 31 | 32 | setCurrentColor(color:Color){ 33 | this.currentColor=color; 34 | } 35 | 36 | getCurrentColorClass(color:Color){ 37 | if(color == this.currentColor){ 38 | return "list-group-item list-group-item-warning" 39 | }else{ 40 | return "list-group-item" 41 | } 42 | } 43 | 44 | getAllCarsClass(){ 45 | if(!this.currentColor){ 46 | return "list-group-item list-group-item-warning" 47 | }else{ 48 | return "list-group-item" 49 | } 50 | } 51 | 52 | resetCurrentColor(){ 53 | this.currentColor=this.nullColor; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/app/components/login/login.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Giriş yap

5 | 6 |
7 | 14 | 15 |
16 | 17 |
18 | 19 |
20 | 27 | 28 |
29 | 30 |
31 | 34 |
35 | 38 |
39 |
40 | 43 |

© 2017–2021

44 |
45 |
46 | 47 | -------------------------------------------------------------------------------- /src/app/components/navi/navi.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { CustomerDetail } from 'src/app/models/customerDetail'; 4 | import { AuthService } from 'src/app/services/auth.service'; 5 | import { CustomerService } from 'src/app/services/customer.service'; 6 | import { LocalStorageService } from 'src/app/services/local-storage.service'; 7 | 8 | @Component({ 9 | selector: 'app-navi', 10 | templateUrl: './navi.component.html', 11 | styleUrls: ['./navi.component.css'] 12 | }) 13 | export class NaviComponent implements OnInit { 14 | 15 | 16 | user:CustomerDetail[]=[] 17 | 18 | constructor( 19 | private authService:AuthService, 20 | private customerService:CustomerService, 21 | private localStorageService:LocalStorageService, 22 | private router:Router 23 | ) { } 24 | 25 | ngOnInit(): void { 26 | this.getUsersById(); 27 | } 28 | 29 | 30 | checkLogin():boolean{ 31 | return this.authService.isAuthenticated(); 32 | } 33 | 34 | getUsersById() { 35 | let id =Number(this.localStorageService.getItem('id')) 36 | if(id!=null){ 37 | this.customerService 38 | .getCustomerByUserId(id) 39 | .subscribe((response) => { 40 | this.user = response.data; 41 | })}; 42 | } 43 | 44 | logout(){ 45 | this.authService.logout(); 46 | this.router.navigate(["/cars"]) 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /src/app/components/car/car.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { CarDetail } from 'src/app/models/cardetail'; 3 | import { CardetailService } from 'src/app/services/cardetail.service'; 4 | 5 | @Component({ 6 | selector: 'app-car', 7 | templateUrl: './car.component.html', 8 | styleUrls: ['./car.component.css'] 9 | }) 10 | export class CarComponent implements OnInit { 11 | 12 | cars:CarDetail[]=[] 13 | 14 | currentCar:CarDetail; 15 | nullCar:CarDetail; 16 | filterText=""; 17 | dataLoaded=false; 18 | 19 | constructor(private cardetailService:CardetailService) { } 20 | 21 | ngOnInit(): void { 22 | this.getCars() 23 | } 24 | 25 | getCars(){ 26 | this.cardetailService.getCarDetails().subscribe(response=>{ 27 | this.cars=response.data 28 | this.dataLoaded=true; 29 | }) 30 | 31 | } 32 | 33 | setCurrentCar(car:CarDetail){ 34 | this.currentCar=car; 35 | } 36 | 37 | getCurrentCarClass(car:CarDetail){ 38 | if(car == this.currentCar){ 39 | return "list-group-item list-group-item-warning" 40 | }else{ 41 | return "list-group-item" 42 | } 43 | } 44 | 45 | getAllCarsClass(){ 46 | if(!this.currentCar){ 47 | return "list-group-item list-group-item-warning" 48 | }else{ 49 | return "list-group-item" 50 | } 51 | } 52 | 53 | resetCurrentCar(){ 54 | this.currentCar=this.nullCar; 55 | } 56 | 57 | } 58 | 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/app/components/customer/customer.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Router } from '@angular/router'; 3 | import { Customer } from 'src/app/models/customer'; 4 | import { CustomerDetail } from 'src/app/models/customerDetail'; 5 | import { CustomerService } from 'src/app/services/customer.service'; 6 | import { LocalStorageService } from 'src/app/services/local-storage.service'; 7 | 8 | @Component({ 9 | selector: 'app-customer', 10 | templateUrl: './customer.component.html', 11 | styleUrls: ['./customer.component.css'] 12 | }) 13 | export class CustomerComponent implements OnInit { 14 | 15 | 16 | user:CustomerDetail[]=[] 17 | dataLoaded=false; 18 | constructor(private customerService:CustomerService, 19 | private localStorageService:LocalStorageService, 20 | private router:Router) { } 21 | 22 | ngOnInit(): void { 23 | 24 | this.getUsersById(); 25 | } 26 | 27 | getCustomers(){ 28 | this.customerService.getCustomerDetails().subscribe(response=>{ 29 | this.user=response.data 30 | this.dataLoaded=true; 31 | }) 32 | } 33 | 34 | getUsersById() { 35 | let id =Number(this.localStorageService.getItem('id')) 36 | if(id!=null){ 37 | this.customerService 38 | .getCustomerByUserId(id) 39 | .subscribe((response) => { 40 | this.user = response.data; 41 | })}; 42 | } 43 | 44 | goUpdate(){ 45 | this.router.navigate(["updateprofile"]) 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/app/components/brand/brand.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { Brand } from 'src/app/models/brand'; 3 | import { BrandService } from 'src/app/services/brand.service'; 4 | 5 | @Component({ 6 | selector: 'app-brand', 7 | templateUrl: './brand.component.html', 8 | styleUrls: ['./brand.component.css'] 9 | }) 10 | export class BrandComponent implements OnInit { 11 | 12 | brands:Brand[]=[] 13 | currentBrand:Brand; 14 | nullBrand:Brand; 15 | brandId:number; 16 | filterText=""; 17 | dataLoaded=false; 18 | 19 | constructor(private brandService:BrandService) { } 20 | 21 | ngOnInit(): void { 22 | this.getBrands(); 23 | } 24 | 25 | getBrands(){ 26 | this.brandService.getBrands().subscribe(response=>{ 27 | this.brands=response.data 28 | this.dataLoaded=true; 29 | }) 30 | } 31 | 32 | setCurrentBrand(brand:Brand){ 33 | this.currentBrand=brand; 34 | console.log(this.currentBrand) 35 | } 36 | 37 | getCurrentBrandClass(brand:Brand){ 38 | if(brand == this.currentBrand){ 39 | return "list-group-item list-group-item-warning" 40 | }else{ 41 | return "list-group-item" 42 | } 43 | } 44 | 45 | getAllCarsClass(){ 46 | if(!this.currentBrand){ 47 | return "list-group-item list-group-item-dark" 48 | }else{ 49 | return "list-group-item" 50 | } 51 | } 52 | 53 | resetCurrentBrand(){ 54 | this.currentBrand=this.nullBrand; 55 | } 56 | 57 | } 58 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "rentacar", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve", 7 | "build": "ng build", 8 | "test": "ng test", 9 | "lint": "ng lint", 10 | "e2e": "ng e2e" 11 | }, 12 | "private": true, 13 | "dependencies": { 14 | "@angular/animations": "^11.2.7", 15 | "@angular/common": "~11.2.6", 16 | "@angular/compiler": "~11.2.6", 17 | "@angular/core": "~11.2.6", 18 | "@angular/forms": "~11.2.6", 19 | "@angular/platform-browser": "~11.2.6", 20 | "@angular/platform-browser-dynamic": "~11.2.6", 21 | "@angular/router": "~11.2.6", 22 | "bootstrap": "^5.0.0-beta3", 23 | "jquery": "^3.6.0", 24 | "ngx-toastr": "^13.2.1", 25 | "popper.js": "^1.16.1", 26 | "rxjs": "~6.6.0", 27 | "tslib": "^2.0.0", 28 | "zone.js": "~0.11.3" 29 | }, 30 | "devDependencies": { 31 | "@angular-devkit/build-angular": "~0.1102.5", 32 | "@angular/cli": "~11.2.5", 33 | "@angular/compiler-cli": "~11.2.6", 34 | "@types/jasmine": "~3.6.0", 35 | "@types/node": "^12.11.1", 36 | "codelyzer": "^6.0.0", 37 | "jasmine-core": "~3.6.0", 38 | "jasmine-spec-reporter": "~5.0.0", 39 | "karma": "~6.1.0", 40 | "karma-chrome-launcher": "~3.1.0", 41 | "karma-coverage": "~2.0.3", 42 | "karma-jasmine": "~4.0.0", 43 | "karma-jasmine-html-reporter": "^1.5.0", 44 | "protractor": "~7.0.0", 45 | "ts-node": "~8.3.0", 46 | "tslint": "~6.1.0", 47 | "typescript": "~4.1.5" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/app/components/onecardetail/onecardetail.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 | thumbnail

4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 30 | 31 | 32 |
#MarkaAraçRenkAçıklamaGünlük Fiyat: Gerekli findex:
{{car.carId}}{{car.brandName}}{{car.carName}}{{car.colorName}}{{car.description}}{{car.dailyPrice}} ₺{{car.minFindex}} 27 |
28 | 29 |
33 | 34 | 35 |
36 |
37 |
38 | 39 |
40 | 41 |
42 | -------------------------------------------------------------------------------- /src/app/components/brand/brand.component.html: -------------------------------------------------------------------------------- 1 | 21 | 22 | 23 |
24 |
Marka
25 | 31 | 40 | 43 |
-------------------------------------------------------------------------------- /src/app/components/color/color.component.html: -------------------------------------------------------------------------------- 1 | 23 | 24 |
25 |
Renk
26 | 32 | 40 | 43 |
-------------------------------------------------------------------------------- /src/app/services/customer.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import {HttpClient} from '@angular/common/http' 3 | import { Observable } from 'rxjs'; 4 | import { ListResponseModel } from '../models/listResponseModel'; 5 | import { CustomerDetail } from '../models/customerDetail'; 6 | import { SingleResponseModel } from '../models/singleResponseModel'; 7 | import { User } from '../models/user'; 8 | import { ResponseModel } from '../models/responseModel'; 9 | 10 | @Injectable({ 11 | providedIn: 'root' 12 | }) 13 | export class CustomerService { 14 | 15 | apiUrl="https://localhost:44378/api/" 16 | constructor(private httpClient:HttpClient) { } 17 | 18 | getCustomerDetails():Observable>{ 19 | let newPath= this.apiUrl + "customers/getall" 20 | return this.httpClient.get>(newPath) 21 | } 22 | 23 | getCustomerWithMail(email:string):Observable>{ 24 | let newPath = this.apiUrl + "customers/getbymail?email=" +email 25 | return this.httpClient.get>(newPath) 26 | } 27 | 28 | getCustomerByUserId(id:number):Observable>{ 29 | let newPath = this.apiUrl + "customers/getbyuserid?id=" +id 30 | return this.httpClient.get>(newPath) 31 | } 32 | 33 | update(user:User):Observable{ 34 | return this.httpClient.post(this.apiUrl +"users/update",user) 35 | } 36 | 37 | addFindexById(userId:number){ 38 | 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | jasmine: { 17 | // you can add configuration options for Jasmine here 18 | // the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html 19 | // for example, you can disable the random execution with `random: false` 20 | // or set a specific seed with `seed: 4321` 21 | }, 22 | clearContext: false // leave Jasmine Spec Runner output visible in browser 23 | }, 24 | jasmineHtmlReporter: { 25 | suppressAll: true // removes the duplicated traces 26 | }, 27 | coverageReporter: { 28 | dir: require('path').join(__dirname, './coverage/rentacar'), 29 | subdir: '.', 30 | reporters: [ 31 | { type: 'html' }, 32 | { type: 'text-summary' } 33 | ] 34 | }, 35 | reporters: ['progress', 'kjhtml'], 36 | port: 9876, 37 | colors: true, 38 | logLevel: config.LOG_INFO, 39 | autoWatch: true, 40 | browsers: ['Chrome'], 41 | singleRun: false, 42 | restartOnFileChange: true 43 | }); 44 | }; 45 | -------------------------------------------------------------------------------- /src/app/components/car/car.component.html: -------------------------------------------------------------------------------- 1 |
2 | Loading... 3 |
4 | 5 | 20 | 21 | 22 |
23 |
Tüm Araçlar
24 | 30 | 38 | 41 |
42 |
43 | -------------------------------------------------------------------------------- /src/app/services/rental.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import {HttpClient} from '@angular/common/http' 3 | import { Observable } from 'rxjs'; 4 | import { ListResponseModel } from '../models/listResponseModel'; 5 | import { RentalDetail } from '../models/rentalDetail'; 6 | import { Rental } from '../models/rental'; 7 | import { ResponseModel } from '../models/responseModel'; 8 | 9 | @Injectable({ 10 | providedIn: 'root' 11 | }) 12 | export class RentalService { 13 | 14 | rentingCar:Rental 15 | apiUrl="https://localhost:44378/api/rentals/" 16 | 17 | constructor(private httpClient:HttpClient) { } 18 | 19 | 20 | getRentals():Observable>{ 21 | let newPath = this.apiUrl + "getrentaldetails" 22 | return this.httpClient.get>(newPath) 23 | } 24 | 25 | getRentalByCarId(carId:number):Observable>{ 26 | let newPath = this.apiUrl + "getrentalbycarid?id="+carId 27 | return this.httpClient.get>(newPath) 28 | } 29 | getRentalDetailsByCarId(carId:number):Observable>{ 30 | let newPath = this.apiUrl + "getrentaldetailsbycarid?id="+carId 31 | return this.httpClient.get>(newPath) 32 | } 33 | 34 | setRentingCar(rental: Rental) { 35 | this.rentingCar = rental; 36 | } 37 | 38 | getRentingCar() { 39 | return this.rentingCar; 40 | } 41 | 42 | removeRentingCar() { 43 | this.rentingCar == null 44 | } 45 | 46 | add(rental: Rental):Observable{ 47 | let newPath = this.apiUrl + "add" 48 | return this.httpClient.post(newPath, rental); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/app/components/brand-color/brand-color.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute, Router } from '@angular/router'; 3 | import { ToastrService } from 'ngx-toastr'; 4 | import { Brand } from 'src/app/models/brand'; 5 | import { Color } from 'src/app/models/color'; 6 | import { BrandService } from 'src/app/services/brand.service'; 7 | import { ColorService } from 'src/app/services/color.service'; 8 | 9 | @Component({ 10 | selector: 'app-brand-color', 11 | templateUrl: './brand-color.component.html', 12 | styleUrls: ['./brand-color.component.css'], 13 | }) 14 | export class BrandColorComponent implements OnInit { 15 | 16 | brands: Brand[]; 17 | colors: Color[]; 18 | 19 | brandId: Number; 20 | brandFilterText: string 21 | colorId: Number; 22 | colorFilterText: string; 23 | 24 | 25 | 26 | constructor( 27 | private brandService: BrandService, 28 | private colorService:ColorService, 29 | private router:Router, 30 | private toastrService:ToastrService 31 | 32 | ) {} 33 | 34 | ngOnInit(): void { 35 | this.colorAndBrandGetAll(); 36 | 37 | } 38 | 39 | colorAndBrandGetAll() { 40 | this.colorService.getColors().subscribe(response => { 41 | this.colors = response.data; 42 | }) 43 | this.brandService.getBrands().subscribe(response => { 44 | this.brands = response.data; 45 | }) 46 | } 47 | 48 | getSelectedBrand(brandId: Number) { 49 | if (this.brandId == brandId) { 50 | return true; 51 | } 52 | else { 53 | return false; 54 | } 55 | } 56 | 57 | getSelectedColor(colorId: Number) { 58 | if (this.colorId == colorId) { 59 | return true; 60 | } 61 | else { 62 | return false; 63 | } 64 | } 65 | 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/app/components/add_operations/color-add/color-add.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
Araç Renk Ekle
6 |
7 |
8 |
9 |
10 | 13 |
14 | 15 |
16 |
17 | 20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
Araç Renk Güncelle
30 |
31 |
32 |
33 | 34 |
35 | 38 |
39 | 40 |
41 | 44 |
45 | 46 |
47 |
48 | 51 |
52 |
53 |
54 | -------------------------------------------------------------------------------- /src/app/components/add_operations/brand-add/brand-add.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
Araç Marka Ekle
6 |
7 |
8 |
9 |
10 | 13 |
14 | 15 |
16 |
17 | 20 |
21 |
22 |
23 | 24 |
25 |
26 | 27 |
28 |
29 |
30 |
31 |
Araç Marka Güncelle
32 |
33 |
34 |
35 | 36 |
37 | 40 |
41 | 42 |
43 | 46 |
47 | 48 |
49 |
50 | 53 |
54 |
55 |
56 | -------------------------------------------------------------------------------- /src/app/components/register/register.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 |

Kayıt ol

5 | 6 |
7 | 14 | 15 |
16 | 17 |
18 | 25 | 26 |
27 | 28 |
29 | 36 | 37 |
38 | 39 | 40 |
41 | 48 | 49 |
50 | 51 |
52 | 53 | 54 | 57 |

© 2017–2021

58 |
59 |
60 | 61 | -------------------------------------------------------------------------------- /src/app/services/cardetail.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable } from '@angular/core'; 2 | import {HttpClient} from '@angular/common/http' 3 | import { Observable } from 'rxjs'; 4 | import { ListResponseModel } from '../models/listResponseModel'; 5 | import { CarDetail } from '../models/cardetail'; 6 | import { ResponseModel } from '../models/responseModel'; 7 | 8 | @Injectable({ 9 | providedIn: 'root' 10 | }) 11 | export class CardetailService { 12 | 13 | 14 | apiUrl="https://localhost:44378/api/" 15 | 16 | constructor(private httpClient:HttpClient) { } 17 | 18 | getCarDetails():Observable>{ 19 | let newPath = this.apiUrl + "cars/getcardetails" 20 | return this.httpClient.get>(newPath) 21 | } 22 | 23 | getCarDetailsByBrandId(brandId:number):Observable>{ 24 | let newPath=this.apiUrl+"cars/getcarbybrandid?id="+brandId 25 | return this.httpClient.get>(newPath) 26 | } 27 | 28 | getCarDetailsByColorId(colorId:number):Observable>{ 29 | let newPath=this.apiUrl+"cars/getcarbycolorid?id="+colorId 30 | return this.httpClient.get>(newPath) 31 | } 32 | 33 | getCarByCarId(carId:number):Observable>{ 34 | let newPath=this.apiUrl+"cars/getcarbycarid?id="+carId 35 | return this.httpClient.get>(newPath) 36 | } 37 | 38 | getCarDetailsFiltered(brandId:number,colorId:number):Observable>{ 39 | let newPath = this.apiUrl+"cars/getcardetailsfiltered?id="+brandId+"&id2="+colorId 40 | return this.httpClient.get>(newPath) 41 | } 42 | 43 | add(car:CarDetail):Observable{ 44 | return this.httpClient.post(this.apiUrl +"cars/add",car) 45 | } 46 | 47 | update(car:CarDetail):Observable{ 48 | return this.httpClient.post(this.apiUrl +"cars/update",car) 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/app/components/login/login.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormGroup,FormControl,Validators,FormBuilder} from "@angular/forms"; 3 | import { Router } from '@angular/router'; 4 | import { ToastrService } from 'ngx-toastr'; 5 | import { AuthService } from 'src/app/services/auth.service'; 6 | import { CustomerService } from 'src/app/services/customer.service'; 7 | import { LocalStorageService } from 'src/app/services/local-storage.service'; 8 | 9 | @Component({ 10 | selector: 'app-login', 11 | templateUrl: './login.component.html', 12 | styleUrls: ['./login.component.css'] 13 | }) 14 | export class LoginComponent implements OnInit { 15 | 16 | loginForm:FormGroup; 17 | constructor(private formBuilder:FormBuilder, 18 | private authService:AuthService, 19 | private toastrService:ToastrService, 20 | private customerService:CustomerService, 21 | private localStorageService:LocalStorageService, 22 | private router:Router 23 | ) { } 24 | 25 | ngOnInit(): void { 26 | this.createLoginForm(); 27 | } 28 | 29 | createLoginForm(){ 30 | this.loginForm=this.formBuilder.group({ 31 | email: ["",Validators.required], 32 | password:["",Validators.required] 33 | }) 34 | } 35 | 36 | login(){ 37 | if(this.loginForm.valid){ 38 | let loginModel = Object.assign({},this.loginForm.value) 39 | console.log(loginModel) 40 | this.authService.login(loginModel).subscribe(response=>{ 41 | this.setIdToLocalStorage(loginModel.email) 42 | this.toastrService.info(response.message,"Ana sayfaya yönlendiriliyorsunuz.") 43 | this.localStorageService.setItem("token",response.data.token) 44 | this.router.navigate(["cars"]) 45 | 46 | }, responseError=>{ 47 | this.toastrService.error(responseError.error,"Tekrar deneyin.") 48 | }) 49 | 50 | }else{ 51 | this.toastrService.error("Lütfen bilgileri eksiksiz giriniz") 52 | } 53 | 54 | } 55 | 56 | 57 | setIdToLocalStorage(email:string){ 58 | this.customerService.getCustomerWithMail(email).subscribe(response=>{ 59 | console.log(response.data) 60 | this.localStorageService.setItem("id",(response.data[0].userId).toString()) 61 | }) 62 | } 63 | 64 | 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/app/components/navi/navi.component.html: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app/components/customer/customer-update/customer-update/customer-update.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import {FormGroup,FormBuilder,Validators} from "@angular/forms"; 3 | import { ToastrService } from 'ngx-toastr'; 4 | import { CustomerService } from 'src/app/services/customer.service'; 5 | import { LocalStorageService } from 'src/app/services/local-storage.service'; 6 | 7 | @Component({ 8 | selector: 'app-customer-update', 9 | templateUrl: './customer-update.component.html', 10 | styleUrls: ['./customer-update.component.css'] 11 | }) 12 | export class CustomerUpdateComponent implements OnInit { 13 | 14 | customerUpdateForm: FormGroup 15 | id2 =Number(this.localStorageService.getItem('id')) 16 | 17 | constructor( 18 | private formBuilder:FormBuilder, 19 | private customerService:CustomerService, 20 | private toastrService:ToastrService, 21 | private localStorageService:LocalStorageService) { } 22 | 23 | ngOnInit(): void { 24 | this.createCustomerUpdateForm(); 25 | } 26 | 27 | createCustomerUpdateForm() { 28 | 29 | this.customerUpdateForm = this.formBuilder.group({ 30 | id:[this.id2,Validators.required], 31 | firstName: ['', Validators.required], 32 | lastName: ['', Validators.required], 33 | email: ['', Validators.required], 34 | password: ['', Validators.required], 35 | 36 | }); 37 | } 38 | 39 | update() { 40 | if (this.customerUpdateForm.valid) { 41 | let customerModel = Object.assign({}, this.customerUpdateForm.value); 42 | this.customerService.update(customerModel).subscribe( 43 | (response) => { 44 | this.toastrService.success(response.message, 'Başarılı'); 45 | }, 46 | (responseError) => { 47 | if (responseError.error.ValidationErrors.length > 0) { 48 | for ( 49 | let i = 0; 50 | i < responseError.error.ValidationErrors.length; 51 | i++ 52 | ) { 53 | this.toastrService.error( 54 | responseError.error.ValidationErrors[i].ErrorMessage, 55 | 'Doğrulama Hatası' 56 | ); 57 | } 58 | } else { 59 | this.toastrService.error('Form eksik', 'Dikkat'); 60 | } 61 | } 62 | ); 63 | } 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/app/components/customer/customer-update/customer-update/customer-update.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
Profili Güncelle
6 |
7 |
8 |
9 | 10 |
11 | 12 |
13 | 20 |
21 |
22 | 23 |
24 | 25 |
26 | 33 |
34 |
35 | 36 |
37 | 38 |
39 | 46 |
47 |
48 | 49 |
50 | 51 |
52 | 59 |
60 |
61 | 62 |
63 |
64 | 67 |
68 |
69 |
70 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { RouterModule, Routes } from '@angular/router'; 3 | import { BrandAddComponent } from './components/add_operations/brand-add/brand-add.component'; 4 | import { CarAddComponent } from './components/add_operations/car-add/car-add.component'; 5 | import { ColorAddComponent } from './components/add_operations/color-add/color-add.component'; 6 | import { CardetailComponent } from './components/cardetail/cardetail.component'; 7 | import { CustomerUpdateComponent } from './components/customer/customer-update/customer-update/customer-update.component'; 8 | import { CustomerComponent } from './components/customer/customer.component'; 9 | import { LoginComponent } from './components/login/login.component'; 10 | import { OnecardetailComponent } from './components/onecardetail/onecardetail.component'; 11 | import { PaymentComponent } from './components/payment/payment.component'; 12 | import { RegisterComponent } from './components/register/register.component'; 13 | import { RentalComponent } from './components/rental/rental.component'; 14 | import { LoginGuard } from './guards/login.guard'; 15 | 16 | const routes: Routes = [ 17 | {path:"", pathMatch:"full",component:CardetailComponent}, 18 | {path:"cars",component:CardetailComponent}, 19 | {path:"cars/brands/:brandId", component:CardetailComponent}, 20 | {path:"cars/colors/:colorId", component:CardetailComponent}, 21 | {path:"cars/filter/:brandId/:colorId",component:CardetailComponent}, 22 | 23 | {path:"cars/:carId", component:OnecardetailComponent}, 24 | {path:"cars/details/:carId", component:OnecardetailComponent}, 25 | 26 | {path:"rental/:carId",component:RentalComponent}, 27 | {path:"cars/rental/:carId",component:RentalComponent}, 28 | 29 | {path:"payment/:rental",component: PaymentComponent}, 30 | 31 | {path:"car/add",component:CarAddComponent, canActivate:[LoginGuard]}, 32 | {path:"color/add", component:ColorAddComponent}, 33 | {path:"brand/add",component:BrandAddComponent}, 34 | 35 | {path:"login",component:LoginComponent}, 36 | {path:"register",component:RegisterComponent}, 37 | {path:"profile",component:CustomerComponent}, 38 | {path:"updateprofile",component:CustomerUpdateComponent} 39 | 40 | 41 | 42 | ]; 43 | 44 | @NgModule({ 45 | imports: [RouterModule.forRoot(routes)], 46 | exports: [RouterModule] 47 | }) 48 | export class AppRoutingModule { } 49 | -------------------------------------------------------------------------------- /src/app/components/register/register.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormGroup, FormControl, Validators, FormBuilder} from "@angular/forms"; 3 | import { Router } from '@angular/router'; 4 | import { ToastrService } from 'ngx-toastr'; 5 | import { Findex } from 'src/app/models/findex'; 6 | import { AuthService } from 'src/app/services/auth.service'; 7 | import { CustomerService } from 'src/app/services/customer.service'; 8 | import { FindexService } from 'src/app/services/findex.service'; 9 | import { LocalStorageService } from 'src/app/services/local-storage.service'; 10 | 11 | @Component({ 12 | selector: 'app-register', 13 | templateUrl: './register.component.html', 14 | styleUrls: ['./register.component.css'] 15 | }) 16 | export class RegisterComponent implements OnInit { 17 | 18 | 19 | registerForm:FormGroup; 20 | findex:Findex; 21 | 22 | constructor( 23 | private formBuilder:FormBuilder, 24 | private authService:AuthService, 25 | private toastrService:ToastrService, 26 | private router:Router, 27 | private findexService:FindexService, 28 | private localStorageService:LocalStorageService, 29 | private customerService:CustomerService 30 | ) { } 31 | 32 | ngOnInit(): void { 33 | this.createRegisterForm(); 34 | } 35 | 36 | createRegisterForm(){ 37 | this.registerForm=this.formBuilder.group({ 38 | firstName:["",Validators.required], 39 | lastName:["",Validators.required], 40 | email:["",Validators.required], 41 | password:["",Validators.required] 42 | }) 43 | } 44 | 45 | register(){ 46 | if(this.registerForm.valid){ 47 | let registerModel = Object.assign({}, this.registerForm.value) 48 | this.authService.register(registerModel).subscribe(response=>{ 49 | //this.setIdToLocalStorage(registerModel.email) 50 | //this.setFindexToZero(0) 51 | this.toastrService.info(response.message,"Giriş ekranına yönlendiriliyorsunuz") 52 | this.router.navigate(["login"]) 53 | 54 | },responseError=>{ 55 | this.toastrService.error(responseError.error,"Form eksik.") 56 | }) 57 | } 58 | } 59 | 60 | 61 | 62 | //---> Yeni kayıt olan birinin findex puanını otomatik 0 olarak veritabanına yollamak istedim. Bunu backend tarafında çok daha kolay yapabiliriz. 63 | // Sadece bir şeyler kurcaladım. 64 | // setIdToLocalStorage(email:string){ 65 | // this.customerService.getCustomerWithMail(email).subscribe(response=>{ 66 | // this.localStorageService.setItem("id",(response.data[0].userId).toString()) 67 | // }) 68 | // } 69 | 70 | // setFindexToZero(findexscore:number){ 71 | // this.findex={findexScore:findexscore, userId:Number(this.localStorageService.getItem('id'))} 72 | // this.findexService.add(this.findex).subscribe(response=>{ 73 | // this.toastrService.info("Findex puanınız 0","Dikkat") 74 | // },) 75 | // } 76 | 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/app/components/cardetail/cardetail.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { ToastrService } from 'ngx-toastr'; 4 | import { CarDetail } from 'src/app/models/cardetail'; 5 | import { RentalDetail } from 'src/app/models/rentalDetail'; 6 | import { CardetailService } from 'src/app/services/cardetail.service'; 7 | import { RentalService } from 'src/app/services/rental.service'; 8 | 9 | @Component({ 10 | selector: 'app-cardetail', 11 | templateUrl: './cardetail.component.html', 12 | styleUrls: ['./cardetail.component.css'] 13 | }) 14 | export class CardetailComponent implements OnInit { 15 | 16 | carDetails:CarDetail[]=[]; 17 | carImages:CarDetail[]=[]; 18 | car:CarDetail; 19 | rent:RentalDetail[]=[]; 20 | currentCar:CarDetail; 21 | 22 | imageBasePath="https://localhost:44378" 23 | dataLoaded=true; 24 | 25 | constructor(private cardetailService:CardetailService, 26 | private activatedRoute:ActivatedRoute, 27 | private toastrService:ToastrService, 28 | private rentalService:RentalService 29 | 30 | ) { } 31 | 32 | ngOnInit(): void { 33 | this.activatedRoute.params.subscribe(params=>{ 34 | if(params["brandId"] && params["colorId"]){ 35 | this.getCarDetailsFiltered(params["brandId"],params["colorId"]) 36 | } 37 | else if(params["brandId"]){ 38 | this.getCarDetailsByBrandId(params["brandId"]) 39 | }else if(params["colorId"]){ 40 | this.getCarDetailsByColorId(params["colorId"]) 41 | } 42 | else{ 43 | this.getCarDetails() 44 | } 45 | }) 46 | } 47 | 48 | 49 | getCarDetails(){ 50 | this.cardetailService.getCarDetails().subscribe(response=>{ 51 | this.carDetails=response.data 52 | this.dataLoaded=true; 53 | }) 54 | } 55 | 56 | getCarDetailsByBrandId(brandId:number){ 57 | this.cardetailService.getCarDetailsByBrandId(brandId).subscribe(response=>{ 58 | this.carDetails=response.data 59 | this.dataLoaded=true; 60 | }) 61 | } 62 | 63 | getCarDetailsByColorId(colorId:number){ 64 | this.cardetailService.getCarDetailsByColorId(colorId).subscribe(response=>{ 65 | this.carDetails=response.data 66 | this.dataLoaded=true; 67 | }) 68 | } 69 | 70 | 71 | getCarByCarId(carId:number){ 72 | this.cardetailService.getCarByCarId(carId).subscribe(response=>{ 73 | this.carDetails=response.data 74 | this.dataLoaded=true; 75 | }) 76 | } 77 | setCurrentCar(car:CarDetail){ 78 | this.currentCar=car; 79 | } 80 | 81 | getCarDetailsFiltered(brandId:number,colorId:number){ 82 | this.cardetailService.getCarDetailsFiltered(brandId,colorId).subscribe(response=>{ 83 | this.carDetails=response.data 84 | this.dataLoaded=true; 85 | if(!this.carDetails.length){ 86 | this.toastrService.warning("Araç mevcut değil","Dikkat") 87 | } 88 | }) 89 | } 90 | 91 | 92 | } 93 | -------------------------------------------------------------------------------- /src/app/components/add_operations/color-add/color-add.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import {FormGroup,FormBuilder,FormControl,Validators} from "@angular/forms" 3 | import { ToastrService } from 'ngx-toastr'; 4 | import { ColorService } from 'src/app/services/color.service'; 5 | 6 | @Component({ 7 | selector: 'app-color-add', 8 | templateUrl: './color-add.component.html', 9 | styleUrls: ['./color-add.component.css'] 10 | }) 11 | export class ColorAddComponent implements OnInit { 12 | 13 | colorAddForm:FormGroup; 14 | colorUpdateForm:FormGroup; 15 | 16 | 17 | constructor(private formBuilder:FormBuilder, 18 | private colorService:ColorService, 19 | private toastrService:ToastrService 20 | ) { } 21 | 22 | ngOnInit(): void { 23 | this.createColorAddForm(); 24 | this.createColorUpdateForm(); 25 | } 26 | 27 | createColorAddForm(){ 28 | this.colorAddForm=this.formBuilder.group({ 29 | name:["",Validators.required] 30 | }) 31 | } 32 | 33 | add() { 34 | if (this.colorAddForm.valid) { 35 | let colorModel = Object.assign({}, this.colorAddForm.value); 36 | this.colorService.add(colorModel).subscribe( 37 | (response) => { 38 | this.toastrService.success(response.message, 'Başarılı'); 39 | }, 40 | (responseError) => { 41 | if (responseError.error.ValidationErrors.length > 0) { 42 | for ( 43 | let i = 0; 44 | i < responseError.error.ValidationErrors.length; 45 | i++ 46 | ) { 47 | this.toastrService.error( 48 | responseError.error.ValidationErrors[i].ErrorMessage, 49 | 'Doğrulama hatası' 50 | ); 51 | } 52 | } 53 | } 54 | ); 55 | } else { 56 | this.toastrService.error('Form eksik', 'Dikkat'); 57 | } 58 | } 59 | 60 | createColorUpdateForm() { 61 | this.colorUpdateForm = this.formBuilder.group({ 62 | id: ['', Validators.required], 63 | name: ['', Validators.required], 64 | }); 65 | } 66 | 67 | update() { 68 | if (this.colorUpdateForm.valid) { 69 | let brandModel = Object.assign({}, this.colorUpdateForm.value); 70 | this.colorService.update(brandModel).subscribe( 71 | (response) => { 72 | this.toastrService.success(response.message, 'Başarılı'); 73 | }, 74 | (responseError) => { 75 | if (responseError.error.ValidationErrors.length > 0) { 76 | for ( 77 | let i = 0; 78 | i < responseError.error.ValidationErrors.length; 79 | i++ 80 | ) { 81 | this.toastrService.error( 82 | responseError.error.ValidationErrors[i].ErrorMessage, 83 | 'Doğrulama Hatası' 84 | ); 85 | } 86 | } else { 87 | this.toastrService.error('Form eksik', 'Dikkat'); 88 | } 89 | } 90 | ); 91 | } 92 | } 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/app/components/add_operations/brand-add/brand-add.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { 3 | FormGroup, 4 | FormBuilder, 5 | FormControl, 6 | Validators, 7 | } from '@angular/forms'; 8 | import { ToastrService } from 'ngx-toastr'; 9 | import { BrandService } from 'src/app/services/brand.service'; 10 | 11 | @Component({ 12 | selector: 'app-brand-add', 13 | templateUrl: './brand-add.component.html', 14 | styleUrls: ['./brand-add.component.css'], 15 | }) 16 | export class BrandAddComponent implements OnInit { 17 | brandAddForm: FormGroup; 18 | brandUpdateForm: FormGroup; 19 | 20 | constructor( 21 | private formBuilder: FormBuilder, 22 | private brandService: BrandService, 23 | private toastrService: ToastrService 24 | ) {} 25 | 26 | ngOnInit(): void { 27 | this.createBrandAddForm(); 28 | this.createBrandUpdateForm(); 29 | } 30 | 31 | createBrandAddForm() { 32 | this.brandAddForm = this.formBuilder.group({ 33 | name: ['', Validators.required], 34 | }); 35 | } 36 | 37 | add() { 38 | if (this.brandAddForm.valid) { 39 | let brandModel = Object.assign({}, this.brandAddForm.value); 40 | this.brandService.add(brandModel).subscribe( 41 | (response) => { 42 | this.toastrService.success(response.message, 'Başarılı'); 43 | }, 44 | (responseError) => { 45 | if (responseError.error.ValidationErrors.length > 0) { 46 | for ( 47 | let i = 0; 48 | i < responseError.error.ValidationErrors.length; 49 | i++ 50 | ) { 51 | this.toastrService.error( 52 | responseError.error.ValidationErrors[i].ErrorMessage, 53 | 'Doğrulama hatası' 54 | ); 55 | } 56 | } 57 | } 58 | ); 59 | } else { 60 | this.toastrService.error('Form eksik', 'Dikkat'); 61 | } 62 | } 63 | 64 | createBrandUpdateForm() { 65 | this.brandUpdateForm = this.formBuilder.group({ 66 | id: ['', Validators.required], 67 | name: ['', Validators.required], 68 | }); 69 | } 70 | 71 | update() { 72 | if (this.brandUpdateForm.valid) { 73 | let brandModel = Object.assign({}, this.brandUpdateForm.value); 74 | this.brandService.update(brandModel).subscribe( 75 | (response) => { 76 | this.toastrService.success(response.message, 'Başarılı'); 77 | }, 78 | (responseError) => { 79 | if (responseError.error.ValidationErrors.length > 0) { 80 | for ( 81 | let i = 0; 82 | i < responseError.error.ValidationErrors.length; 83 | i++ 84 | ) { 85 | this.toastrService.error( 86 | responseError.error.ValidationErrors[i].ErrorMessage, 87 | 'Doğrulama Hatası' 88 | ); 89 | } 90 | } else { 91 | this.toastrService.error('Form eksik', 'Dikkat'); 92 | } 93 | } 94 | ); 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** 22 | * IE11 requires the following for NgClass support on SVG elements 23 | */ 24 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 25 | 26 | /** 27 | * Web Animations `@angular/platform-browser/animations` 28 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 29 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 30 | */ 31 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 32 | 33 | /** 34 | * By default, zone.js will patch all possible macroTask and DomEvents 35 | * user can disable parts of macroTask/DomEvents patch by setting following flags 36 | * because those flags need to be set before `zone.js` being loaded, and webpack 37 | * will put import in the top of bundle, so user need to create a separate file 38 | * in this directory (for example: zone-flags.ts), and put the following flags 39 | * into that file, and then add the following code before importing zone.js. 40 | * import './zone-flags'; 41 | * 42 | * The flags allowed in zone-flags.ts are listed here. 43 | * 44 | * The following flags will work for all browsers. 45 | * 46 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 47 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 48 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 49 | * 50 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 51 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 52 | * 53 | * (window as any).__Zone_enable_cross_context_check = true; 54 | * 55 | */ 56 | 57 | /*************************************************************************************************** 58 | * Zone JS is required by default for Angular itself. 59 | */ 60 | import 'zone.js/dist/zone'; // Included with Angular CLI. 61 | 62 | 63 | /*************************************************************************************************** 64 | * APPLICATION IMPORTS 65 | */ 66 | -------------------------------------------------------------------------------- /src/app/components/onecardetail/onecardetail.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { ToastrService } from 'ngx-toastr'; 4 | import { CarDetail } from 'src/app/models/cardetail'; 5 | import { CustomerDetail } from 'src/app/models/customerDetail'; 6 | import { Findex } from 'src/app/models/findex'; 7 | import { RentalDetail } from 'src/app/models/rentalDetail'; 8 | import { AuthService } from 'src/app/services/auth.service'; 9 | import { CardetailService } from 'src/app/services/cardetail.service'; 10 | import { CustomerService } from 'src/app/services/customer.service'; 11 | import { FindexService } from 'src/app/services/findex.service'; 12 | import { LocalStorageService } from 'src/app/services/local-storage.service'; 13 | import { RentalService } from 'src/app/services/rental.service'; 14 | 15 | @Component({ 16 | selector: 'app-onecardetail', 17 | templateUrl: './onecardetail.component.html', 18 | styleUrls: ['./onecardetail.component.css'], 19 | }) 20 | export class OnecardetailComponent implements OnInit { 21 | constructor( 22 | private cardetailService: CardetailService, 23 | private activatedRoute: ActivatedRoute, 24 | private customerService: CustomerService, 25 | private localStorageService: LocalStorageService, 26 | private toastrService:ToastrService, 27 | private authService:AuthService 28 | ) {} 29 | 30 | cars: CarDetail[] = []; 31 | rental: RentalDetail[]; 32 | findex: Findex[] = []; 33 | user: CustomerDetail[]=[] 34 | dataLoaded = false; 35 | dataLoaded2 = false; 36 | imageBasePath = 'https://localhost:44378'; 37 | 38 | ngOnInit(): void { 39 | this.activatedRoute.params.subscribe((params) => { 40 | if (params['carId']) { 41 | this.getCarByCarId(params['carId']); 42 | this.getUsersById(); 43 | } else { 44 | this.getCarDetails(); 45 | } 46 | }); 47 | } 48 | 49 | getCarDetails() { 50 | this.cardetailService.getCarDetails().subscribe((response) => { 51 | this.cars = response.data; 52 | this.dataLoaded = true; 53 | }); 54 | } 55 | 56 | getCarByCarId(carId: number) { 57 | this.cardetailService.getCarByCarId(carId).subscribe((response) => { 58 | this.cars = response.data; 59 | this.dataLoaded = true; 60 | }); 61 | } 62 | checkLogin():boolean{ 63 | return this.authService.isAuthenticated(); 64 | } 65 | 66 | isCarRentable() { 67 | if(this.checkLogin()==true){ 68 | if (this.cars[0].minFindex <= this.user[0].findexScore) { 69 | 70 | this.dataLoaded2 = true; 71 | this.toastrService.info("Findex uygun","Tarih Seçiniz") 72 | return true; 73 | } 74 | this.toastrService.warning("Findex puanınız yeterli değil","Başka araç deneyiniz") 75 | return false; 76 | }else{ 77 | this.toastrService.warning("Lütfen Giriş yapınız", "Dikkat") 78 | return false; 79 | } 80 | 81 | } 82 | getUsersById() { 83 | this.customerService 84 | .getCustomerByUserId(Number(this.localStorageService.getItem('id'))) 85 | .subscribe((response) => { 86 | this.user = response.data; 87 | }); 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { BrowserModule } from '@angular/platform-browser'; 3 | import {HttpClientModule, HTTP_INTERCEPTORS} from '@angular/common/http' 4 | import {FormsModule, ReactiveFormsModule } from '@angular/forms' 5 | import {BrowserAnimationsModule} from '@angular/platform-browser/animations' 6 | 7 | import { AppRoutingModule } from './app-routing.module'; 8 | import { AppComponent } from './app.component'; 9 | import { NaviComponent } from './components/navi/navi.component'; 10 | import { BrandComponent } from './components/brand/brand.component'; 11 | import { ColorComponent } from './components/color/color.component'; 12 | import { CustomerComponent } from './components/customer/customer.component'; 13 | import { RentalComponent } from './components/rental/rental.component'; 14 | import {CardetailComponent} from './components/cardetail/cardetail.component'; 15 | import { CarComponent } from './components/car/car.component'; 16 | import { OnecardetailComponent } from './components/onecardetail/onecardetail.component'; 17 | import { BrandFilterPipePipe } from './pipes/brand-filter-pipe.pipe'; 18 | import { ColorFilterPipePipe } from './pipes/color-filter-pipe.pipe'; 19 | import { CarFilterPipePipe } from './pipes/car-filter-pipe.pipe'; 20 | import { PaymentComponent } from './components/payment/payment.component'; 21 | 22 | import {ToastrModule} from "ngx-toastr" 23 | import { DatePipe } from '@angular/common'; 24 | import { CarAddComponent } from './components/add_operations/car-add/car-add.component'; 25 | import { BrandAddComponent } from './components/add_operations/brand-add/brand-add.component'; 26 | import { ColorAddComponent } from './components/add_operations/color-add/color-add.component'; 27 | import { LoginComponent } from './components/login/login.component'; 28 | import { AuthInterceptor } from './interceptors/auth.interceptor'; 29 | import { RegisterComponent } from './components/register/register.component'; 30 | import { BrandColorComponent } from './components/brand-color/brand-color.component'; 31 | import { CustomerUpdateComponent } from './components/customer/customer-update/customer-update/customer-update.component'; 32 | 33 | 34 | 35 | @NgModule({ 36 | declarations: [ 37 | AppComponent, 38 | NaviComponent, 39 | BrandComponent, 40 | ColorComponent, 41 | CustomerComponent, 42 | RentalComponent, 43 | CardetailComponent, 44 | CarComponent, 45 | OnecardetailComponent, 46 | BrandFilterPipePipe, 47 | ColorFilterPipePipe, 48 | CarFilterPipePipe, 49 | PaymentComponent, 50 | CarAddComponent, 51 | BrandAddComponent, 52 | ColorAddComponent, 53 | LoginComponent, 54 | RegisterComponent, 55 | BrandColorComponent, 56 | CustomerUpdateComponent, 57 | 58 | 59 | ], 60 | imports: [ 61 | BrowserModule, 62 | AppRoutingModule, 63 | HttpClientModule, 64 | FormsModule, 65 | BrowserAnimationsModule, 66 | ReactiveFormsModule, 67 | ToastrModule.forRoot({ 68 | positionClass:"toast-bottom-right" 69 | }) 70 | ], 71 | providers: [ 72 | {provide:HTTP_INTERCEPTORS, useClass:AuthInterceptor, multi:true}, 73 | DatePipe 74 | ], 75 | bootstrap: [AppComponent] 76 | }) 77 | export class AppModule { } 78 | -------------------------------------------------------------------------------- /src/app/components/add_operations/car-add/car-add.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { 3 | FormGroup, 4 | FormBuilder, 5 | FormControl, 6 | Validators, 7 | } from '@angular/forms'; 8 | import { ToastrService } from 'ngx-toastr'; 9 | import { CardetailService } from 'src/app/services/cardetail.service'; 10 | 11 | @Component({ 12 | selector: 'app-car-add', 13 | templateUrl: './car-add.component.html', 14 | styleUrls: ['./car-add.component.css'], 15 | }) 16 | export class CarAddComponent implements OnInit { 17 | carAddForm: FormGroup; 18 | carUpdateForm: FormGroup; 19 | 20 | constructor( 21 | private formBuilder: FormBuilder, 22 | private carService: CardetailService, 23 | private toastrService: ToastrService 24 | ) {} 25 | 26 | ngOnInit(): void { 27 | this.createCarAddForm(); 28 | this.createCarUpdateForm(); 29 | } 30 | 31 | createCarAddForm() { 32 | this.carAddForm = this.formBuilder.group({ 33 | brandId: ['', Validators.required], 34 | carName: ['', Validators.required], 35 | colorId: ['', Validators.required], 36 | modelYear: ['', Validators.required], 37 | dailyPrice: ['', Validators.required], 38 | description: ['', Validators.required], 39 | minFindex:["",Validators.required] 40 | }); 41 | } 42 | 43 | add() { 44 | if (this.carAddForm.valid) { 45 | let carModel = Object.assign({}, this.carAddForm.value); 46 | this.carService.add(carModel).subscribe( 47 | (response) => { 48 | this.toastrService.success(response.message, 'Başarılı'); 49 | }, 50 | (responseError) => { 51 | if (responseError.error.ValidationErrors.length > 0) { 52 | for ( 53 | let i = 0; 54 | i < responseError.error.ValidationErrors.length; 55 | i++ 56 | ) { 57 | this.toastrService.error( 58 | responseError.error.ValidationErrors[i].ErrorMessage, 59 | 'Doğrulama hatası' 60 | ); 61 | } 62 | } else { 63 | this.toastrService.error('Form eksik', 'Dikkat'); 64 | } 65 | } 66 | ); 67 | } 68 | } 69 | 70 | createCarUpdateForm() { 71 | this.carUpdateForm = this.formBuilder.group({ 72 | id: ['', Validators.required], 73 | brandId: ['', Validators.required], 74 | carName: ['', Validators.required], 75 | colorId: ['', Validators.required], 76 | modelYear: ['', Validators.required], 77 | dailyPrice: ['', Validators.required], 78 | description: ['', Validators.required], 79 | }); 80 | } 81 | 82 | update() { 83 | if (this.carUpdateForm.valid) { 84 | let brandModel = Object.assign({}, this.carUpdateForm.value); 85 | this.carService.update(brandModel).subscribe( 86 | (response) => { 87 | this.toastrService.success(response.message, 'Başarılı'); 88 | }, 89 | (responseError) => { 90 | if (responseError.error.ValidationErrors.length > 0) { 91 | for ( 92 | let i = 0; 93 | i < responseError.error.ValidationErrors.length; 94 | i++ 95 | ) { 96 | this.toastrService.error( 97 | responseError.error.ValidationErrors[i].ErrorMessage, 98 | 'Doğrulama Hatası' 99 | ); 100 | } 101 | } else { 102 | this.toastrService.error('Form eksik', 'Dikkat'); 103 | } 104 | } 105 | ); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /src/app/components/rental/rental.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit } from '@angular/core'; 2 | import { FormBuilder, FormGroup, Validators } from '@angular/forms'; 3 | import { ActivatedRoute, Router } from '@angular/router'; 4 | import { ToastrService } from 'ngx-toastr'; 5 | import { Rental } from 'src/app/models/rental'; 6 | import { RentalDetail } from 'src/app/models/rentalDetail'; 7 | import { LocalStorageService } from 'src/app/services/local-storage.service'; 8 | import { RentalService } from 'src/app/services/rental.service'; 9 | 10 | @Component({ 11 | selector: 'app-rental', 12 | templateUrl: './rental.component.html', 13 | styleUrls: ['./rental.component.css'], 14 | }) 15 | export class RentalComponent implements OnInit { 16 | rentals: RentalDetail[] = []; 17 | dataLoaded = false; 18 | 19 | rental: Rental; 20 | rentalKey:Rental; 21 | carId: number; 22 | addRentCarForm: FormGroup; 23 | currentDate: Date = new Date(); 24 | id2 =Number(this.localStorageService.getItem('id')) 25 | 26 | constructor(private rentalService: RentalService, 27 | private formBuilder: FormBuilder, 28 | private activatedRoute: ActivatedRoute, 29 | private toastrService: ToastrService, 30 | private router: Router, 31 | private localStorageService:LocalStorageService 32 | ) {} 33 | 34 | ngOnInit(): void { 35 | this.carId=Number(this.activatedRoute.snapshot.paramMap.get('carId')); 36 | this.createAddRentCarForm(); 37 | 38 | } 39 | 40 | getRentals() { 41 | this.rentalService.getRentals().subscribe((response) => { 42 | this.rentals = response.data; 43 | this.dataLoaded = true; 44 | }); 45 | } 46 | 47 | createAddRentCarForm() { 48 | this.addRentCarForm = this.formBuilder.group({ 49 | carId: [this.carId, Validators.required], 50 | userId: [this.id2, Validators.required], 51 | rentDate: ['', [Validators.required]], 52 | returnDate: ['', Validators.required] 53 | }); 54 | } 55 | 56 | setRentingCar() { 57 | if (this.addRentCarForm.invalid) { 58 | this.toastrService.warning('Alanları kontrol ediniz', 'Dikkat'); 59 | return false; 60 | } 61 | 62 | this.rental = this.addRentCarForm.value; 63 | let rentDate = new Date(this.rental.rentDate); 64 | let returnDate = new Date(this.rental.returnDate); 65 | 66 | if (rentDate < this.currentDate) { 67 | this.toastrService.warning( 68 | 'Kiralama Tarihi, bu günden sonraki günler olmalıdır', 'Dikkat' 69 | ); 70 | return false; 71 | } 72 | 73 | if (returnDate < rentDate || returnDate.getDate() == rentDate.getDate()) { 74 | this.toastrService.warning( 75 | 'Dönüş Tarihi, kiralama tarihinden sonraki günler olmalıdır', 'Dikkat' 76 | ); 77 | return false; 78 | } 79 | 80 | this.rentalService.setRentingCar(this.rental); 81 | console.log(this.rental) 82 | 83 | this.toastrService.success('Ödeme sayfasına yönlendiriliyorsunuz'); 84 | return this.router.navigate(['payment/' + JSON.stringify(this.rental)]); 85 | 86 | } 87 | 88 | checkCarRentable() { 89 | this.rentalService.getRentalByCarId(this.carId).subscribe(responseSuccess => { 90 | 91 | if (responseSuccess.data[0] == null) { 92 | this.setRentingCar(); 93 | return true; 94 | } 95 | 96 | let lastItem = responseSuccess.data[responseSuccess.data.length - 1]; 97 | 98 | 99 | 100 | if (lastItem.returnDate == null ) { 101 | return this.toastrService.error('Bu araç henüz teslim edilmemiş'); 102 | } 103 | 104 | let returnDate = new Date(lastItem.returnDate); 105 | this.setRentingCar(); 106 | 107 | return true; 108 | }); 109 | } 110 | 111 | 112 | 113 | } 114 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rulesDirectory": [ 4 | "codelyzer" 5 | ], 6 | "rules": { 7 | "align": { 8 | "options": [ 9 | "parameters", 10 | "statements" 11 | ] 12 | }, 13 | "array-type": false, 14 | "arrow-return-shorthand": true, 15 | "curly": true, 16 | "deprecation": { 17 | "severity": "warning" 18 | }, 19 | "eofline": true, 20 | "import-blacklist": [ 21 | true, 22 | "rxjs/Rx" 23 | ], 24 | "import-spacing": true, 25 | "indent": { 26 | "options": [ 27 | "spaces" 28 | ] 29 | }, 30 | "max-classes-per-file": false, 31 | "max-line-length": [ 32 | true, 33 | 140 34 | ], 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-console": [ 47 | true, 48 | "debug", 49 | "info", 50 | "time", 51 | "timeEnd", 52 | "trace" 53 | ], 54 | "no-empty": false, 55 | "no-inferrable-types": [ 56 | true, 57 | "ignore-params" 58 | ], 59 | "no-non-null-assertion": true, 60 | "no-redundant-jsdoc": true, 61 | "no-switch-case-fall-through": true, 62 | "no-var-requires": false, 63 | "object-literal-key-quotes": [ 64 | true, 65 | "as-needed" 66 | ], 67 | "quotemark": [ 68 | true, 69 | "single" 70 | ], 71 | "semicolon": { 72 | "options": [ 73 | "always" 74 | ] 75 | }, 76 | "space-before-function-paren": { 77 | "options": { 78 | "anonymous": "never", 79 | "asyncArrow": "always", 80 | "constructor": "never", 81 | "method": "never", 82 | "named": "never" 83 | } 84 | }, 85 | "typedef": [ 86 | true, 87 | "call-signature" 88 | ], 89 | "typedef-whitespace": { 90 | "options": [ 91 | { 92 | "call-signature": "nospace", 93 | "index-signature": "nospace", 94 | "parameter": "nospace", 95 | "property-declaration": "nospace", 96 | "variable-declaration": "nospace" 97 | }, 98 | { 99 | "call-signature": "onespace", 100 | "index-signature": "onespace", 101 | "parameter": "onespace", 102 | "property-declaration": "onespace", 103 | "variable-declaration": "onespace" 104 | } 105 | ] 106 | }, 107 | "variable-name": { 108 | "options": [ 109 | "ban-keywords", 110 | "check-format", 111 | "allow-pascal-case" 112 | ] 113 | }, 114 | "whitespace": { 115 | "options": [ 116 | "check-branch", 117 | "check-decl", 118 | "check-operator", 119 | "check-separator", 120 | "check-type", 121 | "check-typecast" 122 | ] 123 | }, 124 | "component-class-suffix": true, 125 | "contextual-lifecycle": true, 126 | "directive-class-suffix": true, 127 | "no-conflicting-lifecycle": true, 128 | "no-host-metadata-property": true, 129 | "no-input-rename": true, 130 | "no-inputs-metadata-property": true, 131 | "no-output-native": true, 132 | "no-output-on-prefix": true, 133 | "no-output-rename": true, 134 | "no-outputs-metadata-property": true, 135 | "template-banana-in-box": true, 136 | "template-no-negated-async": true, 137 | "use-lifecycle-interface": true, 138 | "use-pipe-transform-interface": true, 139 | "directive-selector": [ 140 | true, 141 | "attribute", 142 | "app", 143 | "camelCase" 144 | ], 145 | "component-selector": [ 146 | true, 147 | "element", 148 | "app", 149 | "kebab-case" 150 | ] 151 | } 152 | } 153 | -------------------------------------------------------------------------------- /src/app/components/payment/payment.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
Kart Bilgileri
6 |
7 |
8 |
9 |
10 | 11 |
12 | 19 |
20 |
21 | 22 |
23 | 24 |
25 | 32 |
33 |
34 | 35 |
36 | 37 |
38 | 45 |
46 |
47 | 48 |
49 | 50 |
51 |
52 |
53 | 60 |
61 |
62 | 63 |
64 |
65 | 72 |
73 |
74 |
75 |
76 | 77 |
78 | 79 |
80 | 87 |
88 |
89 |
90 |
91 | 100 |
101 |
102 |
103 | 104 |
105 |
106 | 107 |
108 |
109 | 115 | 118 |
119 |
120 |
121 |
122 | 123 | 124 |
125 |
126 | 127 |
128 |
129 |
KartNo: {{card.cardNumber}}
130 |
Kayıtlı kişinin:
131 |

Ad:{{card.nameOnCard}} Soyad:{{card.lastNameOnCard}}

132 | Bu Kart ile öde 133 |
134 |
135 | 136 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "rentacar": { 7 | "projectType": "application", 8 | "schematics": { 9 | "@schematics/angular:application": { 10 | "strict": true 11 | } 12 | }, 13 | "root": "", 14 | "sourceRoot": "src", 15 | "prefix": "app", 16 | "architect": { 17 | "build": { 18 | "builder": "@angular-devkit/build-angular:browser", 19 | "options": { 20 | "outputPath": "dist/rentacar", 21 | "index": "src/index.html", 22 | "main": "src/main.ts", 23 | "polyfills": "src/polyfills.ts", 24 | "tsConfig": "tsconfig.app.json", 25 | "aot": true, 26 | "assets": [ 27 | "src/favicon.ico", 28 | "src/assets" 29 | ], 30 | "styles": [ 31 | "./node_modules/bootstrap/dist/css/bootstrap.min.css", 32 | "./node_modules/ngx-toastr/toastr.css", 33 | "src/styles.css" 34 | ], 35 | "scripts": [ 36 | "node_modules/jquery/dist/jquery.min.js", 37 | "node_modules/popper.js/dist/umd/popper.min.js", 38 | "node_modules/bootstrap/dist/js/bootstrap.min.js" 39 | ] 40 | }, 41 | "configurations": { 42 | "production": { 43 | "fileReplacements": [ 44 | { 45 | "replace": "src/environments/environment.ts", 46 | "with": "src/environments/environment.prod.ts" 47 | } 48 | ], 49 | "optimization": true, 50 | "outputHashing": "all", 51 | "sourceMap": false, 52 | "namedChunks": false, 53 | "extractLicenses": true, 54 | "vendorChunk": false, 55 | "buildOptimizer": true, 56 | "budgets": [ 57 | { 58 | "type": "initial", 59 | "maximumWarning": "500kb", 60 | "maximumError": "1mb" 61 | }, 62 | { 63 | "type": "anyComponentStyle", 64 | "maximumWarning": "2kb", 65 | "maximumError": "4kb" 66 | } 67 | ] 68 | } 69 | } 70 | }, 71 | "serve": { 72 | "builder": "@angular-devkit/build-angular:dev-server", 73 | "options": { 74 | "browserTarget": "rentacar:build" 75 | }, 76 | "configurations": { 77 | "production": { 78 | "browserTarget": "rentacar:build:production" 79 | } 80 | } 81 | }, 82 | "extract-i18n": { 83 | "builder": "@angular-devkit/build-angular:extract-i18n", 84 | "options": { 85 | "browserTarget": "rentacar:build" 86 | } 87 | }, 88 | "test": { 89 | "builder": "@angular-devkit/build-angular:karma", 90 | "options": { 91 | "main": "src/test.ts", 92 | "polyfills": "src/polyfills.ts", 93 | "tsConfig": "tsconfig.spec.json", 94 | "karmaConfig": "karma.conf.js", 95 | "assets": [ 96 | "src/favicon.ico", 97 | "src/assets" 98 | ], 99 | "styles": [ 100 | "src/styles.css" 101 | ], 102 | "scripts": [] 103 | } 104 | }, 105 | "lint": { 106 | "builder": "@angular-devkit/build-angular:tslint", 107 | "options": { 108 | "tsConfig": [ 109 | "tsconfig.app.json", 110 | "tsconfig.spec.json", 111 | "e2e/tsconfig.json" 112 | ], 113 | "exclude": [ 114 | "**/node_modules/**" 115 | ] 116 | } 117 | }, 118 | "e2e": { 119 | "builder": "@angular-devkit/build-angular:protractor", 120 | "options": { 121 | "protractorConfig": "e2e/protractor.conf.js", 122 | "devServerTarget": "rentacar:serve" 123 | }, 124 | "configurations": { 125 | "production": { 126 | "devServerTarget": "rentacar:serve:production" 127 | } 128 | } 129 | } 130 | } 131 | } 132 | }, 133 | "defaultProject": "rentacar" 134 | } 135 | -------------------------------------------------------------------------------- /src/app/components/payment/payment.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, OnInit, Input } from '@angular/core'; 2 | import { ToastrService } from 'ngx-toastr'; 3 | import { FakeCardService } from 'src/app/services/fake-card.service'; 4 | import { 5 | FormGroup, 6 | FormBuilder, 7 | Validators, 8 | } from '@angular/forms'; 9 | import { ActivatedRoute, Router } from '@angular/router'; 10 | import { LocalStorageService } from 'src/app/services/local-storage.service'; 11 | import { FakeCard } from 'src/app/models/fakeCard'; 12 | import { RentalService } from 'src/app/services/rental.service'; 13 | import { Rental } from 'src/app/models/rental'; 14 | import { CardetailService } from 'src/app/services/cardetail.service'; 15 | import { CarDetail } from 'src/app/models/cardetail'; 16 | 17 | @Component({ 18 | selector: 'app-payment', 19 | templateUrl: './payment.component.html', 20 | styleUrls: ['./payment.component.css'], 21 | }) 22 | export class PaymentComponent implements OnInit { 23 | paymentForm: FormGroup; 24 | userCards:FakeCard[]=[] 25 | rental:Rental 26 | card:FakeCard; 27 | amountOfPayment:number; 28 | carDetail:CarDetail; 29 | registeredCardCheck:boolean; 30 | id2 =Number(this.localStorageService.getItem('id')) 31 | 32 | constructor( 33 | private fakeCardService: FakeCardService, 34 | private toastrService: ToastrService, 35 | private formBuilder: FormBuilder, 36 | private router: Router, 37 | private rentalService:RentalService, 38 | private activatedRoute:ActivatedRoute, 39 | private localStorageService:LocalStorageService, 40 | private carDetailService:CardetailService 41 | ) {} 42 | 43 | ngOnInit(): void { 44 | this.activatedRoute.params.subscribe((params)=>{ 45 | if(params['rental']){ 46 | this.createPaymentForm(); 47 | this.rental=JSON.parse(params['rental']) 48 | console.log(this.rental) 49 | this.getCards(); 50 | this.getCarDetailsById(); 51 | this.paymentCalculator(); 52 | this.saveCard(); 53 | } 54 | }) 55 | 56 | } 57 | 58 | getCarDetailsById(){ 59 | this.carDetailService.getCarByCarId(this.rental.carId).subscribe(response=>{ 60 | this.carDetail=response.data[0] 61 | console.log(this.carDetail) 62 | this.paymentCalculator() 63 | console.log(this.amountOfPayment) 64 | }) 65 | } 66 | 67 | createPaymentForm() { 68 | this.paymentForm = this.formBuilder.group({ 69 | userId:[this.id2,Validators.required], 70 | cardNumber: ['', Validators.required], 71 | cardCVV: ['', Validators.required], 72 | nameOnCard: ['', Validators.required], 73 | lastNameOnCard:['', Validators.required], 74 | expirationDateMonth: ['', Validators.required], 75 | expirationDateYear: ['', Validators.required], 76 | }); 77 | } 78 | 79 | paymentCheck() { 80 | let paymentModel = Object.assign({}, this.paymentForm.value); 81 | console.log(paymentModel); 82 | this.fakeCardService.isCardExist(paymentModel).subscribe( 83 | (response) => { 84 | 85 | if(this.userCards[0].moneyInCard >= this.amountOfPayment){ 86 | this.userCards[0].moneyInCard=this.userCards[0].moneyInCard - this.amountOfPayment; 87 | this.toastrService.success("Ödeme alındı","Bakiye yeterli") 88 | this.toastrService.success('Ödeme Bilgileri Onaylandı','İşlem Başarılı'); 89 | this.addRental(); 90 | }else{ 91 | this.toastrService.error("Yeterli miktarda para yok","Dikkat") 92 | } 93 | }, 94 | (responseError) => { 95 | this.toastrService.error( 96 | 'Ödeme Bilgileri Onaylanmadı, Tekrar deneyin.', 97 | 'İşlem Başarısız' 98 | ); 99 | 100 | this.router.navigate(['payment/' + JSON.stringify(this.rental)]); 101 | } 102 | ); 103 | } 104 | 105 | getCards(){ 106 | this.fakeCardService.getCardByUserId(this.id2).subscribe(response=>{ 107 | this.userCards=response.data 108 | console.log(this.userCards) 109 | }) 110 | 111 | } 112 | 113 | addRental(){ 114 | 115 | this.rentalService.add(this.rental).subscribe(response=>{ 116 | this.toastrService.success(response.message,"Kira oluşturuldu") 117 | }) 118 | } 119 | 120 | paymentCalculator() { 121 | if (this.rental.returnDate != null) { 122 | var date1 = new Date(this.rental.returnDate); 123 | var date2 = new Date(this.rental.rentDate); 124 | var difference = date1.getTime() - date2.getTime(); 125 | 126 | var numberOfDays = Math.ceil(difference / (1000 * 3600 * 24)); 127 | 128 | this.amountOfPayment = numberOfDays * this.carDetail?.dailyPrice; 129 | console.log(this.amountOfPayment) 130 | } 131 | } 132 | 133 | 134 | registeredCard(event: any) { 135 | if (event.target.checked) { 136 | this.registeredCardCheck = true; 137 | } else { 138 | this.registeredCardCheck = false; 139 | } 140 | } 141 | 142 | saveCard(){ 143 | if(this.registeredCardCheck==true){ 144 | let cardModel = Object.assign({},this.paymentForm.value) 145 | this.fakeCardService.add(cardModel).subscribe(response=>{ 146 | this.toastrService.success("Eklendi") 147 | },(responseError=>{ 148 | this.toastrService.error("Kaydedilemedi") 149 | })) 150 | } 151 | } 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | } 161 | -------------------------------------------------------------------------------- /src/app/components/add_operations/car-add/car-add.component.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 |
Araç Ekle
6 |
7 |
8 |
9 | 10 |
11 | 12 |
13 | 20 |
21 |
22 | 23 |
24 | 25 |
26 | 33 |
34 |
35 | 36 |
37 | 38 |
39 | 46 |
47 |
48 | 49 |
50 | 51 |
52 | 59 |
60 |
61 | 62 |
63 | 64 |
65 | 72 |
73 |
74 | 75 |
76 | 77 |
78 | 85 |
86 |
87 | 88 |
89 | 90 |
91 | 98 |
99 |
100 | 101 | 102 |
103 |
104 | 107 |
108 |
109 |
110 | 111 | 112 |
113 |
114 |
115 | 116 | 117 |
118 |
119 |
120 |
121 |
Araç Güncelle
122 |
123 |
124 |
125 | 126 |
127 | 128 |
129 | 136 |
137 |
138 | 139 | 140 |
141 | 142 |
143 | 150 |
151 |
152 | 153 |
154 | 155 |
156 | 163 |
164 |
165 | 166 |
167 | 168 |
169 | 176 |
177 |
178 | 179 |
180 | 181 |
182 | 189 |
190 |
191 | 192 |
193 | 194 |
195 | 202 |
203 |
204 | 205 |
206 | 207 |
208 | 215 |
216 |
217 |
218 |
219 | 222 |
223 |
224 |
225 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular ile RentACar-Frontend 2 | ## :mag:Başlarken 3 | 4 | Web uygulamaları geliştirmek için kullandığımız, Google tarafından geliştirilen bir framework. 5 | 6 | + Visual Studio Code kullandık. 7 | + Nodejs 14.16.0 LTS kurulumu yaptık. 8 | + Angular cli kurulumu yaptık. (npm install -g @angular/cli) 9 | + Projemizi oluşturduk. 10 | + Bootstrap v5.0.0-beta3 kurduk. 11 | 12 | ## :scroll:Geliştirmeler 13 | 14 | ### 1. Veriler Api tarafından çekilmeye çalışıldı. 15 | 16 | **Hiçbir güzelleştirme olmadan sadece api'den veriler çekmeye çalışıldı. 17 | Sırasıyla markalar,renkler,müşteriler,arabalar,kiralamalar listelendi.** 18 | 19 | + Öncelikle çekmek istediğimiz veriler ve navbar için components klasörü oluşturuldu. 20 | daha sonra models ve services klasörü oluşturuldu. 21 | 22 | + Verileri çekmek için (sadece brand'i düşünürsek) 23 | 24 | *brand , brandResponseModel, responseModel* modelleri oluşturuldu. 25 | 26 | + Services klasörünün içinde 27 | *brandService* oluşturuldu. HttpClient import edildi.(hem servis için hem app-module içinde(HttpClientModule)) 28 | 29 | + Servis içerisinde apiUrl yolu belli edilerek *getBrands()* yazıldı. 30 | 31 | + brandComponent'te servis private tanımlanarak *getBrands()* çağırılıp subscribe olundu. 32 | html'de bir ngFor ile basit şekilde veriler gösteriliyor mu test edildi. 33 | 34 | app.component.html'de yazılan 35 | 36 |
37 | 38 |
39 |
40 | 41 |
42 | 43 |
44 |
45 | 46 |
47 |
48 |
49 |
50 | 51 |
52 |
53 | 54 |
55 |
56 |
57 | 58 | 59 | 60 | şeklinde bir html'in nasıl yerler kaplayacağını belli etmek için bütün app'ler farklı renklendirildi. Bu renklendirme aşağıdaki şekilde: 61 | ![yenideneme](https://user-images.githubusercontent.com/77545922/112861095-27730480-90bd-11eb-8b1d-53e4a9c96f57.PNG) 62 | 63 | ### 2. Biraz Refactoring ve Resimlerin Getirilişi 64 | 65 | **NOT: appcomponent.html'de router-outlet --> bir tarayıcıda link tarafında ..../'tan sonra şu gelirse şuraya git diye belli ettiğimiz yer burası. 66 | Gideceği yerleri de app-routing.module'da belli ediyoruz.** 67 | 68 | + listResponseModel'lar oluşturulup diğer responseModel'lar silindi. 69 | 70 | + Sadece Brand için düşündüğümüz zaman brandcomponent.html için click event ve routeLink oluşturuldu. 71 | bunun için cardetailservice'e *getbybrandid()* yazıldı 72 | cardetailcomponent düzeltildi. 73 | 74 | + brand.component.html'de tüm araçlara basıldığında tüm araçların listelenmesi ve o butonun yanması için componente 75 | *resetCurrentBrand(), getAllCarsClass()* eklendi. 76 | 77 | Aynı işlemler color tarafında da gerçekleştirildi. 78 | 79 | Basit bir şekilde giriş gerçekleştirdiğimiz için(sadece test olarak düşünülebilir) adım adım ilerliyoruz. 80 | - Araç ve Color aynı anda seçildiğinde en son seçileni direkt gösteriyor ve diğer seçilen hala seçili gösteriyor. 81 | - Tüm araçlar veya tüm renkler'e basıldığında diğer component'in butonları resetlenmiyor. 82 | - Olmayan Renkler gösterilmeyecek. (Renklere çok takılmayın turuncu-yeşil gibi renkleri veritabanına rastgele doldurmuştum .:relieved:) 83 | 84 | ![yenideneme2brandlist](https://user-images.githubusercontent.com/77545922/112862241-3a3a0900-90be-11eb-8bed-a27be5c5b9c5.PNG) 85 | 86 | ### 2.1 Resimlerin getirilişi 87 | 88 | + Bu projede resim getirme işlemini de cardetailcomponent üzerinden yapacağım. Servis'e *getImages() ve 89 | getImagesById()* eklendi, 90 | carDetailComponent'e yazıldı. 91 | 92 | + Resimlerin gelip gelmediğini test etmek için öncelikle carcomponent içinde bir değişken cardetail.imagePath 93 | olarak denendi. ImagePath geliyordu. 94 | 95 | + Resimlerin gösterilip gösterilmediğini test etmek için 96 | cardetailcomponent.html'e aşağıdaki kodlar eklendi. 97 | 98 | thumbnail 100 | 101 | bu kod ile linkini koyduğunuz resmi basit bir şekilde gösterebilirsiniz. Detayları bootstrap'te var. 102 | 103 | + Bu kod ile componentimizde oluşturduğumuz carImages'i dönerek bütün resimleri getirmeye çalışıyoruz. 104 | 105 | 106 | ... 107 | 108 | 109 | ### :bangbang: Resimleri Getiremeyen Arkadaşlar İçin 110 | 111 | + Backend tarafında FileHelper'ı wwwroot'lu şekilde değiştirmeniz gerekiyor ve API tarafında wwwroot/images 112 | şeklinde kayıt olmalı resimleriniz. FileHelper'ı oluşturduktan sonra resimleri tekrar ekleyin. Backend tarafındaki filehelper'a bakabilirsiniz bunun için. 113 | Daha iyi anlayabilmeniz için bütün arabaların resimleri FileHelper'ı değiştirmeden önceki haliyle getirdim ve değiştirdikten 114 | sonra default bir RentACar logosu yükledim. 115 | ![yenideneme2resim](https://user-images.githubusercontent.com/77545922/112863247-52f6ee80-90bf-11eb-9b3c-a07a426224a1.PNG) 116 | 117 | + Ayrıca Api startup.cs tarafında app.UseHttpsRedirection(); 118 | altına app.UseStaticFiles(); eklemeyi unutmayın. 119 | 120 | + Düzenlenen veritabanından sonra araçlar düzensiz bir şekilde görseldeki gibi karşımıza geldi. 121 | Araçlarımızı aldığımıza göre şimdi bunları düzenlemesi kaldı. 122 | ![yenideneme2resim2](https://user-images.githubusercontent.com/77545922/112863443-89346e00-90bf-11eb-9f0f-6876dd9a7330.PNG) 123 | 124 | + Backend tarafında getcarDetails ile imagePath'i de alarak ek olarak oluşturduğum getCarImages ve getCarImagesById fonksiyonlarını 125 | sildim yerine cardetail component'ten bütün işlerime devam ettim. 126 | Sadece carcomponent.html tarafında bootstrap'ten basit bir card alarak src kısmına imagepath'i koydum. 127 | 128 | + Bütün veriler tamamlandıktan sonra appcomponent.html'den app-rental, app-customer'ı kaldırdım 129 | sadece app-brand, app-color ve router-outlet'i bıraktım. 130 | 131 | + Resimlerin boyutları farklı olduğu için bir kayma meydana geldi dengelemek için html'e 132 | width="100" height="200" eklendi. 133 | 134 | + Tasarım düzenlemeleri yapılmadan en basit sonuç aşağıdaki gibi oldu. 135 | ![yenideneme2resim3](https://user-images.githubusercontent.com/77545922/112863822-eaf4d800-90bf-11eb-889b-1079c596f4d1.PNG) 136 | 137 | + Araçları marka-renk olarak dışında tek tek tüm araçların gözükebilmesi için car component oluşturuldu. Araca direkt olarak tıklandığında istenilen aracın ekrana getirilmesini sağlamak amacımız. Bunun için ilk başta şöyle bir yol izledim. CarComponent'i oluşturdum. 138 | Backend tarafında getcarbycarid servisini, managerini,httpget işlemlerini yazdım. 139 | 140 | + İlk olarak düşündüğüm car'ı bir brand gibi düşünüp, tıklandığında cars/:carId routerlink'i verip 141 | carDetailComponent'e bağlanarak ekrana getirmekti. Bu tabii çalıştı, carDetailComponent tarafında bir elseif 142 | daha ekleyerek gayet düzgün çalıştı. Ancak sorun şu ki nasıl tüm araçları kart ile gösterdiysek burada da 1 kart gözüküyor ve tüm sayfa koca bir 143 | boşluk gibi gözüküyor aşağıdaki resimde örneği var. 144 | ![yenideneme2resim4](https://user-images.githubusercontent.com/77545922/112896964-b6951200-90e7-11eb-830f-e88fe32195c0.PNG) 145 | 146 | + Bunun için onecardetail diye bir component daha oluşturdum. Burada araca tıklandığında gidilecek yer olsun, 147 | bütün resimleri toplu şekilde gösterilebilsin, kira durumunu görebilsin diye yönlendireceğim ek sayfa olacak. 148 | Bootstrapten sadece büyük ortalı bir şekilde görülecek bir resim yapısı aldım ve altınada birkaç yazı ekleyerek 149 | basit bir görüntü ortaya çıkardım. 150 | ![yenideneme2resim5](https://user-images.githubusercontent.com/77545922/112897029-cb71a580-90e7-11eb-9815-f198d2405997.PNG) 151 | 152 | ### 3. Kiralama ve Ödeme işlemleri 153 | ### 3.1 154 | + Src-app-pipes oluşturuldu. 155 | 156 | Araç-renk-marka için ayrı ayrı pipelar yazıldı 157 | Araçlar MarkaAdı+AraçAdı şeklinde yazıldığı için pipe'da toplama işlemi yapıldı. 158 | 159 | + Pipe'dan daha sonra 160 | Html-selectoption ile car-brand ve color için marka, renk veya özel olarak tüm araçlar listesinden 161 | araç seçimi yapılabilmesi tanımlandı. Seçilen filtreye göre araç ekrana geliyor. 162 | 163 | + Pipe'lı halini comment haline getirdim. Hem search - hem select şeklinde yazabilirsiniz html'inizi 164 | ancak ben sadece select option ile yazdım. pipe filtresine sonradan ihtiyaç duymadım o yüzden. 165 | Arayüz biraz değiştirildi. 166 | 167 | + Açılır kutuların yanına filtrele ve filtreleri temizle butonları eklendi. 168 | filtrele ile özelliği seçilen araca filtreleri temizle ile anasayfaya dönüyor en basit şekilde. 169 | ***************************** 170 | ### 3.1.2 171 | + Detaya git butonu cardetailcomponent'te tamamlandı click event koyuldu routerlink 172 | onecardetail'e yönlendirildi 173 | onecardetailComponent içerisine kirala butonu tanımlandı. 174 | 175 | + npm install @angular/animations 176 | 177 | npm install ngx-toastr ile paketler kuruldu 178 | 179 | toastr angular.json'da tanımlandı 180 | app.module'da tanımlandı. 181 | 182 | Bu kurulan paketler ile kirala butonuna basıldığında sağ alttan bir bildirim getirilerek 183 | güzelleştirildi. 184 | ### 3.1.3 185 | ***************************** 186 | + Ancak önemli olan durum araç müsait mi sorgusunu gerçekleştirebilmek.Bunun için backend tarafında getrentalbycarid eklenmeli. 187 | 188 | GetRentalByCarId IRentalService'e 189 | 190 | IDataResult GetRentalByCarId(int carId); 191 | 192 | şeklinde eklendi. Detaylı bir bilgi almayacağımız için, işlemlerimizde returndate ve rentDate kullanacağımız için 193 | bu şekilde döndürdük verimizi. Bu işlemin manager'ını ve api controllerda httpget komutunu yazdık. 194 | 195 | + Bu servis eklendikten sonra backend tarafında rental.add işlemi için 196 | 197 | var result = _rentalDal.GetAll(r => r.CarId == rental.CarId && (r.ReturnDate == null || r.ReturnDate < DateTime.Now)).Any(); 198 | 199 | eklendi. 200 | 201 | + Frontend tarafında rentalcomponent.ts ve html [Yusuf Akkurt'un](https://github.com/YusufAkkurt/rent-a-car-front/tree/master/src/app) github'ından alındı. Yapılan işlem özet olarak arabanın müsaitliği kontrol ediliyor, müsaitse set edilip ödeme sayfasına yönlendiriliyor. 202 | 203 | Gidilecek sayfayı rentalcomponent.ts'de 204 | 205 | return this.router.navigate(['/cars']); 206 | 207 | şeklinde ödeme işlemi yönlendiriyorun altında belirtebilirsiniz. 208 | 209 | + Bu işlem biraz zorladı ancak arkadaşlardan baktığımda backend tarafında isRentable() şeklinde tanımlayıp frontend tarafında kullanmak da güzel bir seçenek gibi duruyor. Sevgili Yusuf pairde anlatarak yaptığı için 210 | bu yolu tercih ettim. 211 | ### 3.1.4 212 | ***************************** 213 | + Fake Banka servisini yazmak için 214 | backend tarafında FakeCard oluşturuldu. 215 | 216 | + Sırasıyla Entity-DataAccess-Business-API katmanları dolduruldu. 217 | + Çalışması için business-dependencyresolvers kısmında 218 | 219 | builder.RegisterType().As().SingleInstance(); 220 | builder.RegisterType().As().SingleInstance(); 221 | 222 | şeklinde çözmeyi unutmayın. 223 | 224 | Ayrıca kart eklemek için Fluentvalidation tarafında kurallarınızı eklemeyi unutmayın. En basit akla gelenkurallarım 225 | 226 | RuleFor(c => c.CardCVV).NotEmpty().MinimumLength(3); 227 | RuleFor(c => c.CardNumber).NotEmpty().MinimumLength(12); 228 | RuleFor(c => c.NameOnCard).NotEmpty(); 229 | RuleFor(c => c.MoneyInCard).GreaterThanOrEqualTo(0); 230 | şeklinde 231 | 232 | + SQL Tablosu oluşturuldu ve DbSet'ten tanımlandı 233 | postman'den kart eklendi. 234 | 235 | FakeCard kısmına UserId eklenip kullanıcıyla bağdaştırılabilir. Ancak şu an için basit bir servis denediğim için 236 | gerek duymadım. 237 | 238 | + Frontend tarafında fakeCard modeli-servisi component'i oluşturuldu 239 | component'i ve html'i yazıldı. 240 | 241 | ### Bu kısım beni biraz zorladı. İleriki zamanlarda buraya dönüp bakacağım şu an için eksikler şu şekilde: 242 | 243 | - Arayüz tasarımları tamamen eksik en son proje bittikten sonra bunlarla uğraşılacak. 244 | 245 | - Brand ve Color için aynı anda arama eklenmedi. Ama backend tarafında bir fonksiyon tanımlayarak bu kolayca yapılabilir. 246 | Kiralama ve ödeme ile çok uğraştığım için buna bakmadım ama artık ilerlemek istiyorum çok takıldım burada. 247 | 248 | - Kiralama menüsünde sadece tarih seçilecek 2 ekran getirildi. Aracın müsaitliğini kontrol etmek gibi bir durum. 249 | Burasıyla payment menüsü birleştirilebilir, araç müsaitliğini kontrol et gibi farklı bi şekilde bakış getirilebilir. 250 | Anasayfada listelenen her araca araç müsait mi butonu ekleyerek bir kontrol sağlanabilir. 251 | 252 | - Payment tarafında ise kart bilgilerinin doğruluğu kontrol ediliyor. Kart onaylandıktan sonra bir detaylar sayfası 253 | ve paranın eksileceği kısım tanımlanmadı 254 | 255 | Projenin bu kısmının Rent bölümünde yaptığı Pair ve paylaştığı kodlar için Yusuf Akkurt'a teşekkürler. 256 | 257 | ### 3.2 Resimler 258 | 259 | 3.1 Pipe'ların eklendiği kısım. 260 | ![yenideneme3](https://user-images.githubusercontent.com/77545922/113430805-78e40200-93e3-11eb-8ece-725388c5cb85.PNG) 261 | 262 | 3.1 Select-option eklendiği kısım. 263 | ![yenideneme3 1](https://user-images.githubusercontent.com/77545922/113430880-987b2a80-93e3-11eb-8dfe-c13f955371b7.PNG) 264 | 265 | 3.1.3 Kiralama sorgusu 266 | ![yenideneme3rental](https://user-images.githubusercontent.com/77545922/113430975-bba5da00-93e3-11eb-966c-69643bcca49f.PNG) 267 | 268 | 3.1.4 Ödeme İşlemi 269 | ![yenideneme3 5payment](https://user-images.githubusercontent.com/77545922/113479790-b30fdb00-9499-11eb-8d0f-43c7c480329f.PNG) 270 | 271 | ### 4.0 Araç-Renk-Marka Ekle, Güncelle İşlemleri 272 | 273 | - Öncelikle bu işlemler için 274 | Reactive Formlar kullanacağız 275 | FormsModule ve ReactiveFormsModule'ün import edilmesi gerekiyor. Payment tarafında da formlarla çalışmak için 276 | yapmıştık bu işlemi. 277 | 278 | 279 | **NOT :Bu kısımda araç marka ve renk için ekleme ve güncelleme işlemlerini sadece ayrı bir pathte test ettim. Login, register işlemleri de tamamlandıktan sonra bir yönetici sayfası oluşturup bu işlemleri sadece onlara özel kılmayı düşündüğüm için sadece ayrı bir path oluşturup işlemleri test ettim.** 280 | 281 | - Ekleme ve güncelleme işlemlerinin servisleri her nesnenin servisine yazıldı. 282 | 283 | - Components 284 | add-operations klasörü oluşturuldu. 285 | Car-add component'i oluşturuldu.(aynı işlemler brand ve color için de tekrar edildi.) 286 | 287 | - CarAddForm bir FormGroup olarak tanımlandı. Daha sonra bir createAddForm() oluşturularak Html'de form tarafından alınan inputları mapleyeceğimiz ve post ile göndereceğimiz verileri burada belirttik. Bunun veritabanınızdaki veriler şeklinde olması gerekiyor yoksa uyumsuzluk meydana gelir. Ayrıca veritabanında girilen ValidationRules tarafındaki kurallarınıza uymanız lazım ekleme işlemini yaparken. Benim Car nesnem için 288 | 289 | createCarAddForm() { 290 | this.carAddForm = this.formBuilder.group({ 291 | brandId: ['', Validators.required], 292 | carName: ['', Validators.required], 293 | colorId: ['', Validators.required], 294 | modelYear: ['', Validators.required], 295 | dailyPrice: ['', Validators.required], 296 | description: ['', Validators.required], 297 | }); 298 | } 299 | 300 | şeklinde. Devamında ise form düzgün doldurulmuş ve geçerli ise bunu bir model'e atayarak kodumuza devam ediyoruz. 301 | 302 | if (this.carAddForm.valid) { 303 | let carModel = Object.assign({}, this.carAddForm.value); 304 | 305 | Şeklinde devam eden kodta eğer bu şekildeyse ekleme işlemi gerçekleştiriliyor değilse form eksik uyarısı toastr ile gösteriliyor. 306 | 307 | - Aynı işlemler createCarUpdateForm() şeklinde tekrarlanıyor. Tek fark update tarafında CarId'nin ne olduğunun bilinmesi gerektiği için id de createCarUpdateForm()'a eklendi. 308 | ve update() fonksiyonu da yazıldı. 309 | 310 | - Her biri için app-routing-module tarafında pathler oluşturuldu. Pathlere manuel gidilerek işlemler test edildi. 311 | 312 | Bütün işlemler test edildi ve çalışır vaziyete geldi. 313 | 314 | ### 4.1 Resimler 315 | Resimler için oluşturulan path'te işlemlerin testi 316 | ![yenideneme4 1colorsaddupdate](https://user-images.githubusercontent.com/77545922/113812632-19854980-9777-11eb-9f1b-5c9cbf2daf13.PNG) 317 | 318 | 319 | 320 | ### 5.0 Login-Register-Payment-Findeks 321 | 322 | ### 5.1 Login ve Register İşlemleri. 323 | 324 | - Login işlemleri için login.component oluşturuldu. Giriş Ekranı için bootstrapten sign-in modeli alındı. Login path'i oluşturuldu. 325 | - Login kontrolünden geçtikten sonra login olan kişinin tanımlı kalabilmesi için authService oluşturuldu. 326 | login() ve isAuthenticated() işlemleri yazıldı. 327 | - LoginModel, tokenModel, singleResponseModel oluşturuldu. 328 | - Src-app-interceptors oluşturuldu. Auth-interceptor oluşturuldu. Interceptor'ın devreye girebilmesi için app-guards oluşturuldu. ve app-routing-module'a guard eklendi. 329 | - Register işlemleri için ise component'i oluşturulup, componentinde sadece bir Form oluşturup authService.register() ile yollandı. 330 | 331 | *********************************** 332 | 333 | ### 5.1.1 Findex 334 | 335 | - Öncelikle backend tarafında Car'a MinFindex tanımlandı. Database'de ise araçların minFindex değerleri girildi. 336 | - Frontend tarafında model'e minFindex eklendi, onecardetail'de minimum findex değeri gösterildi. 337 | 338 | Kullanıcı findexi oluşturmak ve kontrol edebilmek için ise 339 | - Backend tarafında sırasıyla findex entity-ifindexdal-effindexdal-ifindexservice-findexmanager oluşturuldu. Dependency resolvers'ta bağımlılığı çözüldü. 340 | - Sql tablosu oluşturuldu. UserId ile bağdaştırıldı. 341 | - RentACarContext'te DbSet'i belirtildi. 342 | - Api Controller'ı yazıldı. 343 | 344 | **Not: Frontend tarafında userName gibi diğer özelliklerle beraber findex puanını da çekmek için CustomerDetailDTO oluşturuldu. ICustomerDal-EfCustomerDal-Servis-Manager DTO için düzenlendi. Bu işlemden sonra postmanden verilerin istenildiği gibi gelip gelmediği kontrol edildi.** 345 | 346 | ![sondeneme1](https://user-images.githubusercontent.com/77545922/114316064-8cd9e300-9b0a-11eb-9ad5-278e3a3fd568.PNG) 347 | 348 | 349 | *********************************** 350 | 351 | - Frontend tarafında customerDetail, findex modeli oluşturuldu. Customerservice düzenlendi. 352 | 353 | **Burada önemli olan kullanıcı login olduğu zaman kullanıcının maili aracılığı ile userı set edebilmek. Örneğin kullanıcı login oldu localstorage'ta bir tokenı oluşuyor ancak benim kullanıcının findex puanını veya başka özellikleri alıp, componentlerde kullanmam lazım. Peki bunu nasıl yapacağım? Localstorageservis burada devreye giriyor.** 354 | 355 | - Localstorageservis oluşturuldu. Fonksiyonları yazıldı. 356 | - Oluşturduğumuz localstorageservis ile login ekranında getCustomerWithMail() fonksiyonu ile kullanıcının id'sini set ettik. 357 | - Önemli olan userId'ye ulaşmamızdı zaten. customerDetailComponent'imizde gerekli her şeyi oluşturmuştuk. Set 358 | ettiğimiz bu userId ile onecardetail kısmında önce bu id'yi getItem() ile aldık ve userId'nin findexScore'u ile aracın 359 | minFindex'ini karşılaştırdık. Böylece findex puanına göre kiralayabilme yetkisini vermiş olduk. 360 | 361 | **Not: Onecardetail'in html'inde isCarRentable() fonksiyonuna dataLoaded2=true diye tanımlama yaptım ve butonu "araç Müsait Mi?" olarak değiştirdim. Araç müsait mi butonuna basıldığında öncelikle findex puanı karşılaştırması yapılıyor. Bu karşılaştırmanın ardından eğer puan uygunsa rental component'te oluşturduğum tarih seçme ekranını altına getirdim. Araç müsait mi kontrolü için tarih seçimleri yapılıp sorgu yapılıyor.** 362 | 363 | | LocalStorage ID | Findex Sorgu | 364 | :---------------------:|:-------------------------: 365 | ![sondeneme2](https://user-images.githubusercontent.com/77545922/114316140-f9ed7880-9b0a-11eb-9783-8d8b87caa04c.PNG) | ![sondeneme3](https://user-images.githubusercontent.com/77545922/114316152-02de4a00-9b0b-11eb-8f43-18e8898485b7.PNG) 366 | 367 | 368 | *********************************** 369 | 370 | ### 5.1.2 Navbar 371 | 372 | - Navbar düzenlemesi için bootstrap'in examples bölümünde headerslardan örnek alarak yapabilirsiniz. Navbarda butonların yerleri düzenlendikten sonra html'de 373 | -- checkLogin() 374 | -- getUsersById() 375 | -- logout() tanımlandı. 376 | 377 | - Html'de checkLogin() navbarın görüntü sorgulayıcısı olarak kullanılacak. Eğer kullanıcı loginse ismi gözükecek ve ismine tıklandığında profil-çıkış yap butonları gelecek şekilde bir dropdown gelecek. Eğer login değilse giriş yap ve kayıt ol butonlarıyla navbar bizi karşılayacak. Navbar üzerinde Araçlar butonu hariç bütün butonlar sağlıklı çalışıyor. 378 | 379 | | LoggedIn | LoggedOut | 380 | :---------------------:|:-------------------------: 381 | ![sondenemenavbar](https://user-images.githubusercontent.com/77545922/114316431-3b325800-9b0c-11eb-9083-97a948beac5e.PNG) | ![sondenemenavbarlogout](https://user-images.githubusercontent.com/77545922/114316537-ac720b00-9b0c-11eb-9925-a4cf9e66da9e.PNG) 382 | 383 | 384 | *********************************** 385 | ### 5.1.3 Brand-Color 386 | 387 | Daha önceki işlemlerde es geçtiğim marka ve brand'i birlikte sorgulama işlemini burada tamamladım. 388 | 389 | - Backend tarafında carmanager'a getcardetailsfiltered() yazıldı. Api'ye eklendi. 390 | - Frontend tarafında cardetail.service'e eklendi. cardetail.component'e if koşuluyla beraber eklendi. 391 | - app-routing-module'da yolu belirtildi. 392 | - brand-color birlikte kontrolü için component'i oluşturuldu. 393 | - app.component.html'de brand ve color kaldırıldı. eklendi. 394 | 395 | *********************************** 396 | 397 | ### 5.1.4 Profil Görüntülenmesi 398 | 399 | customer.component kişinin profilini görüntülemesi için açılacak sayfa olarak düzenlendi. 400 | - localstorage'ta id yakalanarak user'ın özellikleri profile getirildi. Şu an için html'de let ile user'ı dönüyorum. Haliyle tek veri dönüyorum ancak kodlar refactor edilirken serviste listResponseModel yerine singleResponseModel'e döndürülecek. Yine tek veri gelecek ancak daha okunur ve daha düzgün çalışan bir kod olacak. 401 | 402 | - Güncellemelerin yapılabilmesi içni ise customer klasörüne customer-update klasörü eklendi. car-update gibi yaptığımız işlemlerin aynısını yaptım. Oluşturduğum formda kullanıcı idsini localstorage'tan aldım. 403 | - Burada güncelleme yaparken User gönderiyoruz ancak kayıt olurken passwordumuzu passwordHash ve Salt olarak kaydetmiştik. 404 | Bu kısımda eksikler var tamamlanacak. 405 | 406 | ![sondeneme4](https://user-images.githubusercontent.com/77545922/114316568-cf042400-9b0c-11eb-8ede-2583c97e0a85.PNG) 407 | 408 | 409 | 410 | *********************************** 411 | 412 | ### 5.1.5 Ödeme Ekranı Düzenlemeleri, Ödeme Kontrolleri ve Rent Ekleme 413 | 414 | - Kişinin kayıtlı kartlarını görebilmesi için backend tarafında fakeCard'a daha sonra veritabanında kartlara userId eklendi. Böylece kartlar bir kullanıcıya atanmış oldu. Servis ve Managerları yazıldı.(Serviste List döndürmemiz lazım çünkü bir kişinin birden fazla kartı olabilir. Bu işlemle kullanıcının kayıtlı kartlarını ekrana getirebiliriz.) 415 | - Api controller'ı yazıldı, postman'de testi yapıldı. 416 | - Kartlardaki para değişkeni ile karttaki paranın yetip yetmediği kontrol edilecek ve ödeme sonrası azalma sağlanacak. 417 | - frontend tarafında fakeCardServis'e getCardByUserId() ve add() yazıldı. 418 | 419 | *********************************** 420 | - Eğer birden fazla aracı aynı anda kiralama gibi bir durum düşünseydik, bir sepet düşünüp sepete ekle ile ekleme işlemi yapar ve ödeme ekranında sepeti getir kullanarak ödemeyi tamamlardık. Ancak biz tek rental taşıyacağımız için 421 | 422 | JSON.parse() 423 | JSON.stringify() 424 | 425 | dan yararlanıcaz. Rental tarafında route ile /payment yapıp, payment sayfamıza giderek sadece kartın varlığını kontrol etmiştik. Ancak bir ödeme almamış ve kira eklememiştik. Şu an approutingmodule'da paymentcomponent'imize giden yolu payment/:rental yapıyor ve rentalimizden payment'a giden rotamızı 426 | 427 | return this.router.navigate(['payment/' + JSON.stringify(this.rental)]); 428 | 429 | şeklinde değiştiriyoruz. 430 | 431 | - Payment kısmında bu şekilde gelen bir rentali alabilmek için ise bu şekilde: 432 | 433 | ngOnInit(): void { 434 | this.activatedRoute.params.subscribe((params)=>{ 435 | if(params['rental']){ 436 | this.createPaymentForm(); 437 | this.rental=JSON.parse(params['rental']) 438 | console.log(this.rental) 439 | this.getCards(); 440 | } 441 | }) 442 | } 443 | 444 | rental değişkenimize gelen rentali atamış oluyoruz ve klasik kart kontrolü işlemlerinden sonra kira ekleme işlemini paymentCheck'in içine yazıyoruz. 445 | 446 | **Eksikler:** 447 | 448 | ** **Kartı istenilen isme göre kaydetme işlemi getirilebilir.** 449 | 450 | ** **Mevcut kartı güncelleme getirilebilir.** 451 | 452 | ** **Bu Kart ile Öde butonu aktif hale getirilmedi.** 453 | 454 | 455 | - Ödeme işleminde fiyat kıyaslaması için getCarDetailsById() ile rental'den gelen carId'yi kullanarak araç detaylarımızı getirdik. PaymentCalculator() ile de günlük araç fiyatını total günle çarparak total fiyatı bulduk. 456 | 457 | **Eksikler:** 458 | 459 | ** **Ödeme özet sayfası oluşturulabilir.** 460 | 461 | **NOT: paymentCalculator() yazdıktan sonra NaN(NotANumber) döndüren arkadaşlar, bu kodların çalışma sırasında bir sıkıntıdan dolayı olabilir. Şu şekilde basit bir fotoğrafla anlatabilirim galiba.** 462 | 463 | ![sondeneme6](https://user-images.githubusercontent.com/77545922/114316616-f8bd4b00-9b0c-11eb-9532-59e4f368fad0.PNG) 464 | 465 | 466 | **Konsola baktığınızda paymentCalculator'da dönen işleme daha carDetail gitmediği için NaN dönüyor. Ancak carDetail gittikten sonra gördüğünüz gibi ödeme tutarını döndürebiliyor.** 467 | 468 | - Frontend tarafında para kontrolü gerçekleştirildi. Ödeme onaylandıysa para yeterliyse rental ekleniyor. Para kontrolü bir fonksiyona atanacak ancak aşağıdaki işlemler tamamlandıktan sonra. 469 | 470 | **Eksikler:** 471 | 472 | ** **Kiradan sonra findex puanının yükselmesi ve karttaki paranın azalması daha eklenmedi.** 473 | 474 | ** **Diğer sayfalarda listenin gitmesi giderilecek.** 475 | 476 | ** **Kartı kaydetme checkbox'ı eklendi ancak şöyle bir mantık hatası var. Benim yazdığım kodta 477 | veritabanında olmayan kartla ödeme yapılamıyor. Ödeme yapılamadığı için kart kaydedilemiyor.(isterde 478 | ödeme alındıktan sonra kartı kaydet işleminin yapılması). Bu yüzden bu kısımda tekrar düzenlemeler yapılacak.** 479 | 480 | ### 5.2 Final Ve Resimler 481 | 482 | Genel olarak eksiklerin hepsi gidermeye çalışacağım ve her geçen gün bu uygulamayla uğraşarak geliştirmeye çalışacağım. Bu projeye başladığımda web geliştirmenin en ufak bir noktasını dahi bilmiyordum. Öğrenmesi, uygulaması çok keyifli. Ancak vaktim biraz dar. Ek olarak: 483 | 484 | ** **Yönetici paneli eklenebilir.** 485 | 486 | ** **Homepage eklenebilir.** 487 | 488 | Bunların hepsi ilk akla gelen eksikler. Bunları tamamlarken bile belki aklıma farklı şeyler gelecek. Dediğim gibi her geçen gün aklıma gelenleri bu uygulamaya getirmeyi deneyeceğim öncelikli olarak bu eksikleri. 489 | 490 | Ödeme ekranındaki kiralama işlemi yapılırsa ve yapılmazsa aşağıdaki gibi. Ayrıca kayıtlı kart'ı da görebilirsiniz. 491 | 492 | **Peşin Satan 493 | 494 | ![sondeneme8](https://user-images.githubusercontent.com/77545922/114316666-25716280-9b0d-11eb-9424-d89bbdd5ba76.PNG) 495 | 496 | **Veresiye Satan 497 | 498 | ![sondeneme7](https://user-images.githubusercontent.com/77545922/114316671-2d310700-9b0d-11eb-9faa-763fd86263d0.PNG) 499 | 500 | 501 | --------------------------------------------------------------------------------