added online status & last seen online
This commit is contained in:
parent
17165b933c
commit
25b56d2d9c
9 changed files with 147 additions and 32 deletions
|
|
@ -11,7 +11,8 @@
|
||||||
src="./../../../../assets/img/arrow-left.svg"
|
src="./../../../../assets/img/arrow-left.svg"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@if (currentUserId) {
|
@if (currentUserId) { @for (user of checkUserData(currentUserId); track user)
|
||||||
|
{
|
||||||
<div
|
<div
|
||||||
class="contact-details"
|
class="contact-details"
|
||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
|
|
@ -22,20 +23,22 @@
|
||||||
<div
|
<div
|
||||||
class="circle"
|
class="circle"
|
||||||
[ngStyle]="{
|
[ngStyle]="{
|
||||||
'background-color': firebaseService.getUserDetails(
|
'background-color': user.color
|
||||||
currentUserId,
|
|
||||||
'color'
|
|
||||||
)
|
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
@if(user.status) {
|
||||||
|
<img src="./../../../assets/img/online.svg" alt="" />
|
||||||
|
} @else {
|
||||||
|
<img src="./../../../assets/img/offline.svg" alt="" />
|
||||||
|
}
|
||||||
<div class="initials">
|
<div class="initials">
|
||||||
{{ firebaseService.getUserDetails(currentUserId, "initials") }}
|
{{ user.initials }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="word-wrap">
|
<div class="word-wrap">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
{{ firebaseService.getUserDetails(currentUserId, "firstName") }}
|
{{ user.firstName }}
|
||||||
{{ firebaseService.getUserDetails(currentUserId, "lastName") }}
|
{{ user.lastName }}
|
||||||
</div>
|
</div>
|
||||||
<div class="btns">
|
<div class="btns">
|
||||||
<div class="btn btn-edit">
|
<div class="btn btn-edit">
|
||||||
|
|
@ -56,26 +59,22 @@
|
||||||
<div class="headline">Contact Information</div>
|
<div class="headline">Contact Information</div>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<p>Email:</p>
|
<p>Email:</p>
|
||||||
<a
|
<a [href]="'mail:' + user.email">
|
||||||
[href]="
|
{{ user.email }}
|
||||||
'mail:' + firebaseService.getUserDetails(currentUserId, 'email')
|
|
||||||
"
|
|
||||||
>
|
|
||||||
{{ firebaseService.getUserDetails(currentUserId, "email") }}
|
|
||||||
</a>
|
</a>
|
||||||
<p>Phone:</p>
|
<p>Phone:</p>
|
||||||
@if(firebaseService.getUserDetails(currentUserId, 'phone')[0] === '') {
|
@if(user.phone === '') {
|
||||||
<span>no phone</span> } @else {
|
<span>no phone</span> } @else {
|
||||||
<a
|
<a [href]="'tel:' + user.phone">
|
||||||
[href]="
|
<span>{{ user.phone }}</span>
|
||||||
'tel:' + firebaseService.getUserDetails(currentUserId, 'phone')
|
|
||||||
"
|
|
||||||
>
|
|
||||||
<span>{{
|
|
||||||
firebaseService.getUserDetails(currentUserId, "phone")
|
|
||||||
}}</span>
|
|
||||||
</a>
|
</a>
|
||||||
}
|
}
|
||||||
|
<p>Last seen online:</p>
|
||||||
|
@if(user.status) {
|
||||||
|
<span>Currently online</span>
|
||||||
|
} @else {
|
||||||
|
<span>{{ convertTimestamp(user.lastLogin) }}</span>
|
||||||
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -84,5 +83,5 @@
|
||||||
[deleteContact]="deleteContact"
|
[deleteContact]="deleteContact"
|
||||||
[openEditDialog]="openEditDialog"
|
[openEditDialog]="openEditDialog"
|
||||||
></app-contact-nav>
|
></app-contact-nav>
|
||||||
}
|
}}
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
width: 120px;
|
width: 120px;
|
||||||
min-width: 120px;
|
min-width: 120px;
|
||||||
height: 120px;
|
height: 120px;
|
||||||
|
|
@ -59,6 +60,13 @@
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
text-shadow: 1px 1px 2px var(--black);
|
text-shadow: 1px 1px 2px var(--black);
|
||||||
}
|
}
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.word-wrap {
|
.word-wrap {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import { ContactEditComponent } from '../contact-edit/contact-edit.component';
|
||||||
import { SharedService } from '../../../services/shared.service';
|
import { SharedService } from '../../../services/shared.service';
|
||||||
import { ContactNavComponent } from '../contact-nav/contact-nav.component';
|
import { ContactNavComponent } from '../contact-nav/contact-nav.component';
|
||||||
import { FirebaseService } from '../../../services/firebase.service';
|
import { FirebaseService } from '../../../services/firebase.service';
|
||||||
|
import { LanguageService } from '../../../services/language.service';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'app-contact-detail',
|
selector: 'app-contact-detail',
|
||||||
standalone: true,
|
standalone: true,
|
||||||
|
|
@ -26,13 +27,20 @@ export class ContactDetailComponent {
|
||||||
constructor(
|
constructor(
|
||||||
private router: Router,
|
private router: Router,
|
||||||
public sharedService: SharedService,
|
public sharedService: SharedService,
|
||||||
public firebaseService: FirebaseService
|
public firebaseService: FirebaseService,
|
||||||
|
private languageService: LanguageService
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
closeUserDetails() {
|
closeUserDetails() {
|
||||||
this.router.navigate(['contacts']);
|
this.router.navigate(['contacts']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkUserData(userId: string) {
|
||||||
|
return this.firebaseService
|
||||||
|
.getAllUsers()
|
||||||
|
.filter((user) => user.id === userId);
|
||||||
|
}
|
||||||
|
|
||||||
toggleNav() {
|
toggleNav() {
|
||||||
this.isMobileNavbarOpen = !this.isMobileNavbarOpen;
|
this.isMobileNavbarOpen = !this.isMobileNavbarOpen;
|
||||||
}
|
}
|
||||||
|
|
@ -47,6 +55,73 @@ export class ContactDetailComponent {
|
||||||
this.sharedService.isDeleteContactDialogOpen = true;
|
this.sharedService.isDeleteContactDialogOpen = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
convertTimestamp(timestamp: number) {
|
||||||
|
const date = new Date(timestamp);
|
||||||
|
const monthsEN = [
|
||||||
|
'Jan',
|
||||||
|
'Feb',
|
||||||
|
'Mar',
|
||||||
|
'Apr',
|
||||||
|
'May',
|
||||||
|
'Jun',
|
||||||
|
'Jul',
|
||||||
|
'Aug',
|
||||||
|
'Sep',
|
||||||
|
'Oct',
|
||||||
|
'Nov',
|
||||||
|
'Dec',
|
||||||
|
];
|
||||||
|
const monthsDE = [
|
||||||
|
'Jan',
|
||||||
|
'Feb',
|
||||||
|
'Mär',
|
||||||
|
'Apr',
|
||||||
|
'Mai',
|
||||||
|
'Jun',
|
||||||
|
'Jul',
|
||||||
|
'Aug',
|
||||||
|
'Sep',
|
||||||
|
'Okt',
|
||||||
|
'Nov',
|
||||||
|
'Dez',
|
||||||
|
];
|
||||||
|
const months =
|
||||||
|
this.languageService.currentLang === 'de' ? monthsDE : monthsEN;
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = months[date.getMonth()];
|
||||||
|
const day = date.getDate();
|
||||||
|
|
||||||
|
if (this.languageService.currentLang === 'de') {
|
||||||
|
const time = `${day}. ${month}. ${year}`;
|
||||||
|
return `${time} - ${this.convertTimestampHourDE(timestamp)}`;
|
||||||
|
} else {
|
||||||
|
const time = `${month}. ${day}, ${year}`;
|
||||||
|
return `${time} - ${this.convertTimestampHourEN(timestamp)}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
convertTimestampHourEN(timestamp: number) {
|
||||||
|
const date = new Date(timestamp * 1000);
|
||||||
|
let hour = date.getHours();
|
||||||
|
const minute = ('0' + date.getMinutes()).slice(-2);
|
||||||
|
const second = ('0' + date.getMinutes()).slice(-2);
|
||||||
|
const period = hour >= 12 ? 'PM' : 'AM';
|
||||||
|
hour = hour % 12 || 12;
|
||||||
|
|
||||||
|
let hourWithNull = ('0' + hour).slice(-2);
|
||||||
|
|
||||||
|
return `${hourWithNull}:${minute}:${second} ${period}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
convertTimestampHourDE(timestamp: number) {
|
||||||
|
const date = new Date(timestamp * 1000);
|
||||||
|
let hour = date.getHours();
|
||||||
|
const minute = ('0' + date.getMinutes()).slice(-2);
|
||||||
|
const second = ('0' + date.getMinutes()).slice(-2);
|
||||||
|
|
||||||
|
return `${hour}:${minute}:${second} Uhr`;
|
||||||
|
}
|
||||||
|
|
||||||
@HostListener('document:click', ['$event'])
|
@HostListener('document:click', ['$event'])
|
||||||
checkOpenContactEdit(event: MouseEvent) {
|
checkOpenContactEdit(event: MouseEvent) {
|
||||||
const targetElement = event.target as HTMLElement;
|
const targetElement = event.target as HTMLElement;
|
||||||
|
|
|
||||||
|
|
@ -28,25 +28,30 @@
|
||||||
<div
|
<div
|
||||||
class="circle"
|
class="circle"
|
||||||
[ngStyle]="{
|
[ngStyle]="{
|
||||||
'background-color': firebaseService.getUserDetails(user.id, 'color')
|
'background-color': user.color
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
@if(user.status) {
|
||||||
|
<img src="./../../../assets/img/online.svg" alt="" />
|
||||||
|
} @else {
|
||||||
|
<img src="./../../../assets/img/offline.svg" alt="" />
|
||||||
|
}
|
||||||
<div class="initials">
|
<div class="initials">
|
||||||
{{ firebaseService.getUserDetails(user.id, "initials") }}
|
{{ user.initials }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="details">
|
<div class="details">
|
||||||
<div class="name">
|
<div class="name">
|
||||||
<p>
|
<p>
|
||||||
{{ firebaseService.getUserDetails(user.id, "firstName") }}
|
{{ user.firstName }}
|
||||||
</p>
|
</p>
|
||||||
<span>, </span>
|
<span>, </span>
|
||||||
<p class="last-name">
|
<p class="last-name">
|
||||||
{{ firebaseService.getUserDetails(user.id, "lastName") }}
|
{{ user.lastName }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="email">
|
<div class="email">
|
||||||
{{ firebaseService.getUserDetails(user.id, "email") }}
|
{{ user.email }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -97,6 +97,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
position: relative;
|
||||||
width: 42px;
|
width: 42px;
|
||||||
min-width: 42px;
|
min-width: 42px;
|
||||||
height: 42px;
|
height: 42px;
|
||||||
|
|
@ -108,6 +109,13 @@
|
||||||
color: var(--white);
|
color: var(--white);
|
||||||
text-shadow: 1px 1px 2px var(--black);
|
text-shadow: 1px 1px 2px var(--black);
|
||||||
}
|
}
|
||||||
|
img {
|
||||||
|
position: absolute;
|
||||||
|
width: 12px;
|
||||||
|
height: 12px;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.details {
|
.details {
|
||||||
|
|
|
||||||
|
|
@ -7,4 +7,6 @@ export interface User {
|
||||||
phone: string;
|
phone: string;
|
||||||
initials: string;
|
initials: string;
|
||||||
color: string;
|
color: string;
|
||||||
|
status: boolean;
|
||||||
|
lastLogin: number;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import {
|
||||||
GoogleAuthProvider,
|
GoogleAuthProvider,
|
||||||
} from 'firebase/auth';
|
} from 'firebase/auth';
|
||||||
import { FirebaseService } from './firebase.service';
|
import { FirebaseService } from './firebase.service';
|
||||||
import { Firestore } from '@angular/fire/firestore';
|
import { Firestore, collection, doc, updateDoc } from '@angular/fire/firestore';
|
||||||
import { SharedService } from './shared.service';
|
import { SharedService } from './shared.service';
|
||||||
@Injectable({
|
@Injectable({
|
||||||
providedIn: 'root',
|
providedIn: 'root',
|
||||||
|
|
@ -28,7 +28,9 @@ export class LoginService {
|
||||||
this.getUserIdInLocalStorage(
|
this.getUserIdInLocalStorage(
|
||||||
this.firebaseService.checkUserUID(user.uid)[0].id
|
this.firebaseService.checkUserUID(user.uid)[0].id
|
||||||
);
|
);
|
||||||
window.location.reload();
|
this.updateUserOnlineStatus(
|
||||||
|
this.firebaseService.checkUserUID(user.uid)[0].id
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
console.error('No user with this UID was found!');
|
console.error('No user with this UID was found!');
|
||||||
}
|
}
|
||||||
|
|
@ -60,6 +62,16 @@ export class LoginService {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async updateUserOnlineStatus(userId: string) {
|
||||||
|
await updateDoc(doc(collection(this.firestore, 'users'), userId), {
|
||||||
|
status: true,
|
||||||
|
lastLogin: new Date().getTime(),
|
||||||
|
}).catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
window.location.reload();
|
||||||
|
}
|
||||||
|
|
||||||
getUserIdInLocalStorage(userId: string) {
|
getUserIdInLocalStorage(userId: string) {
|
||||||
localStorage.setItem('currentUser', JSON.stringify(userId));
|
localStorage.setItem('currentUser', JSON.stringify(userId));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
3
src/assets/img/offline.svg
Normal file
3
src/assets/img/offline.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="6.99976" cy="7" r="6" fill="#686868" stroke="white" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 185 B |
3
src/assets/img/online.svg
Normal file
3
src/assets/img/online.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle cx="6.99976" cy="7" r="6" fill="#92C83E" stroke="white" stroke-width="2"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 186 B |
Loading…
Reference in a new issue