avancement planning
This commit is contained in:
@@ -204,16 +204,18 @@
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-cell-inner {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
border-radius: 8px;
|
||||
margin: 0 auto;
|
||||
width: calc(100% - 4px) !important;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
border-radius: 6px;
|
||||
margin: 0 2px;
|
||||
color: var(--ugly-yellow);
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
transition: all 0.2s ease;
|
||||
background: transparent;
|
||||
display: block;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-cell:hover .ant-picker-cell-inner {
|
||||
@@ -636,4 +638,268 @@
|
||||
font-weight: 600;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
/* Jour sélectionné */
|
||||
.day-header {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.day-header.selected-day:not(.today) {
|
||||
background: rgba(212, 165, 116, 0.15);
|
||||
border-bottom: 3px solid var(--ugly-yellow);
|
||||
}
|
||||
|
||||
/* Événements show dans la grille */
|
||||
.show-event {
|
||||
background: linear-gradient(135deg, var(--mauve) 0%, #8b7ba8 100%);
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
padding: 2px 5px;
|
||||
font-size: 10px;
|
||||
width: 100%;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 2px;
|
||||
box-shadow: 0 1px 4px rgba(106, 90, 139, 0.3);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.show-event-name {
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.show-event-time {
|
||||
font-size: 9px;
|
||||
opacity: 0.85;
|
||||
}
|
||||
|
||||
/* Show cards dans la sidebar */
|
||||
.show-card {
|
||||
background: white;
|
||||
border-radius: 8px;
|
||||
padding: 10px;
|
||||
margin-bottom: 8px;
|
||||
border-left: 3px solid var(--mauve);
|
||||
}
|
||||
|
||||
.show-card:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.show-card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.show-card-header strong {
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.show-time {
|
||||
font-size: 11px;
|
||||
color: var(--mauve);
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.show-card p {
|
||||
font-size: 11px;
|
||||
color: #777;
|
||||
margin: 2px 0 0 0;
|
||||
}
|
||||
|
||||
.no-shows {
|
||||
font-size: 12px;
|
||||
color: #bbb;
|
||||
font-style: italic;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* ─── Formulaire de création ─────────────────────────────── */
|
||||
|
||||
.create-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
padding: 28px;
|
||||
}
|
||||
|
||||
.create-form-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 14px;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 2px solid #f5ede3;
|
||||
}
|
||||
|
||||
.create-form-icon {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: linear-gradient(135deg, var(--ugly-yellow) 0%, #c49563 100%);
|
||||
border-radius: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 4px 12px rgba(212, 165, 116, 0.35);
|
||||
}
|
||||
|
||||
.create-form-title h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
color: #2d2d2d;
|
||||
margin: 0 0 2px 0;
|
||||
}
|
||||
|
||||
.create-form-title p {
|
||||
font-size: 12px;
|
||||
color: #aaa;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.form-row-2 {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.form-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 7px;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
color: #999;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.7px;
|
||||
}
|
||||
|
||||
.form-required {
|
||||
color: var(--ugly-yellow);
|
||||
}
|
||||
|
||||
.form-input {
|
||||
border: 2px solid #ede8e2;
|
||||
border-radius: 10px;
|
||||
padding: 11px 14px;
|
||||
font-size: 13px;
|
||||
font-family: 'Be Vietnam Pro', sans-serif;
|
||||
outline: none;
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease;
|
||||
background: #fafaf8;
|
||||
color: #333;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
border-color: var(--ugly-yellow);
|
||||
background: white;
|
||||
box-shadow: 0 0 0 3px rgba(212, 165, 116, 0.12);
|
||||
}
|
||||
|
||||
.form-input::placeholder {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.form-textarea {
|
||||
resize: none;
|
||||
min-height: 80px;
|
||||
}
|
||||
|
||||
/* nz-date-picker dans le formulaire */
|
||||
.form-datepicker-wrap ::ng-deep .ant-picker {
|
||||
border: 2px solid #ede8e2 !important;
|
||||
border-radius: 10px !important;
|
||||
background: #fafaf8 !important;
|
||||
height: 44px !important;
|
||||
font-family: 'Be Vietnam Pro', sans-serif !important;
|
||||
width: 100% !important;
|
||||
transition: border-color 0.2s ease, box-shadow 0.2s ease !important;
|
||||
box-sizing: border-box !important;
|
||||
}
|
||||
|
||||
.form-datepicker-wrap ::ng-deep .ant-picker:hover,
|
||||
.form-datepicker-wrap ::ng-deep .ant-picker-focused {
|
||||
border-color: var(--ugly-yellow) !important;
|
||||
box-shadow: 0 0 0 3px rgba(212, 165, 116, 0.12) !important;
|
||||
}
|
||||
|
||||
.form-datepicker-wrap ::ng-deep .ant-picker-input > input {
|
||||
font-family: 'Be Vietnam Pro', sans-serif !important;
|
||||
font-size: 13px !important;
|
||||
color: #333 !important;
|
||||
}
|
||||
|
||||
.form-datepicker-wrap ::ng-deep .ant-picker-input > input::placeholder {
|
||||
color: #ccc !important;
|
||||
}
|
||||
|
||||
.form-datepicker-wrap ::ng-deep .ant-picker-suffix {
|
||||
color: var(--ugly-yellow) !important;
|
||||
}
|
||||
|
||||
/* Boutons du formulaire */
|
||||
.form-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
padding-top: 16px;
|
||||
border-top: 2px solid #f5f0ea;
|
||||
}
|
||||
|
||||
.form-btn-cancel {
|
||||
padding: 11px 22px;
|
||||
border: 2px solid #e5dfd7;
|
||||
background: white;
|
||||
border-radius: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
color: #aaa;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
font-family: 'Be Vietnam Pro', sans-serif;
|
||||
}
|
||||
|
||||
.form-btn-cancel:hover {
|
||||
border-color: #bbb;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.form-btn-submit {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 7px;
|
||||
padding: 11px 22px;
|
||||
background: linear-gradient(135deg, var(--ugly-yellow) 0%, #c49563 100%);
|
||||
border: none;
|
||||
border-radius: 10px;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
box-shadow: 0 3px 12px rgba(212, 165, 116, 0.35);
|
||||
font-family: 'Be Vietnam Pro', sans-serif;
|
||||
}
|
||||
|
||||
.form-btn-submit:hover:not(:disabled) {
|
||||
box-shadow: 0 5px 16px rgba(212, 165, 116, 0.5);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.form-btn-submit:disabled {
|
||||
opacity: 0.5;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
<div class="background">
|
||||
<div class="planning">
|
||||
<div class="left">
|
||||
<!-- Planning de la semaine au centre -->
|
||||
<div class="week-section" *ngIf="selectedDates.length > 0">
|
||||
<div class="week-section">
|
||||
<div class="week-toolbar">
|
||||
<div class="week-actions">
|
||||
<button [class]="isCamionFilterActive ? 'action-btn active' : 'action-btn'"
|
||||
@@ -17,8 +16,7 @@
|
||||
</button>
|
||||
<button [class]="isShowFilterActive ? 'action-btn active' : 'action-btn'" (click)="showFilter()">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<circle cx="11" cy="11" r="8" stroke-width="2"/>
|
||||
<path d="M21 21l-4.35-4.35" stroke-width="2" stroke-linecap="round"/>
|
||||
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" stroke-width="2"/>
|
||||
</svg>
|
||||
Show
|
||||
</button>
|
||||
@@ -30,9 +28,7 @@
|
||||
stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="today-btn" (click)="goToToday()">
|
||||
Aujourd'hui
|
||||
</button>
|
||||
<button class="today-btn" (click)="goToToday()">Aujourd'hui</button>
|
||||
<button class="nav-button-week" (click)="nextWeek()">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M9 18L15 12L9 6" stroke="#666" stroke-width="2" stroke-linecap="round"
|
||||
@@ -44,134 +40,202 @@
|
||||
|
||||
<div class="week-calendar">
|
||||
<div class="week-grid">
|
||||
<!-- Colonne des heures -->
|
||||
<div class="time-column">
|
||||
<div class="time-header"></div>
|
||||
<div class="time-slot" *ngFor="let hour of getHours()">
|
||||
{{ hour }}
|
||||
</div>
|
||||
<div class="time-slot" *ngFor="let hour of getHours()">{{ hour }}</div>
|
||||
</div>
|
||||
|
||||
<!-- Colonnes des jours -->
|
||||
<div class="day-column" *ngFor="let date of selectedDates">
|
||||
<div class="day-header" [class.today]="isToday(date)">
|
||||
<div class="day-header"
|
||||
[class.today]="isToday(date)"
|
||||
[class.selected-day]="isDaySelected(date)"
|
||||
(click)="selectDay(date)">
|
||||
<div class="day-name">{{ getDayName(date) }}</div>
|
||||
<div class="day-date">{{ date.getDate() }}</div>
|
||||
</div>
|
||||
<div class="day-slots">
|
||||
<div class="hour-slot"
|
||||
*ngFor="let hour of getHours()"
|
||||
(click)="selectSlot(date, hour)"
|
||||
[class.selected]="isSlotSelected(date, hour)">
|
||||
<div class="slot-indicator" *ngIf="isSlotSelected(date, hour)"></div>
|
||||
(click)="selectDay(date)">
|
||||
@for (show of getShowsForSlot(date, hour); track show.id) {
|
||||
<div class="show-event">
|
||||
<span class="show-event-name">{{ show.name }}</span>
|
||||
<span class="show-event-time" *ngIf="show.date">{{ formatShowTime(show.date) }}</span>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Message si aucune semaine sélectionnée -->
|
||||
<div *ngIf="selectedDates.length === 0" class="week-section empty-state">
|
||||
<div class="empty-message">
|
||||
<p>Sélectionnez une date dans le calendrier</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="right">
|
||||
<div class="calendar-section">
|
||||
<div class="calendar-title">CALENDRIER</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="calendar-header">
|
||||
<button class="nav-button" (click)="previousMonth()">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M15 18L9 12L15 6" stroke="#d4a574" stroke-width="2" stroke-linecap="round"
|
||||
stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<h2 class="month-title">{{ currentMonthYear }}</h2>
|
||||
<button class="nav-button" (click)="nextMonth()">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M9 18L15 12L9 6" stroke="#d4a574" stroke-width="2" stroke-linecap="round"
|
||||
stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<nz-calendar
|
||||
[nzFullscreen]="false"
|
||||
[ngModel]="currentDate"
|
||||
(nzSelectChange)="onValueChange($event)"
|
||||
(nzPanelChange)="onPanelChange($event)"
|
||||
[nzDateFullCell]="dateCellTemplate"
|
||||
></nz-calendar>
|
||||
<ng-template #dateCellTemplate let-date>
|
||||
<div class="ant-picker-cell-inner" [class.in-selection]="isDateSelected(date)">
|
||||
{{ date.getDate() }}
|
||||
<div class="calendar-section">
|
||||
<div class="calendar-title">CALENDRIER</div>
|
||||
<div class="card">
|
||||
<div class="calendar-header">
|
||||
<button class="nav-button" (click)="previousMonth()">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M15 18L9 12L15 6" stroke="#d4a574" stroke-width="2" stroke-linecap="round"
|
||||
stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<h2 class="month-title">{{ currentMonthYear }}</h2>
|
||||
<button class="nav-button" (click)="nextMonth()">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M9 18L15 12L9 6" stroke="#d4a574" stroke-width="2" stroke-linecap="round"
|
||||
stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
<nz-calendar
|
||||
[nzFullscreen]="false"
|
||||
[ngModel]="currentDate"
|
||||
(nzSelectChange)="onValueChange($event)"
|
||||
(nzPanelChange)="onPanelChange($event)"
|
||||
[nzDateFullCell]="dateCellTemplate"
|
||||
></nz-calendar>
|
||||
<ng-template #dateCellTemplate let-date>
|
||||
<div class="ant-picker-cell-inner" [class.in-selection]="isDateSelected(date)">
|
||||
{{ date.getDate() }}
|
||||
</div>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sidebar à droite -->
|
||||
<div class="details">
|
||||
<div class="sidebar-header">
|
||||
<h3 class="sidebar-title">Détails</h3>
|
||||
</div>
|
||||
<div class="sidebar-content">
|
||||
<div class="sidebar-block" *ngIf="selectedSlot">
|
||||
<h4>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<circle cx="12" cy="12" r="10" stroke-width="2"/>
|
||||
<polyline points="12 6 12 12 16 14" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
Spéctacle sélectionné :
|
||||
</h4>
|
||||
<div class="slot-info">
|
||||
@for (show of shows(); track show.id) {
|
||||
<p><strong>{{ show.name }}</strong></p>
|
||||
<p>{{ show.place }}</p>
|
||||
<p>{{ show.date }}</p>
|
||||
<p>{{ show.description }}</p>
|
||||
<div class="details">
|
||||
<div class="sidebar-header">
|
||||
<h3 class="sidebar-title">
|
||||
@if (selectedDay) {
|
||||
{{ formatSelectedDay(selectedDay) }}
|
||||
} @else {
|
||||
Détails
|
||||
}
|
||||
</h3>
|
||||
</div>
|
||||
<div class="sidebar-content">
|
||||
<div class="sidebar-block">
|
||||
<h4>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<circle cx="12" cy="12" r="10" stroke-width="2"/>
|
||||
<polyline points="12 6 12 12 16 14" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
Spectacles du jour
|
||||
</h4>
|
||||
@if (getDayShows().length === 0) {
|
||||
<p class="no-shows">Aucun spectacle ce jour</p>
|
||||
} @else {
|
||||
<div class="slot-info">
|
||||
@for (show of getDayShows(); track show.id) {
|
||||
<div class="show-card">
|
||||
<div class="show-card-header">
|
||||
<strong>{{ show.name }}</strong>
|
||||
<span class="show-time" *ngIf="show.date">{{ formatShowTime(show.date) }}</span>
|
||||
</div>
|
||||
<p *ngIf="show.place">{{ show.place }}</p>
|
||||
<p *ngIf="show.description">{{ show.description }}</p>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="sidebar-block">
|
||||
<h4>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<circle cx="12" cy="12" r="3" stroke-width="2"/>
|
||||
<path d="M12 1v6m0 6v6M1 12h6m6 0h6" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
Actions rapides
|
||||
</h4>
|
||||
<button class="sidebar-btn" nzType="default" (click)="showModal()">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<path d="M12 5v14M5 12h14" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<span>Créer un spectacle</span>
|
||||
</button>
|
||||
|
||||
<nz-modal (nzOnCancel)="handleCancel()"
|
||||
(nzOnOk)="handleOk()"
|
||||
[(nzVisible)]="isVisible"
|
||||
nzTitle="Création d'évènement">
|
||||
<ng-container *nzModalContent>
|
||||
<p>Day before yesterday I saw a rabbit, and yesterday a deer, and today, you.</p>
|
||||
</ng-container>
|
||||
</nz-modal>
|
||||
<button class="sidebar-btn">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke-width="2"/>
|
||||
<polyline points="14 2 14 8 20 8" stroke-width="2"/>
|
||||
</svg>
|
||||
Voir rapports
|
||||
</button>
|
||||
<div class="sidebar-block">
|
||||
<h4>
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<circle cx="12" cy="12" r="3" stroke-width="2"/>
|
||||
<path d="M12 1v6m0 6v6M1 12h6m6 0h6" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
Actions rapides
|
||||
</h4>
|
||||
<button class="sidebar-btn" (click)="showModal()">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<path d="M12 5v14M5 12h14" stroke-width="2" stroke-linecap="round"/>
|
||||
</svg>
|
||||
<span>Créer un spectacle</span>
|
||||
</button>
|
||||
<button class="sidebar-btn">
|
||||
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" stroke-width="2"/>
|
||||
<polyline points="14 2 14 8 20 8" stroke-width="2"/>
|
||||
</svg>
|
||||
Voir rapports
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<nz-modal
|
||||
[nzVisible]="isVisible()"
|
||||
(nzVisibleChange)="isVisible.set($event)"
|
||||
[nzFooter]="null"
|
||||
[nzWidth]="480"
|
||||
nzClassName="create-show-modal"
|
||||
(nzOnCancel)="handleCancel()">
|
||||
<ng-container *nzModalContent>
|
||||
<div class="create-form">
|
||||
<div class="create-form-title">
|
||||
<div class="create-form-icon">
|
||||
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2" stroke-width="1.5"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Créer un spectacle</h3>
|
||||
<p>Renseignez les informations du spectacle</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label class="form-label">Nom du spectacle <span class="form-required">*</span></label>
|
||||
<input class="form-input" placeholder="Ex: Feu d'artifice 14 juillet"
|
||||
[(ngModel)]="newShow.name" name="name"/>
|
||||
</div>
|
||||
|
||||
<div class="form-row-2">
|
||||
<div class="form-field">
|
||||
<label class="form-label">Lieu</label>
|
||||
<input class="form-input" placeholder="Ex: Place de la mairie"
|
||||
[(ngModel)]="newShow.place" name="place"/>
|
||||
</div>
|
||||
<div class="form-field">
|
||||
<label class="form-label">Date et heure</label>
|
||||
<div class="form-datepicker-wrap">
|
||||
<nz-date-picker
|
||||
nzShowTime
|
||||
nzFormat="dd/MM/yyyy HH:mm"
|
||||
[(ngModel)]="newShowDate"
|
||||
nzPlaceHolder="Choisir une date..."
|
||||
nzDropdownClassName="pyro-datepicker-dropdown"
|
||||
name="date">
|
||||
</nz-date-picker>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-field">
|
||||
<label class="form-label">Description</label>
|
||||
<textarea class="form-input form-textarea"
|
||||
placeholder="Notes, consignes, détails techniques..."
|
||||
[(ngModel)]="newShow.description"
|
||||
name="description">
|
||||
</textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-actions">
|
||||
<button class="form-btn-cancel" (click)="handleCancel()">Annuler</button>
|
||||
<button class="form-btn-submit" [disabled]="!newShow.name" (click)="handleOk()">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
||||
<path d="M12 5v14M5 12h14" stroke-width="2.5" stroke-linecap="round"/>
|
||||
</svg>
|
||||
Créer le spectacle
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</ng-container>
|
||||
</nz-modal>
|
||||
|
||||
@@ -2,24 +2,33 @@ import {Component, inject, OnInit, signal} from '@angular/core';
|
||||
import {NzCalendarMode, NzCalendarModule} from 'ng-zorro-antd/calendar';
|
||||
import {CommonModule} from '@angular/common';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {ReadShowDto, ShowsService} from "../../../services/api";
|
||||
import {CreateShowDto, ReadShowDto, ShowsService} from "../../../services/api";
|
||||
import {firstValueFrom} from "rxjs";
|
||||
import {NzModalComponent, NzModalModule} from "ng-zorro-antd/modal";
|
||||
import {NzModalModule} from "ng-zorro-antd/modal";
|
||||
import {NzButtonModule} from "ng-zorro-antd/button";
|
||||
import {NzDatePickerModule} from "ng-zorro-antd/date-picker";
|
||||
|
||||
@Component({
|
||||
selector: 'app-planning',
|
||||
imports: [NzCalendarModule, CommonModule, FormsModule, NzButtonModule, NzModalModule],
|
||||
imports: [NzCalendarModule, CommonModule, FormsModule, NzButtonModule, NzModalModule, NzDatePickerModule],
|
||||
templateUrl: './planning.html',
|
||||
styleUrl: './planning.css',
|
||||
})
|
||||
export class Planning implements OnInit {
|
||||
private showsServices = inject(ShowsService)
|
||||
private showsServices = inject(ShowsService);
|
||||
|
||||
shows = signal<ReadShowDto[]>([]);
|
||||
|
||||
newShow: CreateShowDto = {};
|
||||
newShowDate: Date | null = null;
|
||||
|
||||
async ngOnInit() {
|
||||
await this.fetchShows();
|
||||
try {
|
||||
await this.fetchShows();
|
||||
} catch {
|
||||
// API indisponible, on continue avec une liste vide
|
||||
}
|
||||
this.goToToday();
|
||||
}
|
||||
|
||||
async fetchShows() {
|
||||
@@ -30,33 +39,31 @@ export class Planning implements OnInit {
|
||||
isVisible = signal<boolean>(false);
|
||||
|
||||
showModal(): void {
|
||||
if (!this.isVisible()) {
|
||||
this.isVisible.set(true);
|
||||
} else {
|
||||
this.isVisible.set(false);
|
||||
}
|
||||
|
||||
this.isVisible.set(!this.isVisible());
|
||||
}
|
||||
|
||||
handleOk(): void {
|
||||
console.log('Button ok clicked!');
|
||||
async handleOk(): Promise<void> {
|
||||
if (!this.newShow.name) return;
|
||||
const dto: CreateShowDto = {
|
||||
...this.newShow,
|
||||
date: this.newShowDate ? this.newShowDate.toISOString() : undefined,
|
||||
};
|
||||
await firstValueFrom(this.showsServices.createShowEndpoint(dto));
|
||||
await this.fetchShows();
|
||||
this.newShow = {};
|
||||
this.newShowDate = null;
|
||||
this.isVisible.set(false);
|
||||
}
|
||||
|
||||
handleCancel(): void {
|
||||
console.log('Button cancel clicked!');
|
||||
this.newShow = {};
|
||||
this.newShowDate = null;
|
||||
this.isVisible.set(false);
|
||||
}
|
||||
|
||||
|
||||
selectSlot(date: Date, hour: string): void {
|
||||
this.selectedSlot = {date, hour};
|
||||
console.log('Slot sélectionné:', date, hour);
|
||||
}
|
||||
|
||||
|
||||
currentDate: Date = new Date();
|
||||
selectedDates: Date[] = [];
|
||||
selectedDay: Date | null = null;
|
||||
monthNames = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
|
||||
'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'];
|
||||
mode: NzCalendarMode = 'month';
|
||||
@@ -65,47 +72,27 @@ export class Planning implements OnInit {
|
||||
return `${this.monthNames[this.currentDate.getMonth()]} ${this.currentDate.getFullYear()}`;
|
||||
}
|
||||
|
||||
getCurrentMonth(): string {
|
||||
const today = new Date();
|
||||
const mois = ['jan', 'fév', 'mar', 'avr', 'mai', 'jun', 'jul', 'aoû', 'sep', 'oct', 'nov', 'déc'];
|
||||
return mois[today.getMonth()];
|
||||
}
|
||||
private updateWeek(startFrom: Date): void {
|
||||
const monday = new Date(startFrom);
|
||||
const day = monday.getDay();
|
||||
const diff = day === 0 ? -6 : 1 - day;
|
||||
monday.setDate(monday.getDate() + diff);
|
||||
|
||||
getCurrentDay(): string {
|
||||
const today = new Date();
|
||||
return String(today.getDate());
|
||||
}
|
||||
|
||||
getCurrentDate(): string {
|
||||
const today = new Date();
|
||||
const mois = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'];
|
||||
return `${today.getDate()} ${mois[today.getMonth()]} ${today.getFullYear()}`;
|
||||
}
|
||||
|
||||
getDayWeek(): string {
|
||||
const today = new Date();
|
||||
const days = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'];
|
||||
return days[today.getDay()];
|
||||
}
|
||||
|
||||
onValueChange(value: Date): void {
|
||||
console.log(`Current value: ${value}`);
|
||||
this.currentDate = value;
|
||||
|
||||
// Sélectionner la date cliquée + les 6 jours suivants (7 jours au total)
|
||||
this.selectedDates = [];
|
||||
for (let i = 0; i < 7; i++) {
|
||||
const date = new Date(value);
|
||||
const date = new Date(monday);
|
||||
date.setDate(date.getDate() + i);
|
||||
this.selectedDates.push(date);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Selected dates:', this.selectedDates);
|
||||
onValueChange(value: Date): void {
|
||||
this.currentDate = value;
|
||||
this.selectedDay = new Date(value);
|
||||
this.updateWeek(value);
|
||||
}
|
||||
|
||||
onPanelChange(change: { date: Date; mode: string }): void {
|
||||
console.log(`Current value: ${change.date}`);
|
||||
console.log(`Current mode: ${change.mode}`);
|
||||
this.currentDate = change.date;
|
||||
}
|
||||
|
||||
@@ -123,30 +110,33 @@ export class Planning implements OnInit {
|
||||
|
||||
previousWeek(): void {
|
||||
if (this.selectedDates.length > 0) {
|
||||
const newDate = new Date(this.selectedDates[0]);
|
||||
newDate.setDate(newDate.getDate() - 7);
|
||||
this.onValueChange(newDate);
|
||||
const newStart = new Date(this.selectedDates[0]);
|
||||
newStart.setDate(newStart.getDate() - 7);
|
||||
this.currentDate = newStart;
|
||||
this.selectedDay = new Date(newStart);
|
||||
this.updateWeek(newStart);
|
||||
}
|
||||
}
|
||||
|
||||
nextWeek(): void {
|
||||
if (this.selectedDates.length > 0) {
|
||||
const newDate = new Date(this.selectedDates[0]);
|
||||
newDate.setDate(newDate.getDate() + 7);
|
||||
this.onValueChange(newDate);
|
||||
const newStart = new Date(this.selectedDates[0]);
|
||||
newStart.setDate(newStart.getDate() + 7);
|
||||
this.currentDate = newStart;
|
||||
this.selectedDay = new Date(newStart);
|
||||
this.updateWeek(newStart);
|
||||
}
|
||||
}
|
||||
|
||||
goToToday(): void {
|
||||
const today = new Date();
|
||||
this.onValueChange(today);
|
||||
this.onValueChange(new Date());
|
||||
}
|
||||
|
||||
isDateSelected(date: Date): boolean {
|
||||
return this.selectedDates.some(selectedDate =>
|
||||
selectedDate.getFullYear() === date.getFullYear() &&
|
||||
selectedDate.getMonth() === date.getMonth() &&
|
||||
selectedDate.getDate() === date.getDate()
|
||||
return this.selectedDates.some(d =>
|
||||
d.getFullYear() === date.getFullYear() &&
|
||||
d.getMonth() === date.getMonth() &&
|
||||
d.getDate() === date.getDate()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -157,67 +147,81 @@ export class Planning implements OnInit {
|
||||
date.getFullYear() === today.getFullYear();
|
||||
}
|
||||
|
||||
isDaySelected(date: Date): boolean {
|
||||
if (!this.selectedDay) return false;
|
||||
return date.getDate() === this.selectedDay.getDate() &&
|
||||
date.getMonth() === this.selectedDay.getMonth() &&
|
||||
date.getFullYear() === this.selectedDay.getFullYear();
|
||||
}
|
||||
|
||||
getDayName(date: Date): string {
|
||||
const days = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'];
|
||||
return days[date.getDay()];
|
||||
}
|
||||
|
||||
formatDate(date: Date): string {
|
||||
const days = ['Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam'];
|
||||
return `${days[date.getDay()]} ${date.getDate()} ${date.getFullYear()}`;
|
||||
}
|
||||
|
||||
getHours(): string[] {
|
||||
return ['', '1h', '2h', '3h', '4h', '5h', '6h', '7h', '8h', '9h', '10h', '11h', '12h', '13h', '14h', '15h', '16h', '17h', '18h', '19h', '20h', '21h', '22h', '23h'];
|
||||
}
|
||||
|
||||
// Filtres
|
||||
isCamionFilterActive = false;
|
||||
|
||||
camionFilter(): void {
|
||||
this.isCamionFilterActive = !this.isCamionFilterActive;
|
||||
console.log('Filtre Camion:', this.isCamionFilterActive);
|
||||
selectDay(date: Date): void {
|
||||
this.selectedDay = date;
|
||||
}
|
||||
|
||||
isShowFilterActive = false;
|
||||
|
||||
showFilter(): void {
|
||||
this.isShowFilterActive = !this.isShowFilterActive;
|
||||
console.log('Filtre Show:', this.isShowFilterActive);
|
||||
getShowsForDay(date: Date): ReadShowDto[] {
|
||||
return this.shows().filter(show => {
|
||||
if (!show.date) return false;
|
||||
const d = new Date(show.date);
|
||||
return d.getFullYear() === date.getFullYear() &&
|
||||
d.getMonth() === date.getMonth() &&
|
||||
d.getDate() === date.getDate();
|
||||
});
|
||||
}
|
||||
|
||||
// Sélection de créneaux
|
||||
selectedSlot: { date: Date; hour: string } | null = null;
|
||||
|
||||
isSlotSelected(date: Date, hour: string): boolean {
|
||||
if (!this.selectedSlot) return false;
|
||||
return this.selectedSlot.date.getTime() === date.getTime() &&
|
||||
this.selectedSlot.hour === hour;
|
||||
getShowsForSlot(date: Date, hour: string): ReadShowDto[] {
|
||||
if (!hour) return [];
|
||||
const h = parseInt(hour);
|
||||
return this.shows().filter(show => {
|
||||
if (!show.date) return false;
|
||||
const d = new Date(show.date);
|
||||
return d.getFullYear() === date.getFullYear() &&
|
||||
d.getMonth() === date.getMonth() &&
|
||||
d.getDate() === date.getDate() &&
|
||||
d.getHours() === h;
|
||||
});
|
||||
}
|
||||
|
||||
formatSelectedDate(date: Date): string {
|
||||
getDayShows(): ReadShowDto[] {
|
||||
if (!this.selectedDay) return [];
|
||||
return this.getShowsForDay(this.selectedDay);
|
||||
}
|
||||
|
||||
formatSelectedDay(date: Date): string {
|
||||
const days = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'];
|
||||
const months = ['janvier', 'février', 'mars', 'avril', 'mai', 'juin', 'juillet', 'août', 'septembre', 'octobre', 'novembre', 'décembre'];
|
||||
return `${days[date.getDay()]} ${date.getDate()} ${months[date.getMonth()]}`;
|
||||
}
|
||||
|
||||
createNewProject(): void {
|
||||
console.log('Création d\'un nouveau projet');
|
||||
alert('Fonctionnalité à venir : Créer un nouveau projet');
|
||||
formatShowTime(dateStr: string): string {
|
||||
const d = new Date(dateStr);
|
||||
return `${d.getHours().toString().padStart(2, '0')}:${d.getMinutes().toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
getTotalEvents(): number {
|
||||
// À implémenter avec de vraies données
|
||||
return 0;
|
||||
isCamionFilterActive = false;
|
||||
isShowFilterActive = false;
|
||||
|
||||
camionFilter(): void {
|
||||
this.isCamionFilterActive = !this.isCamionFilterActive;
|
||||
}
|
||||
|
||||
showFilter(): void {
|
||||
this.isShowFilterActive = !this.isShowFilterActive;
|
||||
}
|
||||
|
||||
getWeekNumber(): number {
|
||||
if (this.selectedDates.length === 0) return 0;
|
||||
|
||||
const date = new Date(this.selectedDates[0]);
|
||||
const firstDayOfYear = new Date(date.getFullYear(), 0, 1);
|
||||
const pastDaysOfYear = (date.getTime() - firstDayOfYear.getTime()) / 86400000;
|
||||
|
||||
return Math.ceil((pastDaysOfYear + firstDayOfYear.getDay() + 1) / 7);
|
||||
}
|
||||
}
|
||||
@@ -27,5 +27,99 @@ button.primary {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* ─── Date picker dropdown (Pyrofetes theme) ──────────────── */
|
||||
.pyro-datepicker-dropdown .ant-picker-panel-container {
|
||||
border-radius: 14px !important;
|
||||
overflow: hidden !important;
|
||||
border: 2px solid var(--ugly-yellow) !important;
|
||||
box-shadow: 0 8px 30px rgba(212, 165, 116, 0.25) !important;
|
||||
min-width: 320px !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-date-panel {
|
||||
min-width: 250px !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-cell {
|
||||
min-width: 32px !important;
|
||||
padding: 2px !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-header {
|
||||
border-bottom: 2px solid #f5ede3 !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-header-view button {
|
||||
color: var(--ugly-yellow) !important;
|
||||
font-weight: 700 !important;
|
||||
font-family: 'Be Vietnam Pro', sans-serif !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-header button {
|
||||
color: var(--ugly-yellow) !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-content th {
|
||||
color: #a08060 !important;
|
||||
font-size: 11px !important;
|
||||
font-weight: 700 !important;
|
||||
text-transform: uppercase !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-cell {
|
||||
padding: 2px 1px !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-cell-inner {
|
||||
width: 100% !important;
|
||||
height: 28px !important;
|
||||
line-height: 28px !important;
|
||||
border-radius: 6px !important;
|
||||
font-size: 12px !important;
|
||||
font-weight: 600 !important;
|
||||
color: #ccc !important;
|
||||
transition: all 0.15s ease !important;
|
||||
display: block !important;
|
||||
text-align: center !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-cell-in-view .ant-picker-cell-inner {
|
||||
color: var(--ugly-yellow) !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-cell:hover .ant-picker-cell-inner {
|
||||
background: rgba(212, 165, 116, 0.12) !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-cell-in-view.ant-picker-cell-selected .ant-picker-cell-inner {
|
||||
background: linear-gradient(135deg, var(--ugly-yellow) 0%, #c49563 100%) !important;
|
||||
color: white !important;
|
||||
box-shadow: 0 2px 8px rgba(212, 165, 116, 0.35) !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-cell-in-view.ant-picker-cell-today .ant-picker-cell-inner::before {
|
||||
border: 2px solid var(--ugly-yellow) !important;
|
||||
border-radius: 6px !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-now-btn {
|
||||
color: var(--ugly-yellow) !important;
|
||||
font-family: 'Be Vietnam Pro', sans-serif !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-ok button:not(:disabled) {
|
||||
background: linear-gradient(135deg, var(--ugly-yellow) 0%, #c49563 100%) !important;
|
||||
border-color: var(--ugly-yellow) !important;
|
||||
color: white !important;
|
||||
border-radius: 8px !important;
|
||||
font-family: 'Be Vietnam Pro', sans-serif !important;
|
||||
}
|
||||
|
||||
.pyro-datepicker-dropdown .ant-picker-time-panel-column > li.ant-picker-time-panel-cell-selected .ant-picker-time-panel-cell-inner {
|
||||
background: rgba(212, 165, 116, 0.15) !important;
|
||||
color: var(--ugly-yellow) !important;
|
||||
font-weight: 700 !important;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user