added & design edit contact component
This commit is contained in:
parent
f41f3dcfc7
commit
70422d87be
10 changed files with 303 additions and 27 deletions
|
|
@ -5,23 +5,23 @@
|
||||||
<p>Edit contact</p>
|
<p>Edit contact</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
|
<div class="badge">
|
||||||
<div
|
<div
|
||||||
class="circle"
|
class="circle"
|
||||||
[ngStyle]="{
|
[ngStyle]="{
|
||||||
'background-color': userService.getUserDetails(
|
'background-color': userService.getUserDetails(
|
||||||
sharedService.currentUserId,
|
currentUserId,
|
||||||
'color'
|
'color'
|
||||||
)
|
)
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div class="initials">
|
<div class="initials">
|
||||||
{{
|
{{ userService.getUserDetails(currentUserId, "initials") }}
|
||||||
userService.getUserDetails(sharedService.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>
|
||||||
|
|
|
||||||
|
|
@ -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%;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
) {}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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() {}
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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",
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue