added & design edit contact component

This commit is contained in:
Chneemann 2024-04-01 16:57:58 +02:00
parent f41f3dcfc7
commit 70422d87be
10 changed files with 303 additions and 27 deletions

View file

@ -5,23 +5,23 @@
<p>Edit contact</p> <p>Edit contact</p>
</div> </div>
<div class="content"> <div class="content">
<div <div class="badge">
class="circle" <div
[ngStyle]="{ class="circle"
'background-color': userService.getUserDetails( [ngStyle]="{
sharedService.currentUserId, 'background-color': userService.getUserDetails(
'color' currentUserId,
) 'color'
}" )
> }"
<div class="initials"> >
{{ <div class="initials">
userService.getUserDetails(sharedService.currentUserId, "initials") {{ userService.getUserDetails(currentUserId, "initials") }}
}} </div>
</div> </div>
</div> </div>
<div class="form"> <div class="form">
<app-contact-form></app-contact-form> <app-contact-form [currentUserId]="currentUserId"></app-contact-form>
</div> </div>
</div> </div>
</div> </div>

View file

@ -61,3 +61,17 @@ section {
} }
} }
} }
.badge {
display: flex;
justify-content: center;
align-items: center;
width: 30%;
}
.form {
display: flex;
justify-content: center;
align-items: center;
width: 70%;
}

View file

@ -12,10 +12,7 @@ import { SharedService } from '../../../services/shared.service';
styleUrl: './contact-edit.component.scss', styleUrl: './contact-edit.component.scss',
}) })
export class ContactEditComponent { export class ContactEditComponent {
@Input() currentUserId!: string | undefined; @Input() currentUserId!: string;
constructor( constructor(public userService: UserService) {}
public userService: UserService,
public sharedService: SharedService
) {}
} }

View file

@ -1 +1,91 @@
<p>contact-form works!</p> <section>
<form
(ngSubmit)="onSubmit(contactForm)"
#contactForm="ngForm"
onsubmit="return false"
class="contact-formular"
>
<div class="name">
<input
id="firstName"
type="text"
class="firstName"
name="firstName"
#firstName="ngModel"
placeholder="{{ contactData.firstName }}"
[(ngModel)]="contactData.firstName"
autocomplete="off"
required
/>
@if (!firstName.valid && firstName.touched) {
<span>{{ "form.invalid-name" | translate }}</span>
}
<input
id="lastName"
type="text"
class="lastName"
name="lastName"
#lastName="ngModel"
placeholder="{{ contactData.lastName }}"
[(ngModel)]="contactData.lastName"
autocomplete="off"
required
/>
@if (!lastName.valid && lastName.touched) {
<span>{{ "form.invalid-name" | translate }}</span>
}
</div>
<input
id="email"
type="email"
name="email"
#email="ngModel"
placeholder="{{ contactData.email }}"
[(ngModel)]="contactData.email"
autocomplete="off"
required
/>
@if (!email.valid && email.touched) {
<span>{{ "form.invalid-email" | translate }}</span>
}
<input
id="phone"
type="phone"
name="phone"
#phone="ngModel"
placeholder="{{ contactData.phone }}"
[(ngModel)]="contactData.phone"
autocomplete="off"
required
/>
@if (!phone.valid && phone.touched) {
<span>{{ "form.invalid-msg" | translate }}</span>
}
<div class="btns">
<div class="btn" (click)="deleteContact()">
<input
class="btn-delete"
type="button"
value="{{ 'form.btn-delete' | translate }}"
/>
</div>
<div class="btn">
<input
class="btn-save"
type="submit"
value="{{ 'form.btn-save' | translate }}"
[disabled]="
firstName.invalid ||
!contactData.firstName ||
lastName.invalid ||
!contactData.lastName ||
email.invalid ||
!contactData.email ||
phone.invalid ||
!contactData.phone
"
/>
</div>
</div>
</form>
</section>

View file

@ -0,0 +1,94 @@
section {
display: flex;
flex-direction: column;
align-items: center;
}
span {
font-size: 14px;
font-weight: 400;
color: red;
padding: 0 0 10px 20px;
}
.name {
display: flex;
}
.contact-formular {
display: flex;
flex-direction: column;
min-width: 480px;
.btn-delete {
padding: 12px;
margin: 12px 12px;
border-radius: 10px;
color: var(--red);
background-color: var(--white);
border: 1px solid var(--red);
font-size: 23px;
font-weight: 400;
cursor: pointer;
&:hover {
color: var(--white);
background-color: var(--red);
border-color: var(--black);
}
}
input {
background-color: var(--white);
border: 1px solid var(--gray);
border-radius: 10px;
font-size: 20px;
font-weight: 400;
padding: 12px;
margin: 12px 12px;
width: 90%;
&:hover {
border-color: var(--light-blue);
}
&:focus {
border-color: var(--light-blue);
outline: none;
}
}
}
.btns {
display: flex;
justify-content: center;
align-items: center;
}
.btn {
display: flex;
flex-direction: column;
align-items: center;
width: 111px;
height: 57px;
margin: 0 24px;
font-size: 21px;
font-weight: 400;
}
.btn-save {
padding: 15px 30px;
margin-top: 12px;
border-radius: 10px;
border-color: var(--black);
background-color: var(--light-gray);
font-size: 23px;
font-weight: 400;
transition: 200ms ease-in-out;
&:hover:not(:disabled) {
background-color: var(--light-blue) !important;
cursor: pointer;
}
&:not(:disabled) {
background-color: var(--very-dark-blue) !important;
color: var(--white);
}
&:hover {
cursor: default;
}
}

View file

@ -1,12 +1,67 @@
import { Component } from '@angular/core'; import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
import { FormsModule, NgForm } from '@angular/forms';
import { TranslateModule } from '@ngx-translate/core';
import { UserService } from '../../../services/user.service';
import { SharedService } from '../../../services/shared.service';
@Component({ @Component({
selector: 'app-contact-form', selector: 'app-contact-form',
standalone: true, standalone: true,
imports: [], imports: [TranslateModule, FormsModule],
templateUrl: './contact-form.component.html', templateUrl: './contact-form.component.html',
styleUrl: './contact-form.component.scss' styleUrl: './contact-form.component.scss',
}) })
export class ContactFormComponent { export class ContactFormComponent implements OnChanges {
@Input() currentUserId!: string;
constructor(
public userService: UserService,
private sharedService: SharedService
) {
this.updateContactData();
}
contactData = {
firstName: '',
lastName: '',
email: '',
phone: '',
};
ngOnChanges(changes: SimpleChanges) {
if (changes['currentUserId']) {
this.updateContactData();
}
}
private updateContactData() {
this.contactData.firstName = this.userService
.getUserDetails(this.currentUserId, 'firstName')
.join(', ');
this.contactData.lastName = this.userService
.getUserDetails(this.currentUserId, 'lastName')
.join(', ');
this.contactData.email = this.userService
.getUserDetails(this.currentUserId, 'email')
.join(', ');
this.contactData.phone = this.userService
.getUserDetails(this.currentUserId, 'phone')
.join(', ');
}
onSubmit(ngForm: NgForm) {
if (ngForm.submitted && ngForm.form.valid) {
this.userService.updateUserData(this.currentUserId, this.contactData);
this.closeEditDialog();
}
}
deleteContact() {
this.closeEditDialog();
}
closeEditDialog() {
this.sharedService.isEditDialogOpen = false;
this.sharedService.isAnyDialogOpen = false;
}
} }

View file

@ -4,8 +4,8 @@ import { Injectable } from '@angular/core';
providedIn: 'root', providedIn: 'root',
}) })
export class SharedService { export class SharedService {
isAnyDialogOpen: boolean = true; isAnyDialogOpen: boolean = false;
isEditDialogOpen: boolean = true; isEditDialogOpen: boolean = false;
currentUserId: string = ''; currentUserId: string = '';
constructor() {} constructor() {}

View file

@ -1,5 +1,11 @@
import { Injectable, OnDestroy, inject } from '@angular/core'; import { Injectable, OnDestroy, inject } from '@angular/core';
import { Firestore, collection, onSnapshot } from '@angular/fire/firestore'; import {
Firestore,
collection,
doc,
onSnapshot,
updateDoc,
} from '@angular/fire/firestore';
import { User } from '../interfaces/user.interface'; import { User } from '../interfaces/user.interface';
@Injectable({ @Injectable({
@ -44,6 +50,15 @@ export class UserService implements OnDestroy {
.map((user) => user[query]); .map((user) => user[query]);
} }
async updateUserData(userId: string, data: any) {
await updateDoc(
doc(collection(this.firestore, 'users'), userId),
data
).catch((err) => {
console.error(err);
});
}
ngOnDestroy() { ngOnDestroy() {
this.unsubUser(); this.unsubUser();
} }

View file

@ -9,6 +9,16 @@
"english": "English", "english": "English",
"german": "German" "german": "German"
}, },
"form": {
"btn-delete": "Delete",
"btn-save": "Save",
"invalid-name": "Your name is required!",
"invalid-email": "Your email is required!",
"invalid-msg": "More than 10 letters are required!",
"invalid-checkbox": "Please accept the privacy policy!",
"msg-send0": "Your message has been sent successfully.",
"msg-send1": "I will contact you shortly."
},
"summary": { "summary": {
"headlineDescription": "Key Metrics at a Glance", "headlineDescription": "Key Metrics at a Glance",
"morning": "Good Morning", "morning": "Good Morning",

View file

@ -10,6 +10,7 @@
--white: #fff; --white: #fff;
--black: #000; --black: #000;
--gray: #a8a8a8; --gray: #a8a8a8;
--red: #ff3d00;
--light-gray: #cdcdcd; --light-gray: #cdcdcd;
--light-blue: #29abe2; --light-blue: #29abe2;
--dark-blue: #2b3647; --dark-blue: #2b3647;