Add validation and error handling for room creation form in MultiChatDialog: Implement input validation for room name, age restrictions, password, and access rights. Enhance UI with error messages and disable button when validation fails.
This commit is contained in:
@@ -63,7 +63,9 @@
|
|||||||
<div class="room-create-grid">
|
<div class="room-create-grid">
|
||||||
<label>
|
<label>
|
||||||
Raumname *
|
Raumname *
|
||||||
<input v-model.trim="roomCreateForm.roomName" type="text" placeholder="z. B. Lounge" />
|
<input v-model.trim="roomCreateForm.roomName" type="text" placeholder="z. B. Lounge"
|
||||||
|
:class="{ 'invalid-input': roomCreateValidation.roomName }" />
|
||||||
|
<span v-if="roomCreateValidation.roomName" class="room-create-error">{{ roomCreateValidation.roomName }}</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Sichtbarkeit
|
Sichtbarkeit
|
||||||
@@ -92,23 +94,33 @@
|
|||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
min_age
|
min_age
|
||||||
<input v-model.number="roomCreateForm.minAge" type="number" min="0" />
|
<input v-model.number="roomCreateForm.minAge" type="number" min="0"
|
||||||
|
:class="{ 'invalid-input': roomCreateValidation.minAge }" />
|
||||||
|
<span v-if="roomCreateValidation.minAge" class="room-create-error">{{ roomCreateValidation.minAge }}</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
max_age
|
max_age
|
||||||
<input v-model.number="roomCreateForm.maxAge" type="number" min="0" />
|
<input v-model.number="roomCreateForm.maxAge" type="number" min="0"
|
||||||
|
:class="{ 'invalid-input': roomCreateValidation.maxAge }" />
|
||||||
|
<span v-if="roomCreateValidation.maxAge" class="room-create-error">{{ roomCreateValidation.maxAge }}</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
Passwort
|
Passwort
|
||||||
<input v-model.trim="roomCreateForm.password" type="text" placeholder="ohne Leerzeichen" />
|
<input v-model.trim="roomCreateForm.password" type="text" placeholder="ohne Leerzeichen"
|
||||||
|
:class="{ 'invalid-input': roomCreateValidation.password }" />
|
||||||
|
<span v-if="roomCreateValidation.password" class="room-create-error">{{ roomCreateValidation.password }}</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
right_id
|
right_id
|
||||||
<input v-model.number="roomCreateForm.rightId" type="number" min="1" />
|
<input v-model.number="roomCreateForm.rightId" type="number" min="1"
|
||||||
|
:class="{ 'invalid-input': roomCreateValidation.rightId }" />
|
||||||
|
<span v-if="roomCreateValidation.rightId" class="room-create-error">{{ roomCreateValidation.rightId }}</span>
|
||||||
</label>
|
</label>
|
||||||
<label>
|
<label>
|
||||||
type_id
|
type_id
|
||||||
<input v-model.number="roomCreateForm.typeId" type="number" min="1" />
|
<input v-model.number="roomCreateForm.typeId" type="number" min="1"
|
||||||
|
:class="{ 'invalid-input': roomCreateValidation.typeId }" />
|
||||||
|
<span v-if="roomCreateValidation.typeId" class="room-create-error">{{ roomCreateValidation.typeId }}</span>
|
||||||
</label>
|
</label>
|
||||||
<label class="checkbox-label">
|
<label class="checkbox-label">
|
||||||
<input type="checkbox" v-model="roomCreateForm.friendsOnly" />
|
<input type="checkbox" v-model="roomCreateForm.friendsOnly" />
|
||||||
@@ -116,9 +128,10 @@
|
|||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="room-create-actions">
|
<div class="room-create-actions">
|
||||||
<button type="button" class="send-btn" @click="sendCreateRoomCommand">Raum erstellen</button>
|
<button type="button" class="send-btn" @click="sendCreateRoomCommand" :disabled="!canSendRoomCreate">Raum erstellen</button>
|
||||||
<button type="button" class="create-room-reset-btn" @click="resetRoomCreateForm">Zurücksetzen</button>
|
<button type="button" class="create-room-reset-btn" @click="resetRoomCreateForm">Zurücksetzen</button>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="roomCreateValidation.range" class="room-create-error room-create-error-block">{{ roomCreateValidation.range }}</div>
|
||||||
<div class="room-create-preview">
|
<div class="room-create-preview">
|
||||||
Kommando: <code>{{ buildRoomCreateCommandPreview() || '/cr <raumname>' }}</code>
|
Kommando: <code>{{ buildRoomCreateCommandPreview() || '/cr <raumname>' }}</code>
|
||||||
</div>
|
</div>
|
||||||
@@ -200,6 +213,30 @@ export default {
|
|||||||
try {
|
try {
|
||||||
return !!(this.menu && this.menu.administration);
|
return !!(this.menu && this.menu.administration);
|
||||||
} catch (_) { return false; }
|
} catch (_) { return false; }
|
||||||
|
},
|
||||||
|
roomCreateValidation() {
|
||||||
|
const errors = {};
|
||||||
|
const name = (this.roomCreateForm.roomName || '').trim();
|
||||||
|
const minAge = this.parseOptionalInteger(this.roomCreateForm.minAge);
|
||||||
|
const maxAge = this.parseOptionalInteger(this.roomCreateForm.maxAge);
|
||||||
|
const rightId = this.parseOptionalInteger(this.roomCreateForm.rightId);
|
||||||
|
const typeId = this.parseOptionalInteger(this.roomCreateForm.typeId);
|
||||||
|
const password = this.roomCreateForm.password || '';
|
||||||
|
|
||||||
|
if (!name) errors.roomName = 'Raumname ist erforderlich.';
|
||||||
|
if (minAge !== null && minAge < 0) errors.minAge = 'min_age muss >= 0 sein.';
|
||||||
|
if (maxAge !== null && maxAge < 0) errors.maxAge = 'max_age muss >= 0 sein.';
|
||||||
|
if (minAge !== null && maxAge !== null && minAge > maxAge) {
|
||||||
|
errors.range = 'min_age darf nicht größer als max_age sein.';
|
||||||
|
}
|
||||||
|
if (password.includes(' ')) errors.password = 'Passwort darf keine Leerzeichen enthalten.';
|
||||||
|
if (rightId !== null && rightId <= 0) errors.rightId = 'right_id muss > 0 sein.';
|
||||||
|
if (typeId !== null && typeId <= 0) errors.typeId = 'type_id muss > 0 sein.';
|
||||||
|
|
||||||
|
return errors;
|
||||||
|
},
|
||||||
|
canSendRoomCreate() {
|
||||||
|
return Object.keys(this.roomCreateValidation).length === 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@@ -332,6 +369,12 @@ export default {
|
|||||||
buildRoomCreateCommandPreview() {
|
buildRoomCreateCommandPreview() {
|
||||||
return this.buildRoomCreateCommand();
|
return this.buildRoomCreateCommand();
|
||||||
},
|
},
|
||||||
|
parseOptionalInteger(value) {
|
||||||
|
if (value === null || value === undefined || value === '') return null;
|
||||||
|
const num = Number(value);
|
||||||
|
if (!Number.isFinite(num)) return null;
|
||||||
|
return Math.trunc(num);
|
||||||
|
},
|
||||||
buildRoomCreateCommand() {
|
buildRoomCreateCommand() {
|
||||||
const name = (this.roomCreateForm.roomName || '').trim();
|
const name = (this.roomCreateForm.roomName || '').trim();
|
||||||
if (!name) return '';
|
if (!name) return '';
|
||||||
@@ -341,20 +384,24 @@ export default {
|
|||||||
parts.push(`public=${this.roomCreateForm.publicFlag}`);
|
parts.push(`public=${this.roomCreateForm.publicFlag}`);
|
||||||
}
|
}
|
||||||
if (this.roomCreateForm.gender) parts.push(`gender=${this.roomCreateForm.gender}`);
|
if (this.roomCreateForm.gender) parts.push(`gender=${this.roomCreateForm.gender}`);
|
||||||
if (Number.isInteger(this.roomCreateForm.minAge) && this.roomCreateForm.minAge >= 0) {
|
const minAge = this.parseOptionalInteger(this.roomCreateForm.minAge);
|
||||||
parts.push(`min_age=${this.roomCreateForm.minAge}`);
|
if (minAge !== null && minAge >= 0) {
|
||||||
|
parts.push(`min_age=${minAge}`);
|
||||||
}
|
}
|
||||||
if (Number.isInteger(this.roomCreateForm.maxAge) && this.roomCreateForm.maxAge >= 0) {
|
const maxAge = this.parseOptionalInteger(this.roomCreateForm.maxAge);
|
||||||
parts.push(`max_age=${this.roomCreateForm.maxAge}`);
|
if (maxAge !== null && maxAge >= 0) {
|
||||||
|
parts.push(`max_age=${maxAge}`);
|
||||||
}
|
}
|
||||||
const password = (this.roomCreateForm.password || '').trim();
|
const password = (this.roomCreateForm.password || '').trim();
|
||||||
if (password) parts.push(`password=${password}`);
|
if (password) parts.push(`password=${password}`);
|
||||||
if (this.roomCreateForm.friendsOnly) parts.push('friends_only=true');
|
if (this.roomCreateForm.friendsOnly) parts.push('friends_only=true');
|
||||||
if (Number.isInteger(this.roomCreateForm.rightId) && this.roomCreateForm.rightId > 0) {
|
const rightId = this.parseOptionalInteger(this.roomCreateForm.rightId);
|
||||||
parts.push(`right_id=${this.roomCreateForm.rightId}`);
|
if (rightId !== null && rightId > 0) {
|
||||||
|
parts.push(`right_id=${rightId}`);
|
||||||
}
|
}
|
||||||
if (Number.isInteger(this.roomCreateForm.typeId) && this.roomCreateForm.typeId > 0) {
|
const typeId = this.parseOptionalInteger(this.roomCreateForm.typeId);
|
||||||
parts.push(`type_id=${this.roomCreateForm.typeId}`);
|
if (typeId !== null && typeId > 0) {
|
||||||
|
parts.push(`type_id=${typeId}`);
|
||||||
}
|
}
|
||||||
return parts.join(' ');
|
return parts.join(' ');
|
||||||
},
|
},
|
||||||
@@ -371,15 +418,15 @@ export default {
|
|||||||
this.messages.push({ id: Date.now(), user: 'System', text: 'Keine Verbindung zum Chat-Server.' });
|
this.messages.push({ id: Date.now(), user: 'System', text: 'Keine Verbindung zum Chat-Server.' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (!this.canSendRoomCreate) {
|
||||||
|
this.messages.push({ id: Date.now(), user: 'System', text: 'Bitte Eingaben im Raum-Formular korrigieren.' });
|
||||||
|
return;
|
||||||
|
}
|
||||||
const command = this.buildRoomCreateCommand();
|
const command = this.buildRoomCreateCommand();
|
||||||
if (!command) {
|
if (!command) {
|
||||||
this.messages.push({ id: Date.now(), user: 'System', text: 'Bitte einen Raumnamen angeben.' });
|
this.messages.push({ id: Date.now(), user: 'System', text: 'Bitte einen Raumnamen angeben.' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ((this.roomCreateForm.password || '').includes(' ')) {
|
|
||||||
this.messages.push({ id: Date.now(), user: 'System', text: 'Passwort darf keine Leerzeichen enthalten.' });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const payload = { type: 'message', message: command };
|
const payload = { type: 'message', message: command };
|
||||||
if (this.debug) console.log('[Chat WS >>]', payload);
|
if (this.debug) console.log('[Chat WS >>]', payload);
|
||||||
this.sendWithToken(payload);
|
this.sendWithToken(payload);
|
||||||
@@ -1800,6 +1847,11 @@ export default {
|
|||||||
padding: 0.35em 0.5em;
|
padding: 0.35em 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.invalid-input {
|
||||||
|
border-color: #c62828 !important;
|
||||||
|
background: #fff6f6;
|
||||||
|
}
|
||||||
|
|
||||||
.checkbox-label {
|
.checkbox-label {
|
||||||
flex-direction: row !important;
|
flex-direction: row !important;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
@@ -1826,6 +1878,15 @@ export default {
|
|||||||
color: #444;
|
color: #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.room-create-error {
|
||||||
|
color: #b00020;
|
||||||
|
font-size: 0.85em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.room-create-error-block {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
.chat-message {
|
.chat-message {
|
||||||
margin-bottom: 0.3em;
|
margin-bottom: 0.3em;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user