diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 02972627..59096dbc 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,7 +1,28 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; +import { ListComponent } from './contacts/list/list.component'; +import { ViewComponent } from './contacts/view/view.component'; +import { AddComponent } from './contacts/add/add.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/update/:id", + component: EditComponent + }, + { + path: "contacts/:id", + component: ViewComponent + }, +]; @NgModule({ imports: [RouterModule.forRoot(routes)], diff --git a/src/app/app.component.css b/src/app/app.component.css index 31d9e249..793a9e8a 100644 --- a/src/app/app.component.css +++ b/src/app/app.component.css @@ -5,5 +5,10 @@ .page { flex: 1; display: flex; + flex-direction: column; justify-content: center; } + +.contact-list { + display: grid; +} diff --git a/src/app/app.component.html b/src/app/app.component.html index 17aaa0c6..66e41277 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,4 +1,11 @@ - -
- -
+ +
+
+
+

{{title}}

+ +
+
+
+ + \ No newline at end of file diff --git a/src/app/app.component.ts b/src/app/app.component.ts index b82791ab..c2ea089f 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,8 +3,9 @@ import { Component } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', + standalone: false, styleUrls: ['./app.component.css'] }) export class AppComponent { - title = 'angular-address-book'; + title = 'Address-book'; } diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8207184c..9bf6af34 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -4,10 +4,12 @@ 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'; +import { CommonModule } from '@angular/common'; @NgModule({ declarations: [AppComponent], - imports: [BrowserModule, AppRoutingModule, LayoutModule], + imports: [BrowserModule, AppRoutingModule, LayoutModule, ContactsModule, CommonModule], 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..e69de29b diff --git a/src/app/contacts/add/add.component.html b/src/app/contacts/add/add.component.html new file mode 100644 index 00000000..9df020cf --- /dev/null +++ b/src/app/contacts/add/add.component.html @@ -0,0 +1,23 @@ + +
+

Add a contact

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
diff --git a/src/app/contacts/add/add.component.ts b/src/app/contacts/add/add.component.ts new file mode 100644 index 00000000..7f3186ce --- /dev/null +++ b/src/app/contacts/add/add.component.ts @@ -0,0 +1,39 @@ +import { Component, inject } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { Router } from '@angular/router'; +import { ContactService } from 'src/app/services/contact.service'; +import { Contact } from '../models/contact'; + +@Component({ + selector: 'app-add', + standalone: false, + templateUrl: './add.component.html', + styleUrl: './add.component.css' +}) +export class AddComponent { + contactForm: FormGroup; + formBuilder = inject(FormBuilder); + contactService = inject(ContactService) + router = inject(Router) + + constructor() { + this.contactForm = this.formBuilder.group({ + firstName: ["", Validators.required], + lastName: ["", Validators.required], + street: ["", Validators.required], + city: ["", Validators.required] + }); + } + addContact() { + const newContact: Contact = { + id: 0, + firstName: this.contactForm.value.firstName, + lastName: this.contactForm.value.lastName, + street: this.contactForm.value.street, + city: this.contactForm.value.city, + } + this.contactService.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..1cfbe17e --- /dev/null +++ b/src/app/contacts/contacts.module.ts @@ -0,0 +1,26 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ListComponent } from './list/list.component'; +import { RouterModule } from '@angular/router'; +import { AddComponent } from './add/add.component'; +import { ViewComponent } from './view/view.component'; +import { ReactiveFormsModule } from '@angular/forms'; +import { EditComponent } from './edit/edit.component'; + + + +@NgModule({ + declarations: [ + ListComponent, + AddComponent, + ViewComponent, + EditComponent + ], + imports: [ + CommonModule, + RouterModule, + ReactiveFormsModule + ], + exports: [ListComponent, ViewComponent, AddComponent, EditComponent] +}) +export class ContactsModule { } diff --git a/src/app/contacts/data/contacts.ts b/src/app/contacts/data/contacts.ts new file mode 100644 index 00000000..e587d867 --- /dev/null +++ b/src/app/contacts/data/contacts.ts @@ -0,0 +1,33 @@ + +import { Contact } from "../models/contact"; + +export const CONTACTS: Contact[] = [ + { + id: 1, + firstName: "Magnus", + lastName: "Hissingby", + street: "someStreet", + city: "someCity" + }, + { + id: 2, + firstName: "Birk", + lastName: "Sala", + street: "someStreet", + city: "someCity" + }, + { + id: 3, + firstName: "Cru", + lastName: "Lavender", + street: "someStreet", + city: "someCity" + }, + { + id: 4, + firstName: "Unc", + lastName: "Rivand", + street: "someStreet", + city: "someCity" + } +] \ No newline at end of file diff --git a/src/app/contacts/edit/edit.component.css b/src/app/contacts/edit/edit.component.css new file mode 100644 index 00000000..e69de29b diff --git a/src/app/contacts/edit/edit.component.html b/src/app/contacts/edit/edit.component.html new file mode 100644 index 00000000..831bb919 --- /dev/null +++ b/src/app/contacts/edit/edit.component.html @@ -0,0 +1,27 @@ + +@if (this.contact === null) { +

Contact does not exist!!!

+} @else { +
+

Edit contact

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+} \ No newline at end of file diff --git a/src/app/contacts/edit/edit.component.ts b/src/app/contacts/edit/edit.component.ts new file mode 100644 index 00000000..d2cb4202 --- /dev/null +++ b/src/app/contacts/edit/edit.component.ts @@ -0,0 +1,58 @@ +import { Component, inject } from '@angular/core'; +import { Contact } from '../models/contact'; +import { Form, FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ContactService } from 'src/app/services/contact.service'; +import { ActivatedRoute, Router } from '@angular/router'; + +@Component({ + selector: 'app-edit', + templateUrl: './edit.component.html', + styleUrl: './edit.component.css' +}) +export class EditComponent { + contact: Contact | null = null; + contactId: number | null = null; + contactForm: FormGroup; + formBuilder: FormBuilder = inject(FormBuilder) + contactService: ContactService = inject(ContactService) + router: Router = inject(Router) + route: ActivatedRoute = inject(ActivatedRoute) + + constructor() { + this.contactForm = this.formBuilder.group({ + firstName: ['', Validators.required], + lastName: ['', Validators.required], + street: ['', Validators.required], + city: ['', Validators.required] + }); + } + + ngOnInit() { + this.contactId = Number(this.route.snapshot.paramMap.get('id')); + this.contact = this.contactService.getContactById(this.contactId) + if (this.contact !== null && this.contact !== undefined) { + this.contactForm.patchValue({ + firstName: this.contact.firstName, + lastName: this.contact.lastName, + street: this.contact.street, + city: this.contact.city + }) + } + } + + editContact() { + if (!this.contactId) return; + + const updatedContact: Contact = { + id: this.contactId, + firstName: this.contactForm.value.firstName, + lastName: this.contactForm.value.lastName, + street: this.contactForm.value.street, + city: this.contactForm.value.city + } + this.contactService.editContact(updatedContact); + 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..a528e60c --- /dev/null +++ b/src/app/contacts/list/list.component.css @@ -0,0 +1,7 @@ + +.contact-list { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: .9rem; + border: 1px solid black; +} \ No newline at end of file diff --git a/src/app/contacts/list/list.component.html b/src/app/contacts/list/list.component.html new file mode 100644 index 00000000..45e269eb --- /dev/null +++ b/src/app/contacts/list/list.component.html @@ -0,0 +1,21 @@ + +

Contacts

+ +@if (this.contacts.length===0){ +
No contacts yet
+} @else { +
+
+
    + @for (contact of this.contacts; track contact){ +
  • {{contact.firstName}} {{contact.lastName}}
  • +
  • {{contact.street}}
  • +
  • {{contact.city}}
  • +
  • View Contact
  • +
  • Update Contact
  • + } +
+
+
+} + diff --git a/src/app/contacts/list/list.component.ts b/src/app/contacts/list/list.component.ts new file mode 100644 index 00000000..c4bc4fad --- /dev/null +++ b/src/app/contacts/list/list.component.ts @@ -0,0 +1,14 @@ +import { Component, inject } from '@angular/core'; +import { ContactService } from 'src/app/services/contact.service'; +import { Contact } from '../models/contact'; + +@Component({ + selector: 'app-list', + standalone: false, + templateUrl: './list.component.html', + styleUrl: './list.component.css' +}) +export class ListComponent { + contactService = inject(ContactService) + contacts: Contact[] = this.contactService.getAllContacts(); +} diff --git a/src/app/contacts/models/contact.ts b/src/app/contacts/models/contact.ts new file mode 100644 index 00000000..d293255f --- /dev/null +++ b/src/app/contacts/models/contact.ts @@ -0,0 +1,9 @@ + + +export interface Contact { + id: number; + firstName: string; + lastName: string; + street: string; + city: string +} \ No newline at end of file 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..aa9a48b2 --- /dev/null +++ b/src/app/contacts/view/view.component.html @@ -0,0 +1,12 @@ + +@if (this.contact === null) { +
+

Contact is null

+
+} @else { +
+

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

+

Street: {{this.contact.street}}

+

City: {{this.contact.city}}

+
+} \ No newline at end of file diff --git a/src/app/contacts/view/view.component.ts b/src/app/contacts/view/view.component.ts new file mode 100644 index 00000000..0cab924f --- /dev/null +++ b/src/app/contacts/view/view.component.ts @@ -0,0 +1,18 @@ +import { Component, inject } from '@angular/core'; +import { ActivatedRoute } from '@angular/router'; +import { ContactService } from 'src/app/services/contact.service'; +import { Contact } from '../models/contact'; + +@Component({ + selector: 'app-view', + standalone: false, + templateUrl: './view.component.html', + styleUrl: './view.component.css' +}) +export class ViewComponent { + contactService = inject(ContactService) + route = inject(ActivatedRoute) + + id = this.route.snapshot.paramMap.get('id') + contact: Contact | null = this.contactService.getContactById(Number(this.id)) +} diff --git a/src/app/layout/layout.module.ts b/src/app/layout/layout.module.ts index 501b6585..388e3a70 100644 --- a/src/app/layout/layout.module.ts +++ b/src/app/layout/layout.module.ts @@ -1,7 +1,7 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; -import { RouterModule } from '@angular/router'; import { MenuComponent } from './menu/menu.component'; +import { RouterModule } from '@angular/router'; @NgModule({ declarations: [MenuComponent], diff --git a/src/app/layout/menu/menu.component.html b/src/app/layout/menu/menu.component.html index 7c5ec7a2..95fe5dc8 100644 --- a/src/app/layout/menu/menu.component.html +++ b/src/app/layout/menu/menu.component.html @@ -1,5 +1,6 @@

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/services/contact.service.ts b/src/app/services/contact.service.ts new file mode 100644 index 00000000..fb5816fa --- /dev/null +++ b/src/app/services/contact.service.ts @@ -0,0 +1,38 @@ +import { Injectable } from '@angular/core'; +import { Contact } from '../contacts/models/contact'; +import { CONTACTS } from '../contacts/data/contacts'; + +@Injectable({ + providedIn: 'root' +}) +export class ContactService { + private contacts: Contact[] = CONTACTS; + private currentId: number = this.contacts.length + + public getContactById(id: number | null): Contact | null { + const contact = this.contacts.find((curr) => curr.id === id) + if (!contact) { + return null + } + return contact + } + + public getAllContacts(): Contact[] { + return this.contacts; + } + + public addContact(contact: Contact) { + this.currentId++; + contact.id = this.currentId + this.contacts.push(contact) + } + + public editContact(updatedContact: Contact) { + const cont = this.contacts.find((contact) => contact.id === updatedContact.id) + if (cont === undefined) return; + cont.firstName = updatedContact.firstName; + cont.lastName = updatedContact.lastName; + cont.street = updatedContact.street; + cont.city = updatedContact.city; + } +} diff --git a/src/styles.css b/src/styles.css index 90d4ee00..843c287c 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1 +1,23 @@ -/* You can add global styles to this file, and also import other style files */ + + +.side-page { + display: flex; + flex-direction: column; + justify-content: center; + text-align: center; + margin-left: 50px; +} + +form { + display: grid; + grid-template-columns: 150px 1fr; /* første kolonne labels, andre inputs */ + gap: 0.5rem 1rem; /* rad- og kolonneavstand */ + max-width: 400px; +} +form label { + text-align: right; /* høyrejustert label */ + padding-right: 0.5rem; +} +form input { + width: 100%; +}