gitignore
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import { Component } from '@angular/core';
|
||||
import {RouterOutlet} from "@angular/router";
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
imports: [],
|
||||
imports: [RouterOutlet],
|
||||
template: `
|
||||
<p>
|
||||
dashboard works!
|
||||
<router-outlet></router-outlet>
|
||||
</p>
|
||||
`,
|
||||
styles: ``
|
||||
|
||||
@@ -0,0 +1,395 @@
|
||||
.background {
|
||||
padding: 20px;
|
||||
min-height: 100vh;
|
||||
background: #f5f5f0;
|
||||
}
|
||||
|
||||
.planning-container {
|
||||
display: grid;
|
||||
grid-template-columns: 300px 1fr;
|
||||
gap: 20px;
|
||||
max-width: 1400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* Section Calendrier (gauche) */
|
||||
.calendar-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.calendar-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
letter-spacing: 1px;
|
||||
}
|
||||
|
||||
.calendar-date-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
padding: 15px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.date-badge {
|
||||
background: #8b7b8b;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
min-width: 60px;
|
||||
}
|
||||
|
||||
.month-abbr {
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.day-number {
|
||||
font-size: 24px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.date-full {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.date-text {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.day-text {
|
||||
font-size: 13px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.card {
|
||||
background: #fefdfb;
|
||||
border: 2px solid #d4a574;
|
||||
border-radius: 20px;
|
||||
padding: 15px;
|
||||
box-shadow: 0 4px 12px rgba(212, 165, 116, 0.1);
|
||||
}
|
||||
|
||||
.calendar-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 5px 0 15px;
|
||||
}
|
||||
|
||||
.month-title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #d4a574;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.nav-button {
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 6px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.nav-button:hover {
|
||||
opacity: 1;
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
/* Styles pour le calendrier NG-ZORRO */
|
||||
::ng-deep .card nz-calendar {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-calendar {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-calendar-header {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-content {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-content table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
::ng-deep .card thead th {
|
||||
color: #8b6f47;
|
||||
font-weight: 600;
|
||||
font-size: 11px;
|
||||
padding: 8px 0;
|
||||
text-align: center;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-cell {
|
||||
padding: 4px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-cell-inner {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
border-radius: 8px;
|
||||
margin: 0 auto;
|
||||
color: #d4a574;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
transition: all 0.2s ease;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-cell:hover .ant-picker-cell-inner {
|
||||
background: #f9f3ec;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-cell-inner.in-selection {
|
||||
background: #d4a574 !important;
|
||||
color: white !important;
|
||||
box-shadow: 0 2px 8px rgba(212, 165, 116, 0.3);
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-cell-inner.in-selection:hover {
|
||||
background: #c49563 !important;
|
||||
}
|
||||
|
||||
::ng-deep .card .ant-picker-cell-disabled .ant-picker-cell-inner {
|
||||
color: #e0d5c7;
|
||||
}
|
||||
|
||||
::ng-deep .card tbody tr {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
/* Section Planning (droite) */
|
||||
.week-section {
|
||||
background: white;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
|
||||
padding: 20px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.empty-state {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
min-height: 500px;
|
||||
}
|
||||
|
||||
.empty-message {
|
||||
text-align: center;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.week-toolbar {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 2px solid #f0f0f0;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.week-actions {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
padding: 8px 16px;
|
||||
border: 1px solid #d9d9d9;
|
||||
background: white;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.action-btn:hover {
|
||||
border-color: #d4a574;
|
||||
}
|
||||
|
||||
.action-btn.active {
|
||||
background: #d4a574;
|
||||
color: white;
|
||||
border-color: #d4a574;
|
||||
}
|
||||
|
||||
.week-nav {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.today-label {
|
||||
font-weight: 600;
|
||||
color: #999;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.today-btn {
|
||||
padding: 8px 16px;
|
||||
background: white;
|
||||
border: 1px solid #d9d9d9;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.today-btn:hover {
|
||||
border-color: #8b7b8b;
|
||||
}
|
||||
|
||||
.new-project-btn {
|
||||
padding: 8px 20px;
|
||||
background: #8b7b8b;
|
||||
color: white;
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
font-size: 13px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.new-project-btn:hover {
|
||||
background: #7a6a7a;
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.week-calendar {
|
||||
overflow-x: auto;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.week-nav-header {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
right: 20px;
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.nav-button-week {
|
||||
background: white;
|
||||
border: 1px solid #e0e0e0;
|
||||
border-radius: 4px;
|
||||
padding: 4px 8px;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.nav-button-week:hover {
|
||||
border-color: #999;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.week-grid {
|
||||
display: grid;
|
||||
grid-template-columns: 70px repeat(7, 1fr);
|
||||
gap: 0;
|
||||
min-width: 900px;
|
||||
}
|
||||
|
||||
.time-column {
|
||||
border-right: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.time-header {
|
||||
height: 70px;
|
||||
border-bottom: 2px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.time-slot {
|
||||
height: 70px;
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: center;
|
||||
padding-top: 5px;
|
||||
font-size: 11px;
|
||||
color: #999;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
|
||||
.day-column {
|
||||
border-right: 1px solid #e8e8e8;
|
||||
}
|
||||
|
||||
.day-column:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.day-header {
|
||||
height: 70px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-bottom: 2px solid #e8e8e8;
|
||||
background: #fafafa;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.day-header.today {
|
||||
background: #8b7b8b;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.day-name {
|
||||
font-size: 13px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.day-date {
|
||||
font-size: 11px;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.day-header.today .day-date {
|
||||
color: rgba(255, 255, 255, 0.8);
|
||||
}
|
||||
|
||||
.day-slots {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.hour-slot {
|
||||
height: 70px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
padding: 3px;
|
||||
position: relative;
|
||||
transition: background 0.2s ease;
|
||||
}
|
||||
|
||||
.hour-slot:hover {
|
||||
background: #f9f9f9;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,110 @@
|
||||
<div class="background">
|
||||
<div class="planning-container">
|
||||
<!-- Calendrier à gauche -->
|
||||
<div class="calendar-section">
|
||||
<div class="calendar-title">CALENDAR</div>
|
||||
<div class="calendar-date-info">
|
||||
<div class="date-badge">
|
||||
<div class="month-abbr">JAN</div>
|
||||
<div class="day-number">21</div>
|
||||
</div>
|
||||
<div class="date-full">
|
||||
<div class="date-text">21 janvier 2026</div>
|
||||
<div class="day-text">Mercredi</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="calendar-header">
|
||||
<button class="nav-button" (click)="previousMonth()">
|
||||
<svg width="24" height="24" 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="24" height="24" 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>
|
||||
</ng-template>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Planning de la semaine à droite -->
|
||||
<div class="week-section" *ngIf="selectedDates.length > 0">
|
||||
<div class="week-toolbar">
|
||||
<div class="week-actions">
|
||||
<button class="action-btn">Lorem</button>
|
||||
<button class="action-btn active">Camion</button>
|
||||
<button class="action-btn">Show</button>
|
||||
</div>
|
||||
<div class="week-nav">
|
||||
<span class="today-label">LOREM</span>
|
||||
<button class="today-btn" (click)="goToToday()">
|
||||
< TODAY >
|
||||
</button>
|
||||
<button class="new-project-btn">NEW PROJECT</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="week-calendar">
|
||||
<div class="week-nav-header">
|
||||
<button class="nav-button-week" (click)="previousWeek()">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M15 18L9 12L15 6" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button class="nav-button-week" (click)="nextWeek()">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
||||
<path d="M9 18L15 12L9 6" stroke="#999" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
<!-- Colonnes des jours -->
|
||||
<div class="day-column" *ngFor="let date of selectedDates">
|
||||
<div class="day-header" [class.today]="isToday(date)">
|
||||
<div class="day-name">{{ getDayName(date) }}</div>
|
||||
<div class="day-date">{{ formatDate(date) }}</div>
|
||||
</div>
|
||||
<div class="day-slots">
|
||||
<div class="hour-slot" *ngFor="let hour of getHours()">
|
||||
<!-- Ici on peut ajouter des événements plus tard -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Message si aucune semaine sélectionnée -->
|
||||
<div class="week-section empty-state" *ngIf="selectedDates.length === 0">
|
||||
<div class="empty-message">
|
||||
<p>Sélectionnez une date dans le calendrier pour voir le planning de la semaine</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
106
src/app/components/pages/planning/planning.ts
Normal file
106
src/app/components/pages/planning/planning.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { NzCalendarMode, NzCalendarModule } from 'ng-zorro-antd/calendar';
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { FormsModule } from '@angular/forms';
|
||||
|
||||
@Component({
|
||||
selector: 'app-planning',
|
||||
imports: [NzCalendarModule, CommonModule, FormsModule],
|
||||
templateUrl: './planning.html',
|
||||
styleUrl: './planning.css',
|
||||
})
|
||||
export class Planning {
|
||||
currentDate: Date = new Date();
|
||||
selectedDates: Date[] = [];
|
||||
monthNames = ['Janvier', 'Février', 'Mars', 'Avril', 'Mai', 'Juin',
|
||||
'Juillet', 'Août', 'Septembre', 'Octobre', 'Novembre', 'Décembre'];
|
||||
|
||||
mode: NzCalendarMode = 'month';
|
||||
|
||||
get currentMonthYear(): string {
|
||||
return `${this.monthNames[this.currentDate.getMonth()]} ${this.currentDate.getFullYear()}`;
|
||||
}
|
||||
|
||||
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);
|
||||
date.setDate(date.getDate() + i);
|
||||
this.selectedDates.push(date);
|
||||
}
|
||||
|
||||
console.log('Selected dates:', this.selectedDates);
|
||||
}
|
||||
|
||||
onPanelChange(change: { date: Date; mode: string }): void {
|
||||
console.log(`Current value: ${change.date}`);
|
||||
console.log(`Current mode: ${change.mode}`);
|
||||
this.currentDate = change.date;
|
||||
}
|
||||
|
||||
previousMonth(): void {
|
||||
const newDate = new Date(this.currentDate);
|
||||
newDate.setMonth(newDate.getMonth() - 1);
|
||||
this.currentDate = newDate;
|
||||
}
|
||||
|
||||
nextMonth(): void {
|
||||
const newDate = new Date(this.currentDate);
|
||||
newDate.setMonth(newDate.getMonth() + 1);
|
||||
this.currentDate = newDate;
|
||||
}
|
||||
|
||||
previousWeek(): void {
|
||||
if (this.selectedDates.length > 0) {
|
||||
const newDate = new Date(this.selectedDates[0]);
|
||||
newDate.setDate(newDate.getDate() - 7);
|
||||
this.onValueChange(newDate);
|
||||
}
|
||||
}
|
||||
|
||||
nextWeek(): void {
|
||||
if (this.selectedDates.length > 0) {
|
||||
const newDate = new Date(this.selectedDates[0]);
|
||||
newDate.setDate(newDate.getDate() + 7);
|
||||
this.onValueChange(newDate);
|
||||
}
|
||||
}
|
||||
|
||||
goToToday(): void {
|
||||
const today = new Date();
|
||||
this.onValueChange(today);
|
||||
}
|
||||
|
||||
isDateSelected(date: Date): boolean {
|
||||
return this.selectedDates.some(selectedDate =>
|
||||
selectedDate.getFullYear() === date.getFullYear() &&
|
||||
selectedDate.getMonth() === date.getMonth() &&
|
||||
selectedDate.getDate() === date.getDate()
|
||||
);
|
||||
}
|
||||
|
||||
isToday(date: Date): boolean {
|
||||
const today = new Date();
|
||||
return date.getDate() === today.getDate() &&
|
||||
date.getMonth() === today.getMonth() &&
|
||||
date.getFullYear() === today.getFullYear();
|
||||
}
|
||||
|
||||
getDayName(date: Date): string {
|
||||
const days = ['Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi'];
|
||||
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 ['8 AM', '10 AM', '11 AM', '12 PM', '14 PM', '16 PM', '18 PM'];
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,10 @@ export const routes: Routes = [
|
||||
{
|
||||
path: 'test',
|
||||
loadComponent: () => import('./components/pages/test/test').then(x => x.Test)
|
||||
},
|
||||
{
|
||||
path: 'planning',
|
||||
loadComponent: () => import('./components/pages/planning/planning').then(x => x.Planning)
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user