added online status & last seen online

This commit is contained in:
Chneemann 2024-05-04 10:46:12 +02:00
parent 17165b933c
commit 25b56d2d9c
9 changed files with 147 additions and 32 deletions

View file

@ -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>

View file

@ -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 {

View file

@ -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;

View file

@ -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>,&nbsp;</span> <span>,&nbsp;</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>

View file

@ -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 {

View file

@ -7,4 +7,6 @@ export interface User {
phone: string; phone: string;
initials: string; initials: string;
color: string; color: string;
status: boolean;
lastLogin: number;
} }

View file

@ -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));
} }

View 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

View 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