From 40a859c53475aa3fcb2d25b6a2369885f14d6a69 Mon Sep 17 00:00:00 2001 From: Roman Eriksen Date: Mon, 8 Sep 2025 14:06:05 +0200 Subject: [PATCH] core --- angular.json | 3 ++ src/app/app-routing.module.ts | 11 ++++- src/app/app.module.ts | 3 +- src/app/contacts/add/add.component.css | 25 +++++++++++ src/app/contacts/add/add.component.html | 19 ++++++++ src/app/contacts/add/add.component.spec.ts | 23 ++++++++++ src/app/contacts/add/add.component.ts | 44 ++++++++++++++++++ src/app/contacts/contacts.module.ts | 15 +++++++ src/app/contacts/contacts.service.spec.ts | 16 +++++++ src/app/contacts/contacts.service.ts | 25 +++++++++++ src/app/contacts/edit/edit.component.css | 25 +++++++++++ src/app/contacts/edit/edit.component.html | 20 +++++++++ src/app/contacts/edit/edit.component.spec.ts | 23 ++++++++++ src/app/contacts/edit/edit.component.ts | 46 +++++++++++++++++++ src/app/contacts/list/list.component.css | 0 src/app/contacts/list/list.component.html | 11 +++++ src/app/contacts/list/list.component.spec.ts | 23 ++++++++++ src/app/contacts/list/list.component.ts | 20 +++++++++ src/app/contacts/view/view.component.css | 0 src/app/contacts/view/view.component.html | 11 +++++ src/app/contacts/view/view.component.spec.ts | 23 ++++++++++ src/app/contacts/view/view.component.ts | 25 +++++++++++ src/app/data/contacts.ts | 47 ++++++++++++++++++++ src/app/layout/menu/menu.component.html | 4 +- src/app/layout/menu/menu.component.ts | 1 + src/app/models/contacts.ts | 7 +++ 26 files changed, 466 insertions(+), 4 deletions(-) create mode 100644 src/app/contacts/add/add.component.css create mode 100644 src/app/contacts/add/add.component.html create mode 100644 src/app/contacts/add/add.component.spec.ts create mode 100644 src/app/contacts/add/add.component.ts create mode 100644 src/app/contacts/contacts.module.ts create mode 100644 src/app/contacts/contacts.service.spec.ts create mode 100644 src/app/contacts/contacts.service.ts create mode 100644 src/app/contacts/edit/edit.component.css create mode 100644 src/app/contacts/edit/edit.component.html create mode 100644 src/app/contacts/edit/edit.component.spec.ts create mode 100644 src/app/contacts/edit/edit.component.ts create mode 100644 src/app/contacts/list/list.component.css create mode 100644 src/app/contacts/list/list.component.html create mode 100644 src/app/contacts/list/list.component.spec.ts create mode 100644 src/app/contacts/list/list.component.ts create mode 100644 src/app/contacts/view/view.component.css create mode 100644 src/app/contacts/view/view.component.html create mode 100644 src/app/contacts/view/view.component.spec.ts create mode 100644 src/app/contacts/view/view.component.ts create mode 100644 src/app/data/contacts.ts create mode 100644 src/app/models/contacts.ts diff --git a/angular.json b/angular.json index 7a4f1ef7..f68fdcc5 100644 --- a/angular.json +++ b/angular.json @@ -94,5 +94,8 @@ } } } + }, + "cli": { + "analytics": "5e68f19b-492b-43bf-a083-d2e199b34a6d" } } diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 02972627..b2238619 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,7 +1,16 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; +import { ListComponent } from './contacts/list/list.component'; +import { AddComponent } from './contacts/add/add.component'; +import { ViewComponent } from './contacts/view/view.component'; +import { EditComponent } from './contacts/edit/edit.component'; -const routes: Routes = []; +const routes: Routes = [ + { path: 'contacts', component: ListComponent}, + { path: 'contacts/add', component: AddComponent}, + { path: 'contacts/:id', component: ViewComponent}, + { path: 'contacts/edit/:id', component: EditComponent}, +]; @NgModule({ imports: [RouterModule.forRoot(routes)], diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8207184c..2f305a5a 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -4,10 +4,11 @@ import { BrowserModule } from '@angular/platform-browser'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; import { LayoutModule } from './layout/layout.module'; +import { ContactsModule } from './contacts/contacts.module'; @NgModule({ declarations: [AppComponent], - imports: [BrowserModule, AppRoutingModule, LayoutModule], + imports: [BrowserModule, AppRoutingModule, LayoutModule, ContactsModule], bootstrap: [AppComponent], }) export class AppModule {} diff --git a/src/app/contacts/add/add.component.css b/src/app/contacts/add/add.component.css new file mode 100644 index 00000000..04068da6 --- /dev/null +++ b/src/app/contacts/add/add.component.css @@ -0,0 +1,25 @@ +:host { + display: flex; + box-sizing: border-box; + width: 40vw; + flex-direction: column; +} + +form { + display: flex; + flex-direction: column; + flex: 1; + gap: 0.5em; +} + +label { + font-weight: bold; +} + +.actions { + display: flex; +} + +.spacer { + flex: 1; +} diff --git a/src/app/contacts/add/add.component.html b/src/app/contacts/add/add.component.html new file mode 100644 index 00000000..241402f6 --- /dev/null +++ b/src/app/contacts/add/add.component.html @@ -0,0 +1,19 @@ +

Create Contact

+
+ + + + + + + + + + + + +
+
+ +
+
diff --git a/src/app/contacts/add/add.component.spec.ts b/src/app/contacts/add/add.component.spec.ts new file mode 100644 index 00000000..f4528470 --- /dev/null +++ b/src/app/contacts/add/add.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { AddComponent } from './add.component'; + +describe('AddComponent', () => { + let component: AddComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [AddComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(AddComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/contacts/add/add.component.ts b/src/app/contacts/add/add.component.ts new file mode 100644 index 00000000..a70d42ac --- /dev/null +++ b/src/app/contacts/add/add.component.ts @@ -0,0 +1,44 @@ +import { Component } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ContactsService } from '../contacts.service'; +import { Contact } from 'src/app/models/contacts'; +import { Router } from '@angular/router'; + +@Component({ + selector: 'app-add', + standalone: false, + templateUrl: './add.component.html', + styleUrl: './add.component.css', +}) + +export class AddComponent { + contactForm: FormGroup; + cservice: ContactsService; + constructor( + private formBuilder: FormBuilder, + private readonly contactService: ContactsService, + private readonly router: Router + ) { + this.contactForm = this.formBuilder.group({ + firstName: ['', Validators.required], + lastName: ['', Validators.required], + city: ['', Validators.required], + street: ['', Validators.required], + }); + this.cservice = this.contactService; + } + + addContact(): void { + const newContact: Contact = { + id: 0, + firstName: this.contactForm.value.firstName, + lastName: this.contactForm.value.lastName, + city: this.contactForm.value.city, + street: this.contactForm.value.street, + }; + console.log(newContact) + this.cservice.AddContact(newContact); + this.contactForm.reset(); + this.router.navigate(['/contacts']); + } +} diff --git a/src/app/contacts/contacts.module.ts b/src/app/contacts/contacts.module.ts new file mode 100644 index 00000000..b466ea73 --- /dev/null +++ b/src/app/contacts/contacts.module.ts @@ -0,0 +1,15 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { AddComponent } from './add/add.component'; +import { ViewComponent } from './view/view.component'; +import { ListComponent } from './list/list.component'; +import { ReactiveFormsModule } from '@angular/forms'; +import { RouterModule } from '@angular/router'; +import { EditComponent } from './edit/edit.component'; + +@NgModule({ + declarations: [AddComponent, ViewComponent, ListComponent, EditComponent], + imports: [CommonModule, ReactiveFormsModule, RouterModule], + exports: [AddComponent, ViewComponent, ListComponent, EditComponent], +}) +export class ContactsModule {} diff --git a/src/app/contacts/contacts.service.spec.ts b/src/app/contacts/contacts.service.spec.ts new file mode 100644 index 00000000..b64b5962 --- /dev/null +++ b/src/app/contacts/contacts.service.spec.ts @@ -0,0 +1,16 @@ +import { TestBed } from '@angular/core/testing'; + +import { ContactsService } from './contacts.service'; + +describe('ContactsService', () => { + let service: ContactsService; + + beforeEach(() => { + TestBed.configureTestingModule({}); + service = TestBed.inject(ContactsService); + }); + + it('should be created', () => { + expect(service).toBeTruthy(); + }); +}); diff --git a/src/app/contacts/contacts.service.ts b/src/app/contacts/contacts.service.ts new file mode 100644 index 00000000..71d474c4 --- /dev/null +++ b/src/app/contacts/contacts.service.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@angular/core'; +import { CONTACTS } from '../data/contacts'; +import { HttpClient } from '@angular/common/http'; +import { Contact } from '../models/contacts'; +import { Observable, of } from 'rxjs'; + +@Injectable({ + providedIn: 'root' +}) +export class ContactsService { + public contacts: Contact[] = CONTACTS; + + public AddContact(contact: Contact): void { + this.contacts.push(contact); + } + + GetContactById(id: number) { + const contact = this.contacts.find((c) => c.id === id); + return contact ?? null; + } + + EditContact(newContact: Contact) { + } + +} diff --git a/src/app/contacts/edit/edit.component.css b/src/app/contacts/edit/edit.component.css new file mode 100644 index 00000000..04068da6 --- /dev/null +++ b/src/app/contacts/edit/edit.component.css @@ -0,0 +1,25 @@ +:host { + display: flex; + box-sizing: border-box; + width: 40vw; + flex-direction: column; +} + +form { + display: flex; + flex-direction: column; + flex: 1; + gap: 0.5em; +} + +label { + font-weight: bold; +} + +.actions { + display: flex; +} + +.spacer { + flex: 1; +} diff --git a/src/app/contacts/edit/edit.component.html b/src/app/contacts/edit/edit.component.html new file mode 100644 index 00000000..abb90e1b --- /dev/null +++ b/src/app/contacts/edit/edit.component.html @@ -0,0 +1,20 @@ +

Edit Contact

+
+ + + + + + + + + + + + + +
+
+ +
+
diff --git a/src/app/contacts/edit/edit.component.spec.ts b/src/app/contacts/edit/edit.component.spec.ts new file mode 100644 index 00000000..6676ccfd --- /dev/null +++ b/src/app/contacts/edit/edit.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { EditComponent } from './edit.component'; + +describe('EditComponent', () => { + let component: EditComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [EditComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(EditComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/contacts/edit/edit.component.ts b/src/app/contacts/edit/edit.component.ts new file mode 100644 index 00000000..a493b4a3 --- /dev/null +++ b/src/app/contacts/edit/edit.component.ts @@ -0,0 +1,46 @@ +import { Component } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ContactsService } from '../contacts.service'; +import { Contact } from 'src/app/models/contacts'; +import { Router } from '@angular/router'; +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ReactiveFormsModule } from '@angular/forms'; + + +@Component({ + selector: 'app-edit', + standalone: false, + templateUrl: './edit.component.html', + styleUrl: './edit.component.css' +}) +export class EditComponent { + contactForm: FormGroup; + cservice: ContactsService; + constructor( + private formBuilder: FormBuilder, + private readonly contactService: ContactsService, + private readonly router: Router + ) { + this.contactForm = this.formBuilder.group({ + firstName: ['', Validators.required], + lastName: ['', Validators.required], + city: ['', Validators.required], + street: ['', Validators.required], + }); + this.cservice = this.contactService; + } + + editContact(): void { + const newContact: Contact = { + id: 0, + firstName: this.contactForm.value.firstName, + lastName: this.contactForm.value.lastName, + city: this.contactForm.value.city, + street: this.contactForm.value.street, + }; + this.cservice.AddContact(newContact); + this.contactForm.reset(); + this.router.navigate(['/contacts']); + } +} diff --git a/src/app/contacts/list/list.component.css b/src/app/contacts/list/list.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/contacts/list/list.component.html b/src/app/contacts/list/list.component.html new file mode 100644 index 00000000..0d1f0b0a --- /dev/null +++ b/src/app/contacts/list/list.component.html @@ -0,0 +1,11 @@ +

Contacts

+ + + \ No newline at end of file diff --git a/src/app/contacts/list/list.component.spec.ts b/src/app/contacts/list/list.component.spec.ts new file mode 100644 index 00000000..b602c867 --- /dev/null +++ b/src/app/contacts/list/list.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ListComponent } from './list.component'; + +describe('ListComponent', () => { + let component: ListComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ListComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ListComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/contacts/list/list.component.ts b/src/app/contacts/list/list.component.ts new file mode 100644 index 00000000..0142eba2 --- /dev/null +++ b/src/app/contacts/list/list.component.ts @@ -0,0 +1,20 @@ +import { Injectable } from '@angular/core'; +import { Component } from '@angular/core'; +import { Contact } from 'src/app/models/contacts'; +import { ContactsService } from '../contacts.service'; + +@Component({ + selector: 'app-list', + standalone: false, + // imports: [], + templateUrl: './list.component.html', + styleUrl: './list.component.css' +}) +export class ListComponent { + contacts: Contact[] = []; + + constructor(private readonly contactService: ContactsService) { + this.contacts = this.contactService.contacts; + console.log(this.contacts) + } +} diff --git a/src/app/contacts/view/view.component.css b/src/app/contacts/view/view.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/contacts/view/view.component.html b/src/app/contacts/view/view.component.html new file mode 100644 index 00000000..db0292fe --- /dev/null +++ b/src/app/contacts/view/view.component.html @@ -0,0 +1,11 @@ + + + +

{{ contact.firstName }} {{ contact.lastName }}

+

{{ contact.street }}, {{ contact.city }}

+
+ + +

Contact not found

+
diff --git a/src/app/contacts/view/view.component.spec.ts b/src/app/contacts/view/view.component.spec.ts new file mode 100644 index 00000000..380ab164 --- /dev/null +++ b/src/app/contacts/view/view.component.spec.ts @@ -0,0 +1,23 @@ +import { ComponentFixture, TestBed } from '@angular/core/testing'; + +import { ViewComponent } from './view.component'; + +describe('ViewComponent', () => { + let component: ViewComponent; + let fixture: ComponentFixture; + + beforeEach(async () => { + await TestBed.configureTestingModule({ + imports: [ViewComponent] + }) + .compileComponents(); + + fixture = TestBed.createComponent(ViewComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + }); + + it('should create', () => { + expect(component).toBeTruthy(); + }); +}); diff --git a/src/app/contacts/view/view.component.ts b/src/app/contacts/view/view.component.ts new file mode 100644 index 00000000..8b3028d5 --- /dev/null +++ b/src/app/contacts/view/view.component.ts @@ -0,0 +1,25 @@ +import { Component, OnInit } from '@angular/core'; + +import { ContactsService } from '../contacts.service'; +import { ActivatedRoute } from '@angular/router'; +import { Contact } from 'src/app/models/contacts'; + +@Component({ + selector: 'app-view', + // standalone: false, + templateUrl: './view.component.html', + styleUrl: './view.component.css', +}) +export class ViewComponent { + contact: Contact | null | undefined = null; + contactId: number | null = null; + + constructor( + private route: ActivatedRoute, + private contactsService: ContactsService + ) { + this.contact = this.contactsService.GetContactById( + Number(route.snapshot.paramMap.get('id')) + ); + } +} \ No newline at end of file diff --git a/src/app/data/contacts.ts b/src/app/data/contacts.ts new file mode 100644 index 00000000..6925a716 --- /dev/null +++ b/src/app/data/contacts.ts @@ -0,0 +1,47 @@ +import { Contact } from '../models/contacts' + +export const CONTACTS: Contact[] = [ + { + id: 1, + firstName: 'Roman', + lastName: 'Eriksen', + city: 'Oslo', + street: 'Bergensgata' + }, + { + id: 2, + firstName: 'Maya', + lastName: 'Larsen', + city: 'Bergen', + street: 'Fjellveien' +}, +{ + id: 3, + firstName: 'Jonas', + lastName: 'Haugen', + city: 'Trondheim', + street: 'Elgeseter gate' +}, +{ + id: 4, + firstName: 'Ingrid', + lastName: 'Nilsen', + city: 'Stavanger', + street: 'Kirkegata' +}, +{ + id: 5, + firstName: 'Oliver', + lastName: 'Sørensen', + city: 'Tromsø', + street: 'Storgata' +}, +{ + id: 6, + firstName: 'Emma', + lastName: 'Johansen', + city: 'Drammen', + street: 'Bragernes Torg' +} + +] \ No newline at end of file diff --git a/src/app/layout/menu/menu.component.html b/src/app/layout/menu/menu.component.html index 7c5ec7a2..aed3259d 100644 --- a/src/app/layout/menu/menu.component.html +++ b/src/app/layout/menu/menu.component.html @@ -1,5 +1,5 @@

Menu

diff --git a/src/app/layout/menu/menu.component.ts b/src/app/layout/menu/menu.component.ts index 1c826c99..33c5f00d 100644 --- a/src/app/layout/menu/menu.component.ts +++ b/src/app/layout/menu/menu.component.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; @Component({ selector: 'app-menu', + standalone: false, templateUrl: './menu.component.html', styleUrls: ['./menu.component.css'], }) diff --git a/src/app/models/contacts.ts b/src/app/models/contacts.ts new file mode 100644 index 00000000..0cc920d4 --- /dev/null +++ b/src/app/models/contacts.ts @@ -0,0 +1,7 @@ +export interface Contact { + id: number | null; + firstName: string; + lastName: string; + city: string; + street: string; +} \ No newline at end of file