256 lines
9.2 KiB
HTML
256 lines
9.2 KiB
HTML
<div class="guest-settings-edit-container">
|
|
<!-- Header -->
|
|
<div class="settings-header">
|
|
<div class="header-left">
|
|
<button mat-icon-button (click)="onCancel()" matTooltip="Back to Settings">
|
|
<mat-icon>arrow_back</mat-icon>
|
|
</button>
|
|
<div class="header-title">
|
|
<h1>Edit Guest Settings</h1>
|
|
<p class="subtitle">Configure guest user access and limitations</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Loading State -->
|
|
@if (isLoading() && !settings()) {
|
|
<div class="loading-container">
|
|
<mat-spinner diameter="60"></mat-spinner>
|
|
<p>Loading settings...</p>
|
|
</div>
|
|
}
|
|
|
|
<!-- Error State -->
|
|
@if (error() && !isLoading() && !settings()) {
|
|
<mat-card class="error-card">
|
|
<mat-card-content>
|
|
<div class="error-content">
|
|
<mat-icon color="warn">error_outline</mat-icon>
|
|
<div class="error-text">
|
|
<h3>Failed to Load Settings</h3>
|
|
<p>{{ error() }}</p>
|
|
</div>
|
|
</div>
|
|
<button mat-raised-button color="primary" (click)="onCancel()">
|
|
<mat-icon>arrow_back</mat-icon>
|
|
Go Back
|
|
</button>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
}
|
|
|
|
<!-- Settings Form -->
|
|
@if (settings() || (!isLoading() && settingsForm)) {
|
|
<form [formGroup]="settingsForm" (ngSubmit)="onSubmit()" class="settings-form">
|
|
<!-- Access Control Section -->
|
|
<mat-card class="form-section">
|
|
<mat-card-header>
|
|
<div class="section-icon access">
|
|
<mat-icon>lock_open</mat-icon>
|
|
</div>
|
|
<mat-card-title>Access Control</mat-card-title>
|
|
<mat-card-subtitle>Enable or disable guest access to the platform</mat-card-subtitle>
|
|
</mat-card-header>
|
|
<mat-card-content>
|
|
<div class="toggle-field">
|
|
<div class="toggle-info">
|
|
<label>Guest Access Enabled</label>
|
|
<p class="field-description">Allow users to access the platform without registering</p>
|
|
</div>
|
|
<mat-slide-toggle formControlName="guestAccessEnabled" color="primary">
|
|
</mat-slide-toggle>
|
|
</div>
|
|
@if (!settingsForm.get('guestAccessEnabled')?.value) {
|
|
<div class="warning-banner">
|
|
<mat-icon>warning</mat-icon>
|
|
<span>When disabled, all users must register and login to access the platform.</span>
|
|
</div>
|
|
}
|
|
</mat-card-content>
|
|
</mat-card>
|
|
|
|
<!-- Quiz Limits Section -->
|
|
<mat-card class="form-section">
|
|
<mat-card-header>
|
|
<div class="section-icon limits">
|
|
<mat-icon>rule</mat-icon>
|
|
</div>
|
|
<mat-card-title>Quiz Limits</mat-card-title>
|
|
<mat-card-subtitle>Set daily and per-quiz restrictions for guests</mat-card-subtitle>
|
|
</mat-card-header>
|
|
<mat-card-content>
|
|
<div class="form-row">
|
|
<mat-form-field appearance="outline" class="full-width">
|
|
<mat-label>Max Quizzes Per Day</mat-label>
|
|
<input matInput type="number" formControlName="maxQuizzesPerDay" min="1" max="100">
|
|
<mat-icon matPrefix>calendar_today</mat-icon>
|
|
<mat-hint>Number of quizzes a guest can take per day (1-100)</mat-hint>
|
|
@if (hasError('maxQuizzesPerDay')) {
|
|
<mat-error>{{ getErrorMessage('maxQuizzesPerDay') }}</mat-error>
|
|
}
|
|
</mat-form-field>
|
|
</div>
|
|
|
|
<div class="form-row">
|
|
<mat-form-field appearance="outline" class="full-width">
|
|
<mat-label>Max Questions Per Quiz</mat-label>
|
|
<input matInput type="number" formControlName="maxQuestionsPerQuiz" min="1" max="50">
|
|
<mat-icon matPrefix>quiz</mat-icon>
|
|
<mat-hint>Maximum questions allowed in a single quiz (1-50)</mat-hint>
|
|
@if (hasError('maxQuestionsPerQuiz')) {
|
|
<mat-error>{{ getErrorMessage('maxQuestionsPerQuiz') }}</mat-error>
|
|
}
|
|
</mat-form-field>
|
|
</div>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
|
|
<!-- Session Configuration Section -->
|
|
<mat-card class="form-section">
|
|
<mat-card-header>
|
|
<div class="section-icon session">
|
|
<mat-icon>schedule</mat-icon>
|
|
</div>
|
|
<mat-card-title>Session Configuration</mat-card-title>
|
|
<mat-card-subtitle>Configure guest session duration</mat-card-subtitle>
|
|
</mat-card-header>
|
|
<mat-card-content>
|
|
<div class="form-row">
|
|
<mat-form-field appearance="outline" class="full-width">
|
|
<mat-label>Session Expiry Hours</mat-label>
|
|
<input matInput type="number" formControlName="sessionExpiryHours" min="1" max="168">
|
|
<mat-icon matPrefix>timer</mat-icon>
|
|
<mat-hint>
|
|
How long guest sessions remain active (1-168 hours / 7 days)
|
|
@if (settingsForm.get('sessionExpiryHours')?.value) {
|
|
- {{ formatExpiryTime(settingsForm.get('sessionExpiryHours')?.value) }}
|
|
}
|
|
</mat-hint>
|
|
@if (hasError('sessionExpiryHours')) {
|
|
<mat-error>{{ getErrorMessage('sessionExpiryHours') }}</mat-error>
|
|
}
|
|
</mat-form-field>
|
|
</div>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
|
|
<!-- Upgrade Prompt Section -->
|
|
<mat-card class="form-section">
|
|
<mat-card-header>
|
|
<div class="section-icon message">
|
|
<mat-icon>message</mat-icon>
|
|
</div>
|
|
<mat-card-title>Upgrade Prompt</mat-card-title>
|
|
<mat-card-subtitle>Message shown when guests reach their limit</mat-card-subtitle>
|
|
</mat-card-header>
|
|
<mat-card-content>
|
|
<div class="form-row">
|
|
<mat-form-field appearance="outline" class="full-width">
|
|
<mat-label>Upgrade Prompt Message</mat-label>
|
|
<textarea
|
|
matInput
|
|
formControlName="upgradePromptMessage"
|
|
rows="4"
|
|
maxlength="500"
|
|
></textarea>
|
|
<mat-icon matPrefix>format_quote</mat-icon>
|
|
<mat-hint align="end">
|
|
{{ settingsForm.get('upgradePromptMessage')?.value?.length || 0 }} / 500 characters
|
|
</mat-hint>
|
|
@if (hasError('upgradePromptMessage')) {
|
|
<mat-error>{{ getErrorMessage('upgradePromptMessage') }}</mat-error>
|
|
}
|
|
</mat-form-field>
|
|
</div>
|
|
|
|
<!-- Message Preview -->
|
|
@if (settingsForm.get('upgradePromptMessage')?.value) {
|
|
<div class="message-preview">
|
|
<div class="preview-label">
|
|
<mat-icon>visibility</mat-icon>
|
|
<span>Preview:</span>
|
|
</div>
|
|
<div class="preview-content">
|
|
{{ settingsForm.get('upgradePromptMessage')?.value }}
|
|
</div>
|
|
</div>
|
|
}
|
|
</mat-card-content>
|
|
</mat-card>
|
|
|
|
<!-- Changes Preview -->
|
|
@if (hasUnsavedChanges()) {
|
|
<mat-card class="changes-preview">
|
|
<mat-card-header>
|
|
<div class="section-icon changes">
|
|
<mat-icon>pending_actions</mat-icon>
|
|
</div>
|
|
<mat-card-title>Pending Changes</mat-card-title>
|
|
<mat-card-subtitle>Review changes before saving</mat-card-subtitle>
|
|
</mat-card-header>
|
|
<mat-card-content>
|
|
<div class="changes-list">
|
|
@for (change of getChangesPreview(); track change.label) {
|
|
<div class="change-item">
|
|
<div class="change-label">{{ change.label }}</div>
|
|
<div class="change-values">
|
|
<span class="old-value">{{ change.old }}</span>
|
|
<mat-icon>arrow_forward</mat-icon>
|
|
<span class="new-value">{{ change.new }}</span>
|
|
</div>
|
|
</div>
|
|
}
|
|
</div>
|
|
</mat-card-content>
|
|
</mat-card>
|
|
}
|
|
|
|
<!-- Form Actions -->
|
|
<div class="form-actions">
|
|
<div class="actions-left">
|
|
<button
|
|
mat-stroked-button
|
|
type="button"
|
|
(click)="onReset()"
|
|
[disabled]="isSubmitting || !hasUnsavedChanges()"
|
|
>
|
|
<mat-icon>refresh</mat-icon>
|
|
Reset
|
|
</button>
|
|
</div>
|
|
<div class="actions-right">
|
|
<button
|
|
mat-button
|
|
type="button"
|
|
(click)="onCancel()"
|
|
[disabled]="isSubmitting"
|
|
>
|
|
Cancel
|
|
</button>
|
|
@if (isSubmitting) {
|
|
<button
|
|
mat-raised-button
|
|
color="primary"
|
|
type="submit"
|
|
disabled
|
|
>
|
|
<mat-spinner diameter="20"></mat-spinner>
|
|
Saving...
|
|
</button>
|
|
} @else {
|
|
<button
|
|
mat-raised-button
|
|
color="primary"
|
|
type="submit"
|
|
[disabled]="settingsForm.invalid || !hasUnsavedChanges()"
|
|
>
|
|
<mat-icon>save</mat-icon>
|
|
Save Changes
|
|
</button>
|
|
}
|
|
</div>
|
|
</div>
|
|
</form>
|
|
}
|
|
</div>
|