frontend: add loading state for room creation with spinner and loading messages
This commit is contained in:
parent
10b3531cf3
commit
275d15f68f
@ -18,21 +18,45 @@
|
||||
|
||||
<main class="wizard-content">
|
||||
<section class="step-content ov-surface">
|
||||
@switch (currentStep()?.id) {
|
||||
@case ('basic') {
|
||||
<ov-room-wizard-basic-info></ov-room-wizard-basic-info>
|
||||
}
|
||||
@case ('recording') {
|
||||
<ov-recording-preferences></ov-recording-preferences>
|
||||
}
|
||||
@case ('recordingTrigger') {
|
||||
<ov-recording-trigger></ov-recording-trigger>
|
||||
}
|
||||
@case ('recordingLayout') {
|
||||
<ov-recording-layout></ov-recording-layout>
|
||||
}
|
||||
@case ('preferences') {
|
||||
<ov-room-preferences></ov-room-preferences>
|
||||
@if (isCreatingRoom()) {
|
||||
<!-- Room Creation Loading State -->
|
||||
<div class="room-creation-loading">
|
||||
<div class="loading-content">
|
||||
<div class="loading-header">
|
||||
<div class="loading-title">
|
||||
<mat-icon class="ov-room-icon loading-icon">video_chat</mat-icon>
|
||||
<h2>{{ editMode ? 'Updating Room' : 'Creating Room' }}</h2>
|
||||
</div>
|
||||
<p class="loading-subtitle">
|
||||
{{
|
||||
editMode
|
||||
? 'Please wait while we update your room settings...'
|
||||
: 'Please wait while we set up your video room...'
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="loading-spinner-container">
|
||||
<mat-spinner diameter="48"></mat-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
} @else {
|
||||
@switch (currentStep()?.id) {
|
||||
@case ('basic') {
|
||||
<ov-room-wizard-basic-info></ov-room-wizard-basic-info>
|
||||
}
|
||||
@case ('recording') {
|
||||
<ov-recording-preferences></ov-recording-preferences>
|
||||
}
|
||||
@case ('recordingTrigger') {
|
||||
<ov-recording-trigger></ov-recording-trigger>
|
||||
}
|
||||
@case ('recordingLayout') {
|
||||
<ov-recording-layout></ov-recording-layout>
|
||||
}
|
||||
@case ('preferences') {
|
||||
<ov-room-preferences></ov-room-preferences>
|
||||
}
|
||||
}
|
||||
}
|
||||
</section>
|
||||
|
||||
@ -77,6 +77,65 @@
|
||||
}
|
||||
}
|
||||
|
||||
// Room Creation Loading State
|
||||
.room-creation-loading {
|
||||
@include ov-flex-center;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
min-height: 400px;
|
||||
text-align: center;
|
||||
padding: var(--ov-meet-spacing-xl);
|
||||
|
||||
.loading-content {
|
||||
@include ov-flex-center;
|
||||
flex-direction: column;
|
||||
gap: var(--ov-meet-spacing-xl);
|
||||
width: 100%;
|
||||
|
||||
.loading-header {
|
||||
margin-bottom: var(--ov-meet-spacing-lg);
|
||||
|
||||
.loading-title {
|
||||
@include ov-flex-center;
|
||||
gap: var(--ov-meet-spacing-md);
|
||||
margin-bottom: var(--ov-meet-spacing-md);
|
||||
|
||||
.loading-icon {
|
||||
@include ov-icon(xl);
|
||||
animation: pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: var(--ov-meet-font-size-xl);
|
||||
font-weight: var(--ov-meet-font-weight-medium);
|
||||
color: var(--ov-meet-text-primary);
|
||||
}
|
||||
}
|
||||
|
||||
.loading-subtitle {
|
||||
font-size: var(--ov-meet-font-size-md);
|
||||
color: var(--ov-meet-text-secondary);
|
||||
margin: 0;
|
||||
animation: fadeIn 1s ease-out 0.5s both;
|
||||
}
|
||||
}
|
||||
|
||||
.loading-spinner-container {
|
||||
mat-spinner {
|
||||
margin: 0 auto;
|
||||
|
||||
::ng-deep {
|
||||
.mdc-circular-progress__determinate-circle,
|
||||
.mdc-circular-progress__indeterminate-circle-graphic {
|
||||
stroke: var(--ov-meet-color-primary);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Responsive design using the system mixins
|
||||
@include ov-tablet-down {
|
||||
.wizard-container {
|
||||
@ -90,6 +149,20 @@
|
||||
font-size: var(--ov-meet-font-size-xl);
|
||||
}
|
||||
}
|
||||
|
||||
.room-creation-loading {
|
||||
padding: var(--ov-meet-spacing-lg);
|
||||
|
||||
.loading-content {
|
||||
.loading-header {
|
||||
.loading-title {
|
||||
h2 {
|
||||
font-size: var(--ov-meet-font-size-lg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@include ov-mobile-down {
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { Component, computed, OnInit, Signal } from '@angular/core';
|
||||
import { Component, computed, OnInit, Signal, signal } from '@angular/core';
|
||||
import { MatButtonModule } from '@angular/material/button';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
import { StepIndicatorComponent, WizardNavComponent } from '@lib/components';
|
||||
import { SpinnerComponent, StepIndicatorComponent, WizardNavComponent } from '@lib/components';
|
||||
import { WizardNavigationConfig, WizardStep } from '@lib/models';
|
||||
import { NavigationService, NotificationService, RoomService, RoomWizardStateService } from '@lib/services';
|
||||
import { MeetRoomOptions } from '@lib/typings/ce';
|
||||
@ -21,8 +22,10 @@ import { RoomPreferencesComponent } from './steps/room-preferences/room-preferen
|
||||
CommonModule,
|
||||
StepIndicatorComponent,
|
||||
WizardNavComponent,
|
||||
SpinnerComponent,
|
||||
MatButtonModule,
|
||||
MatIconModule,
|
||||
MatProgressSpinnerModule,
|
||||
MatSlideToggleModule,
|
||||
RoomWizardBasicInfoComponent,
|
||||
RecordingPreferencesComponent,
|
||||
@ -37,6 +40,7 @@ export class RoomWizardComponent implements OnInit {
|
||||
editMode: boolean = false;
|
||||
roomId?: string;
|
||||
existingRoomData?: MeetRoomOptions;
|
||||
isCreatingRoom = signal(false);
|
||||
|
||||
steps: Signal<WizardStep[]>;
|
||||
currentStep: Signal<WizardStep | undefined>;
|
||||
@ -114,21 +118,27 @@ export class RoomWizardComponent implements OnInit {
|
||||
const roomOptions = this.wizardService.roomOptions();
|
||||
console.log('Wizard completed with data:', roomOptions);
|
||||
|
||||
// Activate loading state
|
||||
this.isCreatingRoom.set(true);
|
||||
|
||||
try {
|
||||
if (this.editMode && this.roomId && roomOptions.preferences) {
|
||||
await this.roomService.updateRoom(this.roomId, roomOptions.preferences);
|
||||
await this.navigationService.navigateTo('rooms', undefined, true);
|
||||
this.notificationService.showSnackbar('Room updated successfully');
|
||||
} else {
|
||||
// Create new room
|
||||
await this.roomService.createRoom(roomOptions);
|
||||
this.notificationService.showSnackbar('Room created successfully');
|
||||
const { moderatorRoomUrl } = await this.roomService.createRoom(roomOptions);
|
||||
await this.navigationService.redirectTo(moderatorRoomUrl);
|
||||
}
|
||||
|
||||
await this.navigationService.navigateTo('rooms', undefined, true);
|
||||
} catch (error) {
|
||||
const errorMessage = `Failed to ${this.editMode ? 'update' : 'create'} room`;
|
||||
this.notificationService.showSnackbar(errorMessage);
|
||||
console.error(errorMessage, error);
|
||||
} finally {
|
||||
this.wizardService.resetWizard();
|
||||
// Deactivate loading state
|
||||
this.isCreatingRoom.set(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user