création de groupe début
This commit is contained in:
@@ -107,4 +107,159 @@
|
||||
transform: scale(0.97);
|
||||
box-shadow: 0 1px 5px rgba(180, 80, 80, 0.1);
|
||||
}
|
||||
}
|
||||
|
||||
.mode-switch {
|
||||
margin-top: auto;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
padding: 14px 16px;
|
||||
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
border-radius: 16px;
|
||||
|
||||
backdrop-filter: blur(8px);
|
||||
box-shadow: 0 2px 12px rgba(122, 46, 46, 0.08);
|
||||
}
|
||||
|
||||
.switch-label {
|
||||
color: #7a2e2e;
|
||||
font-weight: 600;
|
||||
font-size: 0.95rem;
|
||||
}
|
||||
|
||||
/* SWITCH */
|
||||
|
||||
.switch {
|
||||
position: relative;
|
||||
width: 58px;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.switch input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.slider {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
border-radius: 999px;
|
||||
|
||||
transition: all 0.25s ease;
|
||||
|
||||
box-shadow:
|
||||
inset 0 1px 3px rgba(0,0,0,0.08),
|
||||
0 2px 8px rgba(0,0,0,0.05);
|
||||
}
|
||||
|
||||
.slider::before {
|
||||
content: "";
|
||||
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
left: 4px;
|
||||
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
|
||||
border-radius: 50%;
|
||||
background: white;
|
||||
|
||||
transition: all 0.25s ease;
|
||||
|
||||
box-shadow:
|
||||
0 2px 8px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.switch input:checked + .slider {
|
||||
background: #bd5a5a;
|
||||
}
|
||||
|
||||
.switch input:checked + .slider::before {
|
||||
transform: translateX(26px);
|
||||
}
|
||||
|
||||
.mode-switch:hover .slider {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
.add-member-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
|
||||
width: 100%;
|
||||
|
||||
padding: 12px 16px;
|
||||
|
||||
border: 2px dashed rgba(189, 90, 90, 0.35);
|
||||
border-radius: 14px;
|
||||
|
||||
background: rgba(255, 255, 255, 0.55);
|
||||
|
||||
color: #bd5a5a;
|
||||
font-size: 0.95rem;
|
||||
font-weight: 600;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
transition: all 0.2s ease;
|
||||
|
||||
ion-icon {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: rgba(255, 255, 255, 0.8);
|
||||
border-color: #bd5a5a;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
|
||||
.remove-btn {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
|
||||
flex-shrink: 0;
|
||||
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
|
||||
background: white;
|
||||
color: #bd5a5a;
|
||||
|
||||
cursor: pointer;
|
||||
|
||||
box-shadow: 0 2px 8px rgba(180, 80, 80, 0.12);
|
||||
|
||||
transition: all 0.2s ease;
|
||||
|
||||
ion-icon {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 4px 12px rgba(180, 80, 80, 0.18);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.92);
|
||||
}
|
||||
}
|
||||
@@ -11,30 +11,91 @@
|
||||
<div class="modal-layout">
|
||||
|
||||
<div class="modal-header">
|
||||
<h2 class="modal-title">Nouvelle conversation</h2>
|
||||
<button class="modal-close-btn" (click)="closeNav()">
|
||||
<ion-icon name="close-outline" />
|
||||
</button>
|
||||
<h2 class="modal-title">{{ isGroup() ? 'Nouveau groupe' : 'Nouvelle conversation' }}</h2>
|
||||
<div class="header-actions">
|
||||
<button class="modal-close-btn" (click)="closeNav()">
|
||||
<ion-icon name="close-outline" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="input-wrapper">
|
||||
<ion-item class="custom-item">
|
||||
<ion-input
|
||||
[formControl]="username"
|
||||
label="Nom d'utilisateur"
|
||||
labelPlacement="floating"
|
||||
placeholder="ex: jean_dupont"
|
||||
/>
|
||||
</ion-item>
|
||||
|
||||
<!-- Mode privé -->
|
||||
<ng-container *ngIf="!isGroup()">
|
||||
<div class="input-wrapper">
|
||||
<ion-item class="custom-item">
|
||||
<ion-input
|
||||
[formControl]="username"
|
||||
label="Nom d'utilisateur"
|
||||
labelPlacement="floating"
|
||||
placeholder="ex: jean_dupont"
|
||||
/>
|
||||
</ion-item>
|
||||
<p class="error-msg" *ngIf="errorMsg()">{{ errorMsg() }}</p>
|
||||
</div>
|
||||
<button class="submit-btn" (click)="startConversation()" [disabled]="isLoading()">
|
||||
{{ isLoading() ? 'Création...' : 'Démarrer la conversation' }}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
<!-- Mode groupe -->
|
||||
<ng-container *ngIf="isGroup()">
|
||||
<div class="input-wrapper">
|
||||
<ion-item class="custom-item">
|
||||
<ion-input
|
||||
[formControl]="groupName"
|
||||
label="Nom du groupe"
|
||||
labelPlacement="floating"
|
||||
placeholder="ex: Les amis"
|
||||
/>
|
||||
</ion-item>
|
||||
</div>
|
||||
|
||||
<div class="members-list">
|
||||
<div class="member-row" *ngFor="let ctrl of groupMembers; let i = index">
|
||||
<ion-item class="custom-item member-item">
|
||||
<ion-input
|
||||
[formControl]="ctrl"
|
||||
label="Membre {{ i + 1 }}"
|
||||
labelPlacement="floating"
|
||||
placeholder="ex: jean_dupont"
|
||||
/>
|
||||
</ion-item>
|
||||
<button class="remove-btn" (click)="removeMember(i)" *ngIf="groupMembers.length > 1">
|
||||
<ion-icon name="close-outline" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="add-member-btn" (click)="addMember()" *ngIf="groupMembers.length < 10">
|
||||
<ion-icon name="add-outline" />
|
||||
Ajouter un membre
|
||||
</button>
|
||||
|
||||
<p class="error-msg" *ngIf="errorMsg()">{{ errorMsg() }}</p>
|
||||
|
||||
<button class="submit-btn" (click)="startGroupConversation()" [disabled]="isLoading()">
|
||||
{{ isLoading() ? 'Création...' : 'Créer le groupe' }}
|
||||
</button>
|
||||
</ng-container>
|
||||
|
||||
<div class="mode-switch">
|
||||
<span class="switch-label">
|
||||
{{ isGroup() ? 'Mode groupe' : 'Conversation privée' }}
|
||||
</span>
|
||||
|
||||
<label class="switch">
|
||||
<input
|
||||
type="checkbox"
|
||||
[checked]="isGroup()"
|
||||
(change)="toggleMode()"
|
||||
>
|
||||
<span class="slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button class="submit-btn" (click)="startConversation()" [disabled]="isLoading()">
|
||||
{{ isLoading() ? 'Création...' : 'Démarrer la conversation' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</ng-template>
|
||||
</ion-modal>
|
||||
@@ -2,14 +2,14 @@ import { Component, inject, signal } from '@angular/core';
|
||||
import { Router } from "@angular/router";
|
||||
import { ReactiveFormsModule, FormControl } from "@angular/forms";
|
||||
import { addIcons } from "ionicons";
|
||||
import { closeOutline } from "ionicons/icons";
|
||||
import { IonIcon, IonInput, IonItem, IonModal } from "@ionic/angular/standalone";
|
||||
import { closeOutline, addOutline } from "ionicons/icons";
|
||||
import { discussionsService } from "../../../core/chat/discussion.service";
|
||||
import { CommonModule } from "@angular/common";
|
||||
import {CommonModule} from "@angular/common";
|
||||
|
||||
@Component({
|
||||
selector: 'app-menu-nav',
|
||||
imports: [CommonModule, IonModal, IonItem, IonInput, IonIcon, ReactiveFormsModule],
|
||||
imports: [IonModal, IonItem, IonInput, IonIcon, ReactiveFormsModule, CommonModule],
|
||||
templateUrl: './menu-nav.component.html',
|
||||
styleUrl: './menu-nav.component.css'
|
||||
})
|
||||
@@ -21,11 +21,17 @@ export class MenuNav {
|
||||
isModalOpen = signal(false);
|
||||
isLoading = signal(false);
|
||||
errorMsg = signal<string | null>(null);
|
||||
isGroup = signal(false);
|
||||
|
||||
// Mode privé
|
||||
username = new FormControl('');
|
||||
|
||||
// Mode groupe
|
||||
groupName = new FormControl('');
|
||||
groupMembers: FormControl[] = [new FormControl('')];
|
||||
|
||||
constructor() {
|
||||
addIcons({ closeOutline });
|
||||
addIcons({ closeOutline, addOutline });
|
||||
}
|
||||
|
||||
openNav() { this.isModalOpen.set(true); }
|
||||
@@ -33,7 +39,25 @@ export class MenuNav {
|
||||
closeNav() {
|
||||
this.isModalOpen.set(false);
|
||||
this.username.reset();
|
||||
this.groupName.reset();
|
||||
this.groupMembers = [new FormControl('')];
|
||||
this.errorMsg.set(null);
|
||||
this.isGroup.set(false);
|
||||
}
|
||||
|
||||
toggleMode() {
|
||||
this.isGroup.update(v => !v);
|
||||
this.errorMsg.set(null);
|
||||
}
|
||||
|
||||
addMember() {
|
||||
if (this.groupMembers.length < 10) {
|
||||
this.groupMembers.push(new FormControl(''));
|
||||
}
|
||||
}
|
||||
|
||||
removeMember(index: number) {
|
||||
this.groupMembers.splice(index, 1);
|
||||
}
|
||||
|
||||
startConversation() {
|
||||
@@ -57,4 +81,30 @@ export class MenuNav {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
startGroupConversation() {
|
||||
const name = this.groupName.value?.trim();
|
||||
const usernames = this.groupMembers
|
||||
.map(c => c.value?.trim())
|
||||
.filter(v => !!v);
|
||||
|
||||
if (!name || usernames.length === 0 || this.isLoading()) return;
|
||||
|
||||
this.isLoading.set(true);
|
||||
this.errorMsg.set(null);
|
||||
|
||||
this.discussionService.createGroupDiscussion(name, usernames).subscribe({
|
||||
next: (discussion) => {
|
||||
this.isLoading.set(false);
|
||||
this.closeNav();
|
||||
this.router.navigate(['/main/messages', discussion.id]);
|
||||
},
|
||||
error: (err) => {
|
||||
this.isLoading.set(false);
|
||||
this.errorMsg.set(
|
||||
err.status === 404 ? 'Un ou plusieurs utilisateurs introuvables.' : 'Une erreur est survenue.'
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user