diff --git a/DeveloperTest/Business/CustomerService.cs b/DeveloperTest/Business/CustomerService.cs new file mode 100644 index 0000000..acd5a9e --- /dev/null +++ b/DeveloperTest/Business/CustomerService.cs @@ -0,0 +1,56 @@ +using System.Linq; +using DeveloperTest.Business.Interfaces; +using DeveloperTest.Database; +using DeveloperTest.Database.Models; +using DeveloperTest.Models; + +namespace DeveloperTest.Business +{ + public class CustomerService : ICustomerService + { + private readonly ApplicationDbContext context; + + public CustomerService(ApplicationDbContext context) + { + this.context = context; + } + + public CustomerModel[] GetCustomers() + { + return context.Customers.Select(x => new CustomerModel + { + CustomerId = x.CustomerId, + Name = x.Name, + Type = x.Type + }).ToArray(); + } + + public CustomerModel GetCustomer(int customerId) + { + return context.Customers.Where(x => x.CustomerId == customerId).Select(x => new CustomerModel + { + CustomerId = x.CustomerId, + Type = x.Type, + Name = x.Name, + }).SingleOrDefault(); + } + + public CustomerModel CreateCustomer(BaseCustomerModel model) + { + var addedCustomer = context.Customers.Add(new Customer + { + Name = model.Name, + Type = model.Type + }); + + context.SaveChanges(); + + return new CustomerModel + { + CustomerId = addedCustomer.Entity.CustomerId, + Name = addedCustomer.Entity.Name, + Type = addedCustomer.Entity.Type + }; + } + } +} diff --git a/DeveloperTest/Business/Interfaces/ICustomerService.cs b/DeveloperTest/Business/Interfaces/ICustomerService.cs new file mode 100644 index 0000000..26e0316 --- /dev/null +++ b/DeveloperTest/Business/Interfaces/ICustomerService.cs @@ -0,0 +1,13 @@ +using DeveloperTest.Models; + +namespace DeveloperTest.Business.Interfaces +{ + public interface ICustomerService + { + CustomerModel[] GetCustomers(); + + CustomerModel GetCustomer(int customerId); + + CustomerModel CreateCustomer(BaseCustomerModel model); + } +} diff --git a/DeveloperTest/Business/JobService.cs b/DeveloperTest/Business/JobService.cs index 7eb8f64..30236ae 100644 --- a/DeveloperTest/Business/JobService.cs +++ b/DeveloperTest/Business/JobService.cs @@ -3,6 +3,7 @@ using DeveloperTest.Database; using DeveloperTest.Database.Models; using DeveloperTest.Models; +using Microsoft.EntityFrameworkCore; namespace DeveloperTest.Business { @@ -21,17 +22,29 @@ public JobModel[] GetJobs() { JobId = x.JobId, Engineer = x.Engineer, - When = x.When + When = x.When, + Customer = x.Customer != null ? new CustomerModel + { + CustomerId = x.Customer.CustomerId, + Name = x.Customer.Name, + Type = x.Customer.Type + } : null }).ToArray(); } public JobModel GetJob(int jobId) { - return context.Jobs.Where(x => x.JobId == jobId).Select(x => new JobModel + return context.Jobs.Include(x => x.Customer).Where(x => x.JobId == jobId).Select(x => new JobModel { JobId = x.JobId, Engineer = x.Engineer, - When = x.When + When = x.When, + Customer = x.Customer != null ? new CustomerModel + { + CustomerId = x.Customer.CustomerId, + Name = x.Customer.Name, + Type = x.Customer.Type + } : null }).SingleOrDefault(); } @@ -40,7 +53,8 @@ public JobModel CreateJob(BaseJobModel model) var addedJob = context.Jobs.Add(new Job { Engineer = model.Engineer, - When = model.When + When = model.When, + CustomerId = model.CustomerId }); context.SaveChanges(); @@ -49,7 +63,13 @@ public JobModel CreateJob(BaseJobModel model) { JobId = addedJob.Entity.JobId, Engineer = addedJob.Entity.Engineer, - When = addedJob.Entity.When + When = addedJob.Entity.When, + Customer = addedJob.Entity.Customer != null ? new CustomerModel + { + CustomerId = addedJob.Entity.Customer.CustomerId, + Name = addedJob.Entity.Customer.Name, + Type = addedJob.Entity.Customer.Type + } : null }; } } diff --git a/DeveloperTest/Controllers/CustomerController.cs b/DeveloperTest/Controllers/CustomerController.cs new file mode 100644 index 0000000..88e3c44 --- /dev/null +++ b/DeveloperTest/Controllers/CustomerController.cs @@ -0,0 +1,56 @@ +using System; +using Microsoft.AspNetCore.Mvc; +using DeveloperTest.Business.Interfaces; +using DeveloperTest.Models; +using System.Linq; + +namespace DeveloperTest.Controllers +{ + [ApiController, Route("[controller]")] + public class CustomerController : ControllerBase + { + private readonly ICustomerService customerService; + + public CustomerController(ICustomerService customerService) + { + this.customerService = customerService; + } + + [HttpGet] + public IActionResult Get() + { + return Ok(customerService.GetCustomers()); + } + + [HttpGet("{id}")] + public IActionResult Get(int id) + { + var customer = customerService.GetCustomer(id); + + if (customer == null) + { + return NotFound(); + } + + return Ok(customer); + } + + [HttpPost] + public IActionResult Create(BaseCustomerModel model) + { + var allowedTypes = new string[] { "Large", "Small" }; + if (!ModelState.IsValid) + { + return BadRequest("Name and Type fields are required and name must be minimum 5 characters"); + } + if (!allowedTypes.Any(t => t != model.Name)) + { + return BadRequest("Customer type should be either Large or Small"); + } + + var customer = customerService.CreateCustomer(model); + + return Created($"customer/{customer.CustomerId}", customer); + } + } +} \ No newline at end of file diff --git a/DeveloperTest/Database/ApplicationDbContext.cs b/DeveloperTest/Database/ApplicationDbContext.cs index f5be4a1..4751413 100644 --- a/DeveloperTest/Database/ApplicationDbContext.cs +++ b/DeveloperTest/Database/ApplicationDbContext.cs @@ -7,6 +7,7 @@ namespace DeveloperTest.Database public class ApplicationDbContext : DbContext { public DbSet Jobs { get; set; } + public DbSet Customers { get; set; } public ApplicationDbContext(DbContextOptions options) : base(options) { @@ -20,10 +21,18 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity() .HasKey(x => x.JobId); + modelBuilder.Entity() .Property(x => x.JobId) .ValueGeneratedOnAdd(); + modelBuilder.Entity() + .HasKey(x => x.CustomerId); + + modelBuilder.Entity() + .Property(x => x.CustomerId) + .ValueGeneratedOnAdd(); + modelBuilder.Entity() .HasData(new Job { diff --git a/DeveloperTest/Database/Models/Customer.cs b/DeveloperTest/Database/Models/Customer.cs new file mode 100644 index 0000000..e0ce5ad --- /dev/null +++ b/DeveloperTest/Database/Models/Customer.cs @@ -0,0 +1,11 @@ +namespace DeveloperTest.Database.Models +{ + public class Customer + { + public int CustomerId { get; set; } + + public string Name { get; set; } + + public string Type { get; set; } + } +} diff --git a/DeveloperTest/Database/Models/Job.cs b/DeveloperTest/Database/Models/Job.cs index 8a2abd0..0299a2a 100644 --- a/DeveloperTest/Database/Models/Job.cs +++ b/DeveloperTest/Database/Models/Job.cs @@ -8,6 +8,10 @@ public class Job public string Engineer { get; set; } + public int? CustomerId { get; set; } + + public Customer Customer { get; set; } + public DateTime When { get; set; } } } diff --git a/DeveloperTest/Migrations/20220310023924_IncludeCustomertable.Designer.cs b/DeveloperTest/Migrations/20220310023924_IncludeCustomertable.Designer.cs new file mode 100644 index 0000000..05f679e --- /dev/null +++ b/DeveloperTest/Migrations/20220310023924_IncludeCustomertable.Designer.cs @@ -0,0 +1,89 @@ +// +using System; +using DeveloperTest.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace DeveloperTest.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20220310023924_IncludeCustomertable")] + partial class IncludeCustomertable + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.1") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + + modelBuilder.Entity("DeveloperTest.Database.Models.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("CustomerId"), 1L, 1); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("Type") + .HasColumnType("nvarchar(max)"); + + b.HasKey("CustomerId"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("DeveloperTest.Database.Models.Job", b => + { + b.Property("JobId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("JobId"), 1L, 1); + + b.Property("CustomerId") + .HasColumnType("int"); + + b.Property("Engineer") + .HasColumnType("nvarchar(max)"); + + b.Property("When") + .HasColumnType("datetime2"); + + b.HasKey("JobId"); + + b.HasIndex("CustomerId"); + + b.ToTable("Jobs"); + + b.HasData( + new + { + JobId = 1, + Engineer = "Test", + When = new DateTime(2022, 2, 1, 12, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("DeveloperTest.Database.Models.Job", b => + { + b.HasOne("DeveloperTest.Database.Models.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId"); + + b.Navigation("Customer"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/DeveloperTest/Migrations/20220310023924_IncludeCustomertable.cs b/DeveloperTest/Migrations/20220310023924_IncludeCustomertable.cs new file mode 100644 index 0000000..c92200e --- /dev/null +++ b/DeveloperTest/Migrations/20220310023924_IncludeCustomertable.cs @@ -0,0 +1,67 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace DeveloperTest.Migrations +{ + public partial class IncludeCustomertable : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Customers", + columns: table => new + { + CustomerId = table.Column(nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(nullable: false), + Type = table.Column(nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Customers", x => x.CustomerId); + }); + + migrationBuilder.AddColumn( + name: "CustomerId", + table: "Jobs", + type: "int", + nullable: true); + + migrationBuilder.UpdateData( + table: "Jobs", + keyColumn: "JobId", + keyValue: 1, + column: "CustomerId", + value: null); + + migrationBuilder.AddForeignKey( + name: "FK_Jobs_Customers_CustomerId", + table: "Jobs", + column: "CustomerId", + principalTable: "Customers", + principalColumn: "CustomerId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Jobs_Customers_CustomerId", + table: "Jobs"); + + migrationBuilder.DropColumn( + name: "CustomerId", + table: "Jobs" + ); + + + migrationBuilder.AddForeignKey( + name: "FK_Jobs_Customers_CustomerId", + table: "Jobs", + column: "CustomerId", + principalTable: "Customers", + principalColumn: "CustomerId", + onDelete: ReferentialAction.Cascade); + } + } +} diff --git a/DeveloperTest/Migrations/ApplicationDbContextModelSnapshot.cs b/DeveloperTest/Migrations/ApplicationDbContextModelSnapshot.cs index 0ee623b..9f1f936 100644 --- a/DeveloperTest/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/DeveloperTest/Migrations/ApplicationDbContextModelSnapshot.cs @@ -22,6 +22,25 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder, 1L, 1); + modelBuilder.Entity("DeveloperTest.Database.Models.Customer", b => + { + b.Property("CustomerId") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("CustomerId"), 1L, 1); + + b.Property("Name") + .HasColumnType("nvarchar(max)"); + + b.Property("Type") + .HasColumnType("nvarchar(max)"); + + b.HasKey("CustomerId"); + + b.ToTable("Customers"); + }); + modelBuilder.Entity("DeveloperTest.Database.Models.Job", b => { b.Property("JobId") @@ -30,6 +49,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("JobId"), 1L, 1); + b.Property("CustomerId") + .HasColumnType("int"); + b.Property("Engineer") .HasColumnType("nvarchar(max)"); @@ -38,6 +60,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("JobId"); + b.HasIndex("CustomerId"); + b.ToTable("Jobs"); b.HasData( @@ -48,6 +72,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) When = new DateTime(2022, 2, 1, 12, 0, 0, 0, DateTimeKind.Unspecified) }); }); + + modelBuilder.Entity("DeveloperTest.Database.Models.Job", b => + { + b.HasOne("DeveloperTest.Database.Models.Customer", "Customer") + .WithMany() + .HasForeignKey("CustomerId"); + + b.Navigation("Customer"); + }); #pragma warning restore 612, 618 } } diff --git a/DeveloperTest/Models/BaseCustomerModel.cs b/DeveloperTest/Models/BaseCustomerModel.cs new file mode 100644 index 0000000..68568c7 --- /dev/null +++ b/DeveloperTest/Models/BaseCustomerModel.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +namespace DeveloperTest.Models +{ + public class BaseCustomerModel + { + [Required] + [MinLength(5)] + public string Name { get; set; } + + [Required] + public string Type { get; set; } + } +} diff --git a/DeveloperTest/Models/BaseJobModel.cs b/DeveloperTest/Models/BaseJobModel.cs index d2bc052..7a65bae 100644 --- a/DeveloperTest/Models/BaseJobModel.cs +++ b/DeveloperTest/Models/BaseJobModel.cs @@ -7,5 +7,7 @@ public class BaseJobModel public string Engineer { get; set; } public DateTime When { get; set; } + + public int CustomerId { get; set; } } } diff --git a/DeveloperTest/Models/CustomerModel.cs b/DeveloperTest/Models/CustomerModel.cs new file mode 100644 index 0000000..0c36952 --- /dev/null +++ b/DeveloperTest/Models/CustomerModel.cs @@ -0,0 +1,7 @@ +namespace DeveloperTest.Models +{ + public class CustomerModel : BaseCustomerModel + { + public int CustomerId { get; set; } + } +} diff --git a/DeveloperTest/Models/JobModel.cs b/DeveloperTest/Models/JobModel.cs index 8f2b5be..2cd0246 100644 --- a/DeveloperTest/Models/JobModel.cs +++ b/DeveloperTest/Models/JobModel.cs @@ -9,5 +9,7 @@ public class JobModel public string Engineer { get; set; } public DateTime When { get; set; } + + public CustomerModel Customer { get; set; } } } diff --git a/DeveloperTest/Startup.cs b/DeveloperTest/Startup.cs index 5242f22..64012da 100644 --- a/DeveloperTest/Startup.cs +++ b/DeveloperTest/Startup.cs @@ -28,6 +28,7 @@ public void ConfigureServices(IServiceCollection services) options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddTransient(); + services.AddTransient(); } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/ui/src/app/app-routing.module.ts b/ui/src/app/app-routing.module.ts index a6af4f8..90b239e 100644 --- a/ui/src/app/app-routing.module.ts +++ b/ui/src/app/app-routing.module.ts @@ -3,13 +3,17 @@ import { Routes, RouterModule } from '@angular/router'; import { JobComponent } from './job/job.component'; import { HomeComponent } from './home/home.component'; import { JobDetailComponent } from './job-detail/job-detail.component'; +import { CustomerComponent } from './customer/customer.component'; +import { CustomerDetailComponent } from './customer-detail/customer-detail.component'; const routes: Routes = [ { path: '', component: HomeComponent }, { path: 'home', component: HomeComponent }, { path: 'jobs', component: JobComponent }, - { path: 'job/:id', component: JobDetailComponent } + { path: 'job/:id', component: JobDetailComponent }, + { path: 'customers', component: CustomerComponent }, + { path: 'customer/:id', component: CustomerDetailComponent } ]; @NgModule({ diff --git a/ui/src/app/app.component.html b/ui/src/app/app.component.html index 49133ec..94af8ff 100644 --- a/ui/src/app/app.component.html +++ b/ui/src/app/app.component.html @@ -2,6 +2,7 @@ \ No newline at end of file diff --git a/ui/src/app/app.module.ts b/ui/src/app/app.module.ts index 0d1f678..3014107 100644 --- a/ui/src/app/app.module.ts +++ b/ui/src/app/app.module.ts @@ -8,13 +8,18 @@ import { AppComponent } from './app.component'; import { JobComponent } from './job/job.component'; import { HomeComponent } from './home/home.component'; import { JobDetailComponent } from './job-detail/job-detail.component'; +import { CustomerComponent } from './customer/customer.component'; +import { CustomerDetailComponent } from './customer-detail/customer-detail.component'; + @NgModule({ declarations: [ AppComponent, JobComponent, HomeComponent, - JobDetailComponent + JobDetailComponent, + CustomerComponent, + CustomerDetailComponent ], imports: [ FormsModule, diff --git a/ui/src/app/customer-detail/customer-detail.component.html b/ui/src/app/customer-detail/customer-detail.component.html new file mode 100644 index 0000000..cf6ccb3 --- /dev/null +++ b/ui/src/app/customer-detail/customer-detail.component.html @@ -0,0 +1,5 @@ +

CustomerId: {{customer.customerId}}

+

Name: {{customer.name}}

+

Type: {{customer.type}}

+ +Back diff --git a/ui/src/app/customer-detail/customer-detail.component.scss b/ui/src/app/customer-detail/customer-detail.component.scss new file mode 100644 index 0000000..e69de29 diff --git a/ui/src/app/customer-detail/customer-detail.component.spec.ts b/ui/src/app/customer-detail/customer-detail.component.spec.ts new file mode 100644 index 0000000..8ae027e --- /dev/null +++ b/ui/src/app/customer-detail/customer-detail.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CustomerDetailComponent } from './customer-detail.component'; + +describe('CustomerDetailComponent', () => { + let component: CustomerDetailComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CustomerDetailComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CustomerDetailComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ui/src/app/customer-detail/customer-detail.component.ts b/ui/src/app/customer-detail/customer-detail.component.ts new file mode 100644 index 0000000..ef90b49 --- /dev/null +++ b/ui/src/app/customer-detail/customer-detail.component.ts @@ -0,0 +1,28 @@ +import { Component, OnInit } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { CustomerService } from '../services/customer.service'; +import { CustomerModel } from '../models/customer.model'; + +@Component({ + selector: 'app-customer-detail', + templateUrl: './customer-detail.component.html', + styleUrls: ['./customer-detail.component.scss'] +}) + +export class CustomerDetailComponent implements OnInit { + + private customerId: number; + + public customer: CustomerModel; + + constructor( + private route: ActivatedRoute, + private customerService: CustomerService) { + this.customerId = route.snapshot.params.id; + } + + ngOnInit() { + this.customerService.GetCustomer(this.customerId).subscribe(customer => this.customer = customer); + } + +} diff --git a/ui/src/app/customer/customer.component.html b/ui/src/app/customer/customer.component.html new file mode 100644 index 0000000..6e7969b --- /dev/null +++ b/ui/src/app/customer/customer.component.html @@ -0,0 +1,33 @@ +

New customer form

+
+ + + Please enter a customer name with atleast 5 characters + + + Please select customer type + +
+ +

Customer list

+ + + + + + + + + + + + + + + +
NameType
{{customer.name}}{{customer.type}} + Open +
\ No newline at end of file diff --git a/ui/src/app/customer/customer.component.scss b/ui/src/app/customer/customer.component.scss new file mode 100644 index 0000000..9b45842 --- /dev/null +++ b/ui/src/app/customer/customer.component.scss @@ -0,0 +1,40 @@ +h2 { + margin-left: 15px; + } + + form { + margin: 15px; + + label { + display: block; + } + + input, select, button { + display: block; + width: 250px; + margin-bottom: 15px; + } + + small { + color: red; + margin-top: -12px; + margin-bottom: 15px; + display: block; + } + } + + table { + margin: 15px; + border-collapse: collapse; + + th, td { + border: 1px solid #ddd; + padding: 5px; + min-width: 100px; + text-align: left; + } + + th { + background-color: #ddd; + } + } \ No newline at end of file diff --git a/ui/src/app/customer/customer.component.spec.ts b/ui/src/app/customer/customer.component.spec.ts new file mode 100644 index 0000000..2092a8c --- /dev/null +++ b/ui/src/app/customer/customer.component.spec.ts @@ -0,0 +1,25 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { CustomerComponent } from './customer.component'; + +describe('CustomerComponent', () => { + let component: CustomerComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + declarations: [ CustomerComponent ] + }) + .compileComponents(); + }); + + beforeEach(() => { + fixture = TestBed.createComponent(CustomerComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/ui/src/app/customer/customer.component.ts b/ui/src/app/customer/customer.component.ts new file mode 100644 index 0000000..70395c8 --- /dev/null +++ b/ui/src/app/customer/customer.component.ts @@ -0,0 +1,31 @@ +import { Component, OnInit } from '@angular/core'; +import { CustomerModel } from '../models/customer.model'; +import { CustomerService } from '../services/customer.service'; + +@Component({ + selector: 'app-customer', + templateUrl: './customer.component.html', + styleUrls: ['./customer.component.scss'] +}) +export class CustomerComponent implements OnInit { + public types: string[] = ['Large', 'Small']; + public customers: CustomerModel[] = []; + public newCustomer: CustomerModel = { + customerId: null, + name: null, + type: null + }; + + constructor(private customerService: CustomerService) { } + + ngOnInit(): void { + this.customerService.GetCustomers().subscribe(customers => this.customers = customers); + } + + public createCustomer(): void { + this.customerService.CreateCustomer(this.newCustomer).then(() => { + this.customerService.GetCustomers().subscribe(customers => this.customers = customers); + }); + } + +} diff --git a/ui/src/app/job-detail/job-detail.component.html b/ui/src/app/job-detail/job-detail.component.html index b92e031..21d97ef 100644 --- a/ui/src/app/job-detail/job-detail.component.html +++ b/ui/src/app/job-detail/job-detail.component.html @@ -1,5 +1,7 @@

JobId: {{job.jobId}}

Engineer: {{job.engineer}}

When: {{job.when | date:'shortDate'}}

+

Customer: {{job.customer ? job.customer.name : 'Unknown' }}

+

Type: {{job.customer ? job.customer.type : 'Unknown' }}

Back \ No newline at end of file diff --git a/ui/src/app/job/job.component.html b/ui/src/app/job/job.component.html index 085c531..c4af2d9 100644 --- a/ui/src/app/job/job.component.html +++ b/ui/src/app/job/job.component.html @@ -9,6 +9,12 @@

New job form

Please select a valid date + + + Please select a customer @@ -18,6 +24,7 @@

Jobs list

Engineer When + Customer @@ -25,6 +32,7 @@

Jobs list

{{job.engineer}} {{job.when | date:'shortDate'}} + {{job.customer ? job.customer.name : 'Unknown'}} Open diff --git a/ui/src/app/job/job.component.ts b/ui/src/app/job/job.component.ts index e9de751..2740d6a 100644 --- a/ui/src/app/job/job.component.ts +++ b/ui/src/app/job/job.component.ts @@ -3,6 +3,8 @@ import { NgForm } from '@angular/forms'; import { EngineerService } from '../services/engineer.service'; import { JobService } from '../services/job.service'; import { JobModel } from '../models/job.model'; +import { CustomerModel } from '../models/customer.model'; +import { CustomerService } from '../services/customer.service'; @Component({ selector: 'app-job', @@ -14,8 +16,10 @@ export class JobComponent implements OnInit { public engineers: string[] = []; public jobs: JobModel[] = []; + public customers: CustomerModel[] = []; public newJob: JobModel = { + customerId: undefined, jobId: null, engineer: null, when: null @@ -23,11 +27,13 @@ export class JobComponent implements OnInit { constructor( private engineerService: EngineerService, - private jobService: JobService) { } + private jobService: JobService, + private customerService: CustomerService) { } ngOnInit() { this.engineerService.GetEngineers().subscribe(engineers => this.engineers = engineers); this.jobService.GetJobs().subscribe(jobs => this.jobs = jobs); + this.customerService.GetCustomers().subscribe(customers => this.customers = customers); } public createJob(form: NgForm): void { diff --git a/ui/src/app/models/customer.model.ts b/ui/src/app/models/customer.model.ts new file mode 100644 index 0000000..2df9531 --- /dev/null +++ b/ui/src/app/models/customer.model.ts @@ -0,0 +1,6 @@ +export interface CustomerModel { + customerId?: number; + name: string; + type: string; + } + \ No newline at end of file diff --git a/ui/src/app/models/job.model.ts b/ui/src/app/models/job.model.ts index 5c3342c..14ab368 100644 --- a/ui/src/app/models/job.model.ts +++ b/ui/src/app/models/job.model.ts @@ -1,5 +1,9 @@ +import { CustomerModel } from "./customer.model"; + export interface JobModel { - jobId: number; + jobId?: number; engineer: string; + customerId?: number; when: Date; + customer?: CustomerModel; } diff --git a/ui/src/app/services/customer.service.spec.ts b/ui/src/app/services/customer.service.spec.ts new file mode 100644 index 0000000..adabb97 --- /dev/null +++ b/ui/src/app/services/customer.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { CustomerService } from './customer.service'; + +describe('CustomerService', () => { + let service: CustomerService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(CustomerService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/ui/src/app/services/customer.service.ts b/ui/src/app/services/customer.service.ts new file mode 100644 index 0000000..a2fbf3a --- /dev/null +++ b/ui/src/app/services/customer.service.ts @@ -0,0 +1,24 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable } from 'rxjs'; +import { CustomerModel } from '../models/customer.model'; + +@Injectable({ + providedIn: 'root' +}) +export class CustomerService { + + constructor(private httpClient: HttpClient) { } + + public GetCustomers(): Observable { + return this.httpClient.get('http://localhost:63235/customer'); + } + + public GetCustomer(customerId: number): Observable { + return this.httpClient.get(`http://localhost:63235/customer/${customerId}`); + } + + public CreateCustomer(customer: CustomerModel): Promise { + return this.httpClient.post('http://localhost:63235/customer', customer).toPromise(); + } +}