diff --git a/angular.json b/angular.json index 7a4f1ef7..be4c78d3 100644 --- a/angular.json +++ b/angular.json @@ -94,5 +94,8 @@ } } } + }, + "cli": { + "analytics": false } } diff --git a/src/app/app-routing.module.ts b/src/app/app-routing.module.ts index 02972627..39b0a119 100644 --- a/src/app/app-routing.module.ts +++ b/src/app/app-routing.module.ts @@ -1,7 +1,14 @@ import { NgModule } from '@angular/core'; import { RouterModule, Routes } from '@angular/router'; +import { ContactlistComponent } from './contacts/contactlist/contactlist.component'; +import { ContactFormComponent } from './contacts/contact-form/contact-form.component'; +import { ContactViewComponent } from './contacts/contact-view/contact-view.component'; -const routes: Routes = []; +const routes: Routes = [ + {path: 'contacts', component: ContactlistComponent}, + {path: 'contact-form', component: ContactFormComponent}, + {path: 'contact/:id', component: ContactViewComponent} +]; @NgModule({ imports: [RouterModule.forRoot(routes)], diff --git a/src/app/app.component.html b/src/app/app.component.html index 17aaa0c6..72855536 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -1,4 +1,4 @@ - +
- +
diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 8207184c..1a271123 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, CommonModule, AppRoutingModule, LayoutModule, ContactsModule], bootstrap: [AppComponent], }) export class AppModule {} diff --git a/src/app/contacts/contact-form/contact-form.component.css b/src/app/contacts/contact-form/contact-form.component.css new file mode 100644 index 00000000..04068da6 --- /dev/null +++ b/src/app/contacts/contact-form/contact-form.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/contact-form/contact-form.component.html b/src/app/contacts/contact-form/contact-form.component.html new file mode 100644 index 00000000..6beb5171 --- /dev/null +++ b/src/app/contacts/contact-form/contact-form.component.html @@ -0,0 +1,19 @@ +

Create Contact

+
+ + + + + + + + + + + + +
+
+ +
+
diff --git a/src/app/contacts/contact-form/contact-form.component.ts b/src/app/contacts/contact-form/contact-form.component.ts new file mode 100644 index 00000000..5a760651 --- /dev/null +++ b/src/app/contacts/contact-form/contact-form.component.ts @@ -0,0 +1,39 @@ +import { Component } from '@angular/core'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; +import { ContactsService } from '../contacts.service'; +import { Router } from '@angular/router'; +import { Contact } from '../models/contact'; + +@Component({ + selector: 'app-contact-form', + standalone: false, + templateUrl: './contact-form.component.html', + styleUrl: './contact-form.component.css' +}) +export class ContactFormComponent { + contactForm: FormGroup; + constructor( + private readonly formBuilder: FormBuilder, + private readonly contactService: ContactsService, + private readonly router: Router + ) { + this.contactForm = this.formBuilder.group({ + firstname: ['', Validators.required], + lastname: ['', Validators.required], + street: ['', Validators.required], + city: ['', Validators.required], + }); + } + addContact(): void { + 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/contact-view/contact-view.component.css b/src/app/contacts/contact-view/contact-view.component.css new file mode 100644 index 00000000..5b84f0f5 --- /dev/null +++ b/src/app/contacts/contact-view/contact-view.component.css @@ -0,0 +1,26 @@ +: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; +} \ No newline at end of file diff --git a/src/app/contacts/contact-view/contact-view.component.html b/src/app/contacts/contact-view/contact-view.component.html new file mode 100644 index 00000000..3c7d35e3 --- /dev/null +++ b/src/app/contacts/contact-view/contact-view.component.html @@ -0,0 +1,33 @@ + +

Contact does not exist!

+
+ + + +

{{ contact?.firstname }} {{ contact?.lastname }}

+

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

+ +
+ + +
+ + + + + + + + + + + + +
+
+ + +
+
+
+
diff --git a/src/app/contacts/contact-view/contact-view.component.ts b/src/app/contacts/contact-view/contact-view.component.ts new file mode 100644 index 00000000..e9ae5537 --- /dev/null +++ b/src/app/contacts/contact-view/contact-view.component.ts @@ -0,0 +1,58 @@ +import { Component } from '@angular/core'; +import { Contact } from '../models/contact'; +import { ActivatedRoute } from '@angular/router'; +import { ContactsService } from '../contacts.service'; +import { FormBuilder, FormGroup, Validators } from '@angular/forms'; + +@Component({ + selector: 'app-contact-view', + standalone: false, + templateUrl: './contact-view.component.html', + styleUrl: './contact-view.component.css' +}) +export class ContactViewComponent { + contact: Contact | null = null; + contactId: number | null = null; + isEditing: boolean = false; + contactForm!: FormGroup; + + constructor( + private route: ActivatedRoute, + private contactService: ContactsService, + private formBuilder: FormBuilder + ) {} + + ngOnInit(): void { + this.contactId = Number(this.route.snapshot.paramMap.get('id')); + + this.contactService.GetContactById(this.contactId).subscribe((data) => { + this.contact = data!; + }); + + if (this.contact) { + this.contactForm = this.formBuilder.group({ + firstname: [this.contact.firstname, Validators.required], + lastname: [this.contact.lastname, Validators.required], + street: [this.contact.street, Validators.required], + city: [this.contact.city, Validators.required] + }) + } + } + + toggleEdit(): void { + this.isEditing = !this.isEditing; + } + + saveChanges(): void{ + if (this.contact && this.contactForm.valid) { + const updatedContact = {id: this.contact.id, ...this.contactForm.value} + + const index = this.contactService.contacts.findIndex(c => c.id === this.contact?.id) + if(index !== -1) { + this.contactService.contacts[index] = updatedContact; + this.contact = updatedContact; + } + this.isEditing = false; + } + } +} diff --git a/src/app/contacts/contactlist/contactlist.component.css b/src/app/contacts/contactlist/contactlist.component.css new file mode 100644 index 00000000..a7943571 --- /dev/null +++ b/src/app/contacts/contactlist/contactlist.component.css @@ -0,0 +1,11 @@ +:host { + padding: 0.5em; + width: 400px; +} + +.contact { + display: flex; + justify-content: space-between; + border-bottom: 1px solid #ddd; + padding: 0.5em 0; +} diff --git a/src/app/contacts/contactlist/contactlist.component.html b/src/app/contacts/contactlist/contactlist.component.html new file mode 100644 index 00000000..845d66db --- /dev/null +++ b/src/app/contacts/contactlist/contactlist.component.html @@ -0,0 +1,15 @@ +

Contacts

+ + +
+
+ {{contact.firstname}} {{contact.lastname}} + + View +
+
+
+ + +
No contacts yet
+
\ No newline at end of file diff --git a/src/app/contacts/contactlist/contactlist.component.ts b/src/app/contacts/contactlist/contactlist.component.ts new file mode 100644 index 00000000..47ffd802 --- /dev/null +++ b/src/app/contacts/contactlist/contactlist.component.ts @@ -0,0 +1,17 @@ +import { Component } from '@angular/core'; +import { Contact } from '../models/contact'; +import { ContactsService } from '../contacts.service'; + +@Component({ + selector: 'app-contactlist', + standalone: false, + templateUrl: './contactlist.component.html', + styleUrl: './contactlist.component.css' +}) +export class ContactlistComponent { + contacts: Contact[]= []; + constructor(private readonly contactService: ContactsService){ + this.contacts = this.contactService.contacts; + console.log("Contacts", this.contacts) + } +} diff --git a/src/app/contacts/contacts.module.ts b/src/app/contacts/contacts.module.ts new file mode 100644 index 00000000..91f0b5a3 --- /dev/null +++ b/src/app/contacts/contacts.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { ContactlistComponent } from './contactlist/contactlist.component'; +import { ContactViewComponent } from './contact-view/contact-view.component'; +import { ContactFormComponent } from './contact-form/contact-form.component'; +import { RouterModule } from '@angular/router'; +import { ReactiveFormsModule } from '@angular/forms'; + +@NgModule({ + declarations: [ContactViewComponent, ContactlistComponent, ContactFormComponent], + imports: [CommonModule, ReactiveFormsModule, RouterModule], + exports: [ContactViewComponent, ContactlistComponent, ContactFormComponent], +}) +export class ContactsModule {} \ No newline at end of file diff --git a/src/app/contacts/contacts.service.ts b/src/app/contacts/contacts.service.ts new file mode 100644 index 00000000..4a4cfd41 --- /dev/null +++ b/src/app/contacts/contacts.service.ts @@ -0,0 +1,31 @@ +import { Injectable } from '@angular/core'; +import { HttpClient } from '@angular/common/http'; +import { Observable, of } from 'rxjs'; + +import { Contact } from './models/contact'; +import { CONTACTS } from './data/contacts'; + +@Injectable({ + providedIn: 'root', +}) +export class ContactsService { + public contacts: Contact[] = CONTACTS; + private lastId:number; + + constructor(){ + this.lastId = this.contacts.length > 0 ? this.contacts[this.contacts.length-1].id ?? 0: 0; + } + + public AddContact(contact: Contact): void { + this.lastId++; + contact.id = this.lastId; + console.log(contact) + this.contacts.push(contact); + } + GetContactById(id: number): Observable { + const contact = this.contacts.find((b) => b.id === id); + return of(contact); + } + + +} \ No newline at end of file diff --git a/src/app/contacts/data/contacts.ts b/src/app/contacts/data/contacts.ts new file mode 100644 index 00000000..4106370e --- /dev/null +++ b/src/app/contacts/data/contacts.ts @@ -0,0 +1,82 @@ +import { Contact } from '../models/contact'; + +export const CONTACTS: Contact[] = [ + { + id: 1, + firstname: 'Anna', + lastname: 'Johansen', + street: 'Storgata 12', + city: 'Oslo' + }, + { + id: 2, + firstname: 'Markus', + lastname: 'Larsen', + street: 'Sjøveien 45', + city: 'Bergen' + }, + { + id: 3, + firstname: 'Ingrid', + lastname: 'Nilsen', + street: 'Solbakken 7', + city: 'Trondheim' + }, + + { + id: 4, + firstname: 'Liam', + lastname: 'Smith', + street: '221B Baker Street', + city: 'London' + }, + { + id: 5, + firstname: 'Sakura', + lastname: 'Tanaka', + street: '3-1 Shibuya Crossing', + city: 'Tokyo' + }, + { + id: 6, + firstname: 'Carlos', + lastname: 'Martínez', + street: 'Calle Mayor 18', + city: 'Madrid' + }, + { + id: 7, + firstname: 'Amira', + lastname: 'Hassan', + street: '12 Al-Muizz Street', + city: 'Cairo' + }, + { + id: 8, + firstname: 'Elena', + lastname: 'Petrova', + street: 'Prospekt Mira 44', + city: 'Moscow' + }, + { + id: 9, + firstname: 'James', + lastname: 'OConnor', + street: '15 Grafton Street', + city: 'Dublin' + }, + { + id: 10, + firstname: 'Lucas', + lastname: 'Müller', + street: 'Hauptstraße 99', + city: 'Berlin' + }, + { + id: 11, + firstname: 'Chloe', + lastname: 'Dupont', + street: 'Rue de Rivoli 32', + city: 'Paris' + } +]; diff --git a/src/app/contacts/models/contact.ts b/src/app/contacts/models/contact.ts new file mode 100644 index 00000000..ba40ffdf --- /dev/null +++ b/src/app/contacts/models/contact.ts @@ -0,0 +1,7 @@ +export interface Contact { + id: number | null; + firstname: string; + lastname: string; + street: string; + city: string; +} \ 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..e9025faa 100644 --- a/src/app/layout/menu/menu.component.html +++ b/src/app/layout/menu/menu.component.html @@ -1,5 +1,5 @@

Menu