git init v2
This commit is contained in:
84
src/app/pages/agenda/agenda.component.html
Normal file
84
src/app/pages/agenda/agenda.component.html
Normal file
@@ -0,0 +1,84 @@
|
||||
<div class="container">
|
||||
<div class="heading">
|
||||
<button
|
||||
appearance="primary"
|
||||
iconStart="@tui.chevron-left"
|
||||
size="m"
|
||||
tuiIconButton
|
||||
(click)="previousDay()"
|
||||
type="button">
|
||||
</button>
|
||||
<h1 class="date" (click)="toggleCalendar()">{{ getDate() }}</h1>
|
||||
<button
|
||||
appearance="primary"
|
||||
iconStart="@tui.chevron-right"
|
||||
size="m"
|
||||
tuiIconButton
|
||||
(click)="nextDay()"
|
||||
type="button">
|
||||
</button>
|
||||
</div>
|
||||
<div class="calendar" *ngIf="showCalendar">
|
||||
<tui-calendar
|
||||
[value]="value"
|
||||
(dayClick)="onDayClick($event)"
|
||||
/>
|
||||
</div>
|
||||
<div class="toolbar">
|
||||
<button
|
||||
*ngIf="today.getDate() != selectedDate.getDate()"
|
||||
appearance="secondary"
|
||||
size="m"
|
||||
tuiButton
|
||||
(click)="setToday()"
|
||||
type="button">
|
||||
Vandaag
|
||||
</button>
|
||||
<button
|
||||
appearance="secondary"
|
||||
size="m"
|
||||
tuiButton
|
||||
(click)="isModalOpen = true"
|
||||
type="button">
|
||||
<tui-icon
|
||||
icon="@tui.plus"
|
||||
[style.height.rem]="1"
|
||||
/>
|
||||
Afspraak maken
|
||||
</button>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="agenda-container">
|
||||
<div *ngFor="let hour of timeSlots" class="time-slot">
|
||||
<span class="time">{{ hour.toString().padStart(2, '0') }}:00</span>
|
||||
|
||||
<div *ngFor="let appointment of getAppointmentsForHour(hour)"
|
||||
class="appointment"
|
||||
(click)="selectAppointment(appointment)"
|
||||
[ngClass]="{ 'large': (getAppointmentHeight(appointment) > 50) }"
|
||||
[ngStyle]="getInlineStyles(appointment)">
|
||||
|
||||
<strong>{{ appointment.title }}</strong>
|
||||
<span class="appointment-time" *ngIf="appointment.customer">
|
||||
<tui-icon icon="@tui.user" [style.font-size.rem]="1"></tui-icon>
|
||||
{{ appointment.customer.firstName }} {{ appointment.customer.lastName }}</span>
|
||||
<span class="appointment-time">
|
||||
<tui-icon icon="@tui.clock" [style.font-size.rem]="1"></tui-icon>
|
||||
{{ getFormattedTime(appointment.startHour, appointment.startMinute) }}
|
||||
- {{ getFormattedTime(appointment.endHour, appointment.endMinute) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<app-modal title="Nieuwe afspraak" (close)="closeNewItemModal()" *ngIf="isModalOpen">
|
||||
<app-new-item [testForm]="appointmentForm" (appointmentAddedEvent)="registerAppointment($event)"></app-new-item>
|
||||
</app-modal>
|
||||
|
||||
<app-modal title="{{selectedAppointment.title}}" (close)="selectedAppointment = undefined"
|
||||
*ngIf="selectedAppointment != undefined">
|
||||
<app-details [appointment]="selectedAppointment" (appointmentDeleted)="appointmentIsDeleted($event)"
|
||||
(appointmentEdited)="appointmentIsEdited($event)"></app-details>
|
||||
</app-modal>
|
||||
141
src/app/pages/agenda/agenda.component.scss
Normal file
141
src/app/pages/agenda/agenda.component.scss
Normal file
@@ -0,0 +1,141 @@
|
||||
.container {
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
background-color: #f9f9f9;
|
||||
margin: 10px 0;
|
||||
padding: 10px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 5px 0 0;
|
||||
}
|
||||
|
||||
.heading {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.calendar {
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.time-slot {
|
||||
height: 25px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 14px;
|
||||
background: #f9f9f9;
|
||||
transition: background 0.3s ease;
|
||||
}
|
||||
|
||||
.time-slot.claimed {
|
||||
background: #d1e7dd; /* Lichtgroene achtergrond voor gereserveerde blokken */
|
||||
color: #155724;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.time-slot:nth-child(odd) {
|
||||
background: #ececec;
|
||||
}
|
||||
|
||||
.time {
|
||||
width: 50px;
|
||||
font-weight: bold;
|
||||
margin-top: 20px;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.content {
|
||||
overflow-y: scroll;
|
||||
max-height: 70vh;
|
||||
}
|
||||
|
||||
.agenda-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid #ddd;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.time-slot {
|
||||
position: relative;
|
||||
border-bottom: 1px solid #ccc;
|
||||
height: 59px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
font-size: 16px;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.appointment {
|
||||
position: absolute;
|
||||
left: 80px;
|
||||
width: calc(100% - 100px);
|
||||
background: #1e88e5;
|
||||
color: white;
|
||||
border-radius: 4px;
|
||||
border-left: 5px solid #1565c0;
|
||||
box-shadow: 2px 2px 5px rgba(0, 0, 0, 0.2);
|
||||
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
display: grid;
|
||||
grid-auto-flow: column;
|
||||
align-items: center;
|
||||
//gap: 5px;
|
||||
|
||||
min-height: 20px;
|
||||
}
|
||||
|
||||
.appointment.large {
|
||||
grid-auto-flow: row;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
strong, p {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.appointment-time {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
.date {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.date:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
206
src/app/pages/agenda/agenda.component.ts
Normal file
206
src/app/pages/agenda/agenda.component.ts
Normal file
@@ -0,0 +1,206 @@
|
||||
import {Component, inject, OnInit} from '@angular/core';
|
||||
import {CommonModule, NgFor, NgIf} from '@angular/common';
|
||||
import {TuiAlertService, TuiButton, TuiCalendar, tuiDateFormatProvider, TuiIcon} from '@taiga-ui/core';
|
||||
import {Appointment} from '../../models/appointment';
|
||||
import {ModalComponent} from '../../components/modal/modal.component';
|
||||
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
||||
import {
|
||||
TuiInputDateModule,
|
||||
TuiInputModule,
|
||||
TuiInputTimeModule,
|
||||
TuiTextareaModule,
|
||||
TuiTextfieldControllerModule
|
||||
} from '@taiga-ui/legacy';
|
||||
import {TuiDay, TuiTime} from '@taiga-ui/cdk';
|
||||
import {AppointmentService} from '../../services/appointment.service';
|
||||
import {DetailsComponent} from '../../components/details/details.component';
|
||||
import {DateFormatter} from '../../utils/date-formatter';
|
||||
import {WeekDay} from '../../models/week-day';
|
||||
import {NewItemComponent} from '../../components/new-item/new-item.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-agenda',
|
||||
imports: [NgFor,
|
||||
TuiButton, CommonModule, NgIf, ModalComponent, ReactiveFormsModule,
|
||||
TuiInputTimeModule, TuiTextfieldControllerModule,
|
||||
TuiInputModule, TuiTextareaModule, TuiInputDateModule, TuiIcon, DetailsComponent, TuiCalendar, NewItemComponent],
|
||||
templateUrl: './agenda.component.html',
|
||||
providers: [tuiDateFormatProvider({separator: '-'}), AppointmentService],
|
||||
styleUrl: './agenda.component.scss'
|
||||
})
|
||||
export class AgendaComponent implements OnInit {
|
||||
|
||||
constructor(private appointmentService: AppointmentService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getAppointmentsByDate(this.selectedDate);
|
||||
}
|
||||
|
||||
timeSlots: number[] = Array.from({length: 24}, (_, i) => i); // 24 uren
|
||||
appointments: Appointment[] = [];
|
||||
isModalOpen = false
|
||||
today = new Date()
|
||||
selectedDate = new Date()
|
||||
waiting: boolean = false;
|
||||
selectedAppointment: Appointment;
|
||||
protected value: TuiDay | null = null;
|
||||
showCalendar: boolean = false;
|
||||
|
||||
private readonly alerts = inject(TuiAlertService);
|
||||
protected appointmentForm = new FormGroup({
|
||||
title: new FormControl('', Validators.required),
|
||||
notes: new FormControl(''),
|
||||
startTime: new FormControl(new TuiTime(this.today.getHours(), this.today.getMinutes()), Validators.required),
|
||||
endTime: new FormControl(new TuiTime(this.getHours(), this.getMinutes()), Validators.required),
|
||||
date: new FormControl(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()), Validators.required),
|
||||
});
|
||||
|
||||
registerAppointment(title: string): void {
|
||||
this.getAppointmentsByDate(this.selectedDate);
|
||||
this.waiting = false
|
||||
this.isModalOpen = false
|
||||
this.showNotification(title)
|
||||
this.resetForms()
|
||||
}
|
||||
|
||||
protected showNotification(message: string): void {
|
||||
this.alerts
|
||||
.open(`Afspraak <strong>${message}</strong> is aangemaakt.`)
|
||||
.subscribe();
|
||||
}
|
||||
|
||||
getAppointmentsForHour(hour: number) {
|
||||
return this.appointments.filter(appointment => appointment.startHour === hour);
|
||||
}
|
||||
|
||||
getDate(): string {
|
||||
const date = this.selectedDate
|
||||
|
||||
const weekDay = WeekDay[date.getDay()];
|
||||
const day = date.getDate().toString().padStart(2, '0'); // Dag met leading zero (01, 02, ..., 31)
|
||||
const monthName = date.toLocaleString('nl-NL', {month: 'long'});
|
||||
const year = date.getFullYear().toString(); // Volledig jaar
|
||||
|
||||
return `${weekDay} ${day} ${monthName} ${year}`;
|
||||
}
|
||||
|
||||
resetForms() {
|
||||
this.appointmentForm = new FormGroup({
|
||||
title: new FormControl('', Validators.required),
|
||||
notes: new FormControl(''),
|
||||
startTime: new FormControl(new TuiTime(this.today.getHours(), this.today.getMinutes()), Validators.required),
|
||||
endTime: new FormControl(new TuiTime(this.getEndTime().getHours(), this.getEndTime().getMinutes()), Validators.required),
|
||||
date: new FormControl(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()), Validators.required),
|
||||
});
|
||||
}
|
||||
|
||||
nextDay() {
|
||||
this.selectedDate.setDate(this.selectedDate.getDate() + 1);
|
||||
this.getAppointmentsByDate(this.selectedDate);
|
||||
this.appointmentForm.get('date').setValue(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()))
|
||||
}
|
||||
|
||||
previousDay() {
|
||||
this.selectedDate.setDate(this.selectedDate.getDate() - 1);
|
||||
this.getAppointmentsByDate(this.selectedDate);
|
||||
this.appointmentForm.get('date').setValue(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()))
|
||||
}
|
||||
|
||||
getHours() {
|
||||
let hours = this.today.getHours()
|
||||
console.log(hours)
|
||||
if (hours > 23) {
|
||||
return 23
|
||||
}
|
||||
return hours
|
||||
}
|
||||
|
||||
getMinutes() {
|
||||
let minutes = this.today.getMinutes() + 30
|
||||
if (minutes > 59) {
|
||||
return 59
|
||||
}
|
||||
return minutes
|
||||
}
|
||||
|
||||
getEndTime(): Date {
|
||||
const endTime = new Date(this.today); // Kopieer startTime
|
||||
endTime.setMinutes(endTime.getMinutes() + 30); // 30 minuten toevoegen
|
||||
|
||||
// Controleer of de dag nog steeds hetzelfde is
|
||||
if (endTime.getDate() !== this.today.getDate()) {
|
||||
endTime.setHours(23, 59, 59, 999); // Zet naar 23:59:59 als het overloopt
|
||||
}
|
||||
|
||||
return endTime;
|
||||
}
|
||||
|
||||
|
||||
setToday() {
|
||||
this.selectedDate = new Date()
|
||||
this.getAppointmentsByDate(this.selectedDate);
|
||||
this.appointmentForm.get('date').setValue(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()))
|
||||
}
|
||||
|
||||
getAppointmentsByDate(date: Date) {
|
||||
this.appointmentService.getAppointmentsByDate(date).subscribe(appointments => {
|
||||
this.appointments = appointments;
|
||||
})
|
||||
}
|
||||
|
||||
getInlineStyles(appointment: Appointment): { [key: string]: string } {
|
||||
return {
|
||||
'--duration': `${appointment.durationInMinutes}`,
|
||||
'--start-minute': `${appointment.startMinute}`,
|
||||
'top': `${appointment.startMinute}px`, // Startpositie binnen het uur
|
||||
'height': `${appointment.durationInMinutes}px`, // Hoogte over meerdere uren
|
||||
};
|
||||
}
|
||||
|
||||
getFormattedTime(hour: number, minute: number): string {
|
||||
return `${hour.toString().padStart(2, '0')}:${minute.toString().padStart(2, '0')}`;
|
||||
}
|
||||
|
||||
getAppointmentHeight(appointment: Appointment): number {
|
||||
const startInMinutes = (appointment.startHour * 60) + appointment.startMinute;
|
||||
const endInMinutes = (appointment.endHour * 60) + appointment.endMinute;
|
||||
return (endInMinutes - startInMinutes); // 50px per uur
|
||||
}
|
||||
|
||||
selectAppointment(appointment: Appointment) {
|
||||
this.selectedAppointment = appointment;
|
||||
}
|
||||
|
||||
protected readonly DateFormatter = DateFormatter;
|
||||
|
||||
onDayClick(day: TuiDay) {
|
||||
this.value = day;
|
||||
this.selectedDate = new Date(day.year, day.month, day.day);
|
||||
this.getAppointmentsByDate(this.selectedDate);
|
||||
this.appointmentForm.get('date').setValue(new TuiDay(this.selectedDate.getFullYear(), this.selectedDate.getMonth(), this.selectedDate.getDate()))
|
||||
this.toggleCalendar()
|
||||
}
|
||||
|
||||
toggleCalendar() {
|
||||
this.showCalendar = !this.showCalendar
|
||||
}
|
||||
|
||||
closeNewItemModal() {
|
||||
this.isModalOpen = false
|
||||
this.resetForms()
|
||||
}
|
||||
|
||||
appointmentIsDeleted(appointment: Appointment) {
|
||||
this.selectedAppointment = undefined;
|
||||
this.alerts
|
||||
.open(`Afspraak <strong>${appointment.title}</strong> is verwijderd.`)
|
||||
.subscribe();
|
||||
this.getAppointmentsByDate(this.selectedDate);
|
||||
}
|
||||
|
||||
appointmentIsEdited($event: Appointment) {
|
||||
this.getAppointmentsByDate(this.selectedDate);
|
||||
}
|
||||
}
|
||||
|
||||
265
src/app/pages/dashboard/dashboard.component.html
Normal file
265
src/app/pages/dashboard/dashboard.component.html
Normal file
@@ -0,0 +1,265 @@
|
||||
<div [style.display]="'flex'">
|
||||
<aside
|
||||
[style.height.rem]="27"
|
||||
[tuiNavigationAside]="expanded()"
|
||||
>
|
||||
<header>
|
||||
<button
|
||||
iconStart="@tui.home"
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
<span tuiFade>A very very long product name</span>
|
||||
</button>
|
||||
</header>
|
||||
<button
|
||||
iconStart="@tui.search"
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
Search
|
||||
|
||||
<ng-container *ngIf="expanded()">
|
||||
<tui-badge appearance="accent">12</tui-badge>
|
||||
</ng-container>
|
||||
</button>
|
||||
<a
|
||||
iconStart="@tui.users"
|
||||
tuiAsideItem
|
||||
[routerLink]="routes.Navigation"
|
||||
>
|
||||
Groups
|
||||
</a>
|
||||
<tui-aside-group>
|
||||
<button
|
||||
automation-id="setting"
|
||||
iconStart="@tui.settings"
|
||||
tuiAsideItem
|
||||
tuiChevron
|
||||
type="button"
|
||||
>
|
||||
Settings
|
||||
<ng-template>
|
||||
<button
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
Account
|
||||
</button>
|
||||
<button
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
Notifications
|
||||
</button>
|
||||
<button
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
Privacy
|
||||
</button>
|
||||
</ng-template>
|
||||
</button>
|
||||
</tui-aside-group>
|
||||
<button
|
||||
automation-id="hint"
|
||||
iconStart="@tui.heart"
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
<span tuiFade>By default ellipsis is used but you can use fade too</span>
|
||||
</button>
|
||||
<button
|
||||
iconEnd="@tui.chevron-right"
|
||||
iconStart="@tui.ellipsis"
|
||||
tuiAsideItem
|
||||
tuiDropdownHover
|
||||
tuiDropdownOpen
|
||||
type="button"
|
||||
[tuiDropdown]="more"
|
||||
>
|
||||
More
|
||||
<ng-template
|
||||
#more
|
||||
let-close
|
||||
>
|
||||
<tui-data-list tuiDataListDropdownManager>
|
||||
<button
|
||||
iconStart="@tui.pencil"
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
Write
|
||||
</button>
|
||||
<button
|
||||
iconStart="@tui.pie-chart"
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
[tuiDropdown]="submenu"
|
||||
>
|
||||
Categories
|
||||
<ng-template #submenu>
|
||||
<tui-data-list>
|
||||
<button
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
(click)="close()"
|
||||
>
|
||||
Fiction (will close menu)
|
||||
</button>
|
||||
<button
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
Non-Fiction
|
||||
</button>
|
||||
<button
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
Children
|
||||
</button>
|
||||
</tui-data-list>
|
||||
</ng-template>
|
||||
</button>
|
||||
</tui-data-list>
|
||||
</ng-template>
|
||||
</button>
|
||||
<hr/>
|
||||
<button
|
||||
iconStart="@tui.plus"
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
<footer>
|
||||
<button
|
||||
iconStart="@tui.star"
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
>
|
||||
Favorites
|
||||
</button>
|
||||
<button
|
||||
tuiAsideItem
|
||||
type="button"
|
||||
[iconStart]="expanded() ? '@tui.chevron-left' : '@tui.chevron-right'"
|
||||
(click)="handleToggle()"
|
||||
>
|
||||
{{ expanded() ? 'Collapse' : 'Expand' }}
|
||||
</button>
|
||||
</footer>
|
||||
</aside>
|
||||
<main tuiNavigationMain>
|
||||
<nav
|
||||
compact
|
||||
tuiSubheader
|
||||
[style.position]="'sticky'"
|
||||
>
|
||||
<tui-breadcrumbs [itemsLimit]="10">
|
||||
<ng-container *ngFor="let item of breadcrumbs; let last = last">
|
||||
<ng-container *ngIf="last">
|
||||
<strong
|
||||
*tuiItem
|
||||
tuiFade
|
||||
>
|
||||
{{ item }}
|
||||
</strong>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="!last">
|
||||
<button
|
||||
*tuiItem
|
||||
tuiLink
|
||||
type="button"
|
||||
>
|
||||
{{ item }}
|
||||
</button>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
</tui-breadcrumbs>
|
||||
<tui-tabs tuiFade>
|
||||
<button
|
||||
tuiTab
|
||||
type="button"
|
||||
>
|
||||
Default view
|
||||
</button>
|
||||
<button
|
||||
tuiTab
|
||||
type="button"
|
||||
>
|
||||
Details
|
||||
</button>
|
||||
<button
|
||||
tuiTab
|
||||
type="button"
|
||||
>
|
||||
Followers
|
||||
</button>
|
||||
</tui-tabs>
|
||||
<button
|
||||
appearance="secondary"
|
||||
tuiButton
|
||||
type="button"
|
||||
>
|
||||
Secondary
|
||||
</button>
|
||||
<button
|
||||
tuiButton
|
||||
type="button"
|
||||
>
|
||||
Primary
|
||||
</button>
|
||||
</nav>
|
||||
<ng-container *tuiRepeatTimes="let index of 10">
|
||||
<form
|
||||
tuiAppearance="floating"
|
||||
tuiCardLarge
|
||||
tuiForm="m"
|
||||
[style.grid-column]="'2 / span 7'"
|
||||
[style.margin-top.rem]="1"
|
||||
>
|
||||
<header tuiHeader>
|
||||
<h2 tuiTitle>
|
||||
Registration form
|
||||
<span tuiSubtitle>Tell us about yourself</span>
|
||||
</h2>
|
||||
</header>
|
||||
<tui-textfield>
|
||||
<label tuiLabel>Name</label>
|
||||
<input
|
||||
placeholder="John Wick"
|
||||
tuiTextfield
|
||||
/>
|
||||
</tui-textfield>
|
||||
<footer>
|
||||
<button
|
||||
appearance="secondary"
|
||||
tuiButton
|
||||
type="button"
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
tuiButton
|
||||
type="submit"
|
||||
>
|
||||
Ok
|
||||
</button>
|
||||
</footer>
|
||||
</form>
|
||||
<div
|
||||
tuiAppearance="outline-grayscale"
|
||||
tuiCardLarge
|
||||
[style.grid-column]="'span 3'"
|
||||
[style.margin-top.rem]="1"
|
||||
>
|
||||
<h2 tuiTitle>
|
||||
Sidebar content
|
||||
<span tuiSubtitle>Use CSS grid to position</span>
|
||||
</h2>
|
||||
</div>
|
||||
</ng-container>
|
||||
</main>
|
||||
</div>
|
||||
0
src/app/pages/dashboard/dashboard.component.scss
Normal file
0
src/app/pages/dashboard/dashboard.component.scss
Normal file
67
src/app/pages/dashboard/dashboard.component.ts
Normal file
67
src/app/pages/dashboard/dashboard.component.ts
Normal file
@@ -0,0 +1,67 @@
|
||||
import {NgForOf, NgIf} from '@angular/common';
|
||||
import {Component, signal} from '@angular/core';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {RouterLink} from '@angular/router';
|
||||
import {TuiPortals, TuiRepeatTimes} from '@taiga-ui/cdk';
|
||||
import {TuiAppearance, TuiButton, TuiDataList, TuiDropdown, TuiLink, TuiTextfield, TuiTitle,} from '@taiga-ui/core';
|
||||
import {TuiBadge, TuiBreadcrumbs, TuiChevron, TuiDataListDropdownManager, TuiFade, TuiTabs,} from '@taiga-ui/kit';
|
||||
import {TuiCardLarge, TuiForm, TuiHeader, TuiNavigation} from '@taiga-ui/layout';
|
||||
|
||||
const ICON =
|
||||
"data:image/svg+xml,%0A%3Csvg width='32' height='32' viewBox='0 0 32 32' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect width='32' height='32' rx='8' fill='url(%23paint0_linear_2036_35276)'/%3E%3Cmask id='mask0_2036_35276' style='mask-type:alpha' maskUnits='userSpaceOnUse' x='6' y='5' width='20' height='21'%3E%3Cpath d='M18.2399 9.36607C21.1347 10.1198 24.1992 9.8808 26 7.4922C26 7.4922 21.5645 5 16.4267 5C11.2888 5 5.36726 8.69838 6.05472 16.6053C6.38707 20.4279 6.65839 23.7948 6.65839 23.7948C8.53323 22.1406 9.03427 19.4433 8.97983 16.9435C8.93228 14.7598 9.55448 12.1668 12.1847 10.4112C14.376 8.94865 16.4651 8.90397 18.2399 9.36607Z' fill='url(%23paint1_linear_2036_35276)'/%3E%3Cpath d='M11.3171 20.2647C9.8683 17.1579 10.7756 11.0789 16.4267 11.0789C20.4829 11.0789 23.1891 12.8651 22.9447 18.9072C22.9177 19.575 22.9904 20.2455 23.2203 20.873C23.7584 22.3414 24.7159 24.8946 24.7159 24.8946C23.6673 24.5452 22.8325 23.7408 22.4445 22.7058L21.4002 19.921L21.2662 19.3848C21.0202 18.4008 20.136 17.7104 19.1217 17.7104H17.5319L17.6659 18.2466C17.9119 19.2306 18.7961 19.921 19.8104 19.921L22.0258 26H10.4754C10.7774 24.7006 12.0788 23.2368 11.3171 20.2647Z' fill='url(%23paint2_linear_2036_35276)'/%3E%3C/mask%3E%3Cg mask='url(%23mask0_2036_35276)'%3E%3Crect x='4' y='4' width='24' height='24' fill='white'/%3E%3C/g%3E%3Cdefs%3E%3ClinearGradient id='paint0_linear_2036_35276' x1='0' y1='0' x2='32' y2='32' gradientUnits='userSpaceOnUse'%3E%3Cstop stop-color='%23A681D4'/%3E%3Cstop offset='1' stop-color='%237D31D4'/%3E%3C/linearGradient%3E%3ClinearGradient id='paint1_linear_2036_35276' x1='6.0545' y1='24.3421' x2='28.8119' y2='3.82775' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0.0001' stop-opacity='0.996458'/%3E%3Cstop offset='0.317708'/%3E%3Cstop offset='1' stop-opacity='0.32'/%3E%3C/linearGradient%3E%3ClinearGradient id='paint2_linear_2036_35276' x1='6.0545' y1='24.3421' x2='28.8119' y2='3.82775' gradientUnits='userSpaceOnUse'%3E%3Cstop offset='0.0001' stop-opacity='0.996458'/%3E%3Cstop offset='0.317708'/%3E%3Cstop offset='1' stop-opacity='0.32'/%3E%3C/linearGradient%3E%3C/defs%3E%3C/svg%3E%0A";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'app-dashboard',
|
||||
imports: [
|
||||
FormsModule,
|
||||
NgForOf,
|
||||
NgIf,
|
||||
RouterLink,
|
||||
TuiAppearance,
|
||||
TuiBadge,
|
||||
TuiBreadcrumbs,
|
||||
TuiButton,
|
||||
TuiCardLarge,
|
||||
TuiChevron,
|
||||
TuiDataList,
|
||||
TuiDataListDropdownManager,
|
||||
TuiDropdown,
|
||||
TuiFade,
|
||||
TuiForm,
|
||||
TuiHeader,
|
||||
TuiLink,
|
||||
TuiNavigation,
|
||||
TuiRepeatTimes,
|
||||
TuiTabs,
|
||||
TuiTextfield,
|
||||
TuiTitle,
|
||||
],
|
||||
templateUrl: './dashboard.component.html',
|
||||
styleUrl: './dashboard.component.scss'
|
||||
})
|
||||
export class DashboardComponent extends TuiPortals {
|
||||
protected expanded = signal(false);
|
||||
protected open = false;
|
||||
protected switch = false;
|
||||
protected readonly routes: any = {};
|
||||
protected readonly breadcrumbs = ['Home', 'Angular', 'Repositories', 'Taiga UI'];
|
||||
|
||||
protected readonly drawer = {
|
||||
Components: [
|
||||
{name: 'Button', icon: ICON},
|
||||
{name: 'Input', icon: ICON},
|
||||
{name: 'Tooltip', icon: ICON},
|
||||
],
|
||||
Essentials: [
|
||||
{name: 'Getting started', icon: ICON},
|
||||
{name: 'Showcase', icon: ICON},
|
||||
{name: 'Typography', icon: ICON},
|
||||
],
|
||||
};
|
||||
|
||||
protected handleToggle(): void {
|
||||
this.expanded.update((e) => !e);
|
||||
}
|
||||
|
||||
}
|
||||
41
src/app/pages/home/home.component.html
Normal file
41
src/app/pages/home/home.component.html
Normal file
@@ -0,0 +1,41 @@
|
||||
<!-- Ignore this part, it is only here to position drawer inside the example block -->
|
||||
<div class="custom-portal">
|
||||
<ng-container #viewContainer/>
|
||||
</div>
|
||||
<header>
|
||||
<div class="navbar">
|
||||
<img src="assets/logo-minimal.png" alt="App Logo" class="img-fluid">
|
||||
<ul>
|
||||
<li><a routerLink="/home/agenda" routerLinkActive="active">Agenda</a></li>
|
||||
<li><a routerLink="/home/klanten" routerLinkActive="active">Klanten</a></li>
|
||||
</ul>
|
||||
<hr/>
|
||||
<button
|
||||
tuiChevron
|
||||
type="button"
|
||||
[tuiDropdown]="dropdownContent"
|
||||
[tuiDropdownManual]="open"
|
||||
[tuiObscuredEnabled]="open"
|
||||
(click)="onClick()"
|
||||
(tuiActiveZoneChange)="onActiveZone($event)"
|
||||
(tuiObscured)="onObscured($event)"
|
||||
>
|
||||
<tui-avatar src="{{getInitials()}}"/>
|
||||
<ng-template #dropdownContent>
|
||||
<div class="dropdown">
|
||||
<h3>{{fullName}}</h3>
|
||||
<button
|
||||
size="m"
|
||||
tuiButton
|
||||
type="button"
|
||||
(click)="logout()"
|
||||
>
|
||||
Uitloggen
|
||||
</button>
|
||||
</div>
|
||||
</ng-template>
|
||||
</button>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<router-outlet></router-outlet>
|
||||
62
src/app/pages/home/home.component.scss
Normal file
62
src/app/pages/home/home.component.scss
Normal file
@@ -0,0 +1,62 @@
|
||||
.navbar {
|
||||
background-color: #f8f9fa;
|
||||
display: flex
|
||||
}
|
||||
|
||||
ul {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
list-style-type: none;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
li {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
img {
|
||||
display: block;
|
||||
max-width: 230px;
|
||||
max-height: 95px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
hr {
|
||||
clear: both;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
tui-avatar {
|
||||
margin-right: 32px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
font-size: 0.8125rem;
|
||||
line-height: 1.25rem;
|
||||
padding: 0.25rem 0.75rem;
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.t-content{
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
button{
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
55
src/app/pages/home/home.component.ts
Normal file
55
src/app/pages/home/home.component.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {FormsModule} from '@angular/forms';
|
||||
import {Router, RouterLink, RouterLinkActive, RouterModule} from '@angular/router';
|
||||
import {TuiAvatar, TuiChevron,} from '@taiga-ui/kit';
|
||||
import {AuthService} from '../../services/auth.service';
|
||||
import {User} from '../../models/user';
|
||||
import {TuiButton, TuiDropdown} from '@taiga-ui/core';
|
||||
import {TuiActiveZone, TuiObscured} from '@taiga-ui/cdk';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
imports: [TuiAvatar, RouterModule, FormsModule, RouterLink, RouterLinkActive, TuiDropdown, TuiObscured, TuiActiveZone, TuiButton, TuiChevron],
|
||||
templateUrl: './home.component.html',
|
||||
styleUrl: './home.component.scss'
|
||||
})
|
||||
export class HomeComponent implements OnInit {
|
||||
user: User
|
||||
fullName: string
|
||||
|
||||
getInitials(): string {
|
||||
this.user = this.authService.getUserInfo();
|
||||
this.fullName = this.user.firstName + ' ' + this.user.lastName;
|
||||
return this.fullName.split(' ').map((n) => n[0]).join('').substring(0, 2);
|
||||
}
|
||||
|
||||
protected open = false;
|
||||
|
||||
protected onClick(): void {
|
||||
this.open = !this.open;
|
||||
}
|
||||
|
||||
protected onObscured(obscured: boolean): void {
|
||||
if (obscured) {
|
||||
this.open = false;
|
||||
}
|
||||
}
|
||||
|
||||
protected onActiveZone(active: boolean): void {
|
||||
this.open = active && this.open;
|
||||
}
|
||||
|
||||
constructor(private authService: AuthService, private router: Router) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
if (!this.authService.isAuthenticated()) {
|
||||
this.router.navigate(['login']);
|
||||
}
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.authService.logout();
|
||||
this.router.navigate(['login']);
|
||||
}
|
||||
}
|
||||
101
src/app/pages/klanten/klanten.component.html
Normal file
101
src/app/pages/klanten/klanten.component.html
Normal file
@@ -0,0 +1,101 @@
|
||||
<div class="container">
|
||||
<div class="heading">
|
||||
<h1>Klanten</h1>
|
||||
</div>
|
||||
<div class="content">
|
||||
<div class="toolbar">
|
||||
<button
|
||||
size="m"
|
||||
tuiButton
|
||||
appearance="secondary"
|
||||
type="button"
|
||||
(click)="toggleCustomerModal()"
|
||||
>
|
||||
<tui-icon
|
||||
icon="@tui.plus"
|
||||
[style.height.rem]="1"
|
||||
/>
|
||||
Klant toevoegen
|
||||
</button>
|
||||
</div>
|
||||
<table class="styled-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Naam</th>
|
||||
<th>Email</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let customer of customers" (click)="selectCustomer(customer)">
|
||||
<td>{{ customer.firstName }} {{ customer.lastName }}</td>
|
||||
<td>{{ customer.email }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<app-modal title="Nieuwe klant toevoegen" *ngIf="showNewCustomer" (close)="toggleCustomerModal()">
|
||||
<form [formGroup]="customerForm">
|
||||
<tui-input
|
||||
formControlName="firstName"
|
||||
tuiTextfieldSize="m"
|
||||
[tuiTextfieldCleaner]="true"
|
||||
>
|
||||
Voornaam
|
||||
<input
|
||||
tuiTextfieldLegacy
|
||||
type="text"
|
||||
formControlName="firstName"
|
||||
/>
|
||||
</tui-input>
|
||||
<br>
|
||||
|
||||
<tui-input
|
||||
formControlName="lastName"
|
||||
tuiTextfieldSize="m"
|
||||
[tuiTextfieldCleaner]="true"
|
||||
>
|
||||
Achternaam
|
||||
<input
|
||||
tuiTextfieldLegacy
|
||||
type="text"
|
||||
formControlName="lastName"
|
||||
/>
|
||||
</tui-input>
|
||||
<br>
|
||||
<tui-input
|
||||
formControlName="email"
|
||||
tuiTextfieldSize="m"
|
||||
[tuiTextfieldCleaner]="true"
|
||||
>
|
||||
Email
|
||||
<input
|
||||
tuiTextfieldLegacy
|
||||
autocomplete="email"
|
||||
type="email"
|
||||
formControlName="email"
|
||||
/>
|
||||
</tui-input>
|
||||
<br>
|
||||
<button
|
||||
appearance="secondary"
|
||||
size="m"
|
||||
tuiButton
|
||||
(click)="saveCustomer()"
|
||||
[disabled]="customerForm.invalid"
|
||||
type="button">
|
||||
<tui-icon
|
||||
icon="@tui.save"
|
||||
[style.height.rem]="1"
|
||||
/>
|
||||
Opslaan
|
||||
</button>
|
||||
</form>
|
||||
</app-modal>
|
||||
|
||||
<app-modal title="Klant bekijken" *ngIf="selectedCustomer != undefined" (close)="selectedCustomer = undefined">
|
||||
<app-customer-details [customer]="selectedCustomer"></app-customer-details>
|
||||
</app-modal>
|
||||
|
||||
72
src/app/pages/klanten/klanten.component.scss
Normal file
72
src/app/pages/klanten/klanten.component.scss
Normal file
@@ -0,0 +1,72 @@
|
||||
h1 {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h2 {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
|
||||
.heading {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.styled-table {
|
||||
width: 100%; /* Tabel breedte */
|
||||
border-collapse: collapse; /* Verwijdert dubbele randen */
|
||||
margin: 20px 0; /* Ruimte rondom de tabel */
|
||||
font-size: 16px;
|
||||
text-align: left; /* Tekst uitlijning */
|
||||
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.1); /* Zachte schaduw */
|
||||
border-radius: 10px; /* Afgeronde hoeken */
|
||||
overflow: hidden; /* Hoeken correct afronden */
|
||||
}
|
||||
|
||||
.styled-table thead {
|
||||
background-color: #868383; /* Blauwe kopregel */
|
||||
color: #ffffff; /* Witte tekst */
|
||||
//text-transform: uppercase; /* Hoofdletters */
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.styled-table th, .styled-table td {
|
||||
padding: 12px 15px; /* Ruimte binnen de cellen */
|
||||
}
|
||||
|
||||
.styled-table tbody tr {
|
||||
border-bottom: 1px solid #dddddd; /* Lichte scheidingslijn */
|
||||
}
|
||||
|
||||
.styled-table tbody tr:nth-child(even) {
|
||||
background-color: #f3f3f3; /* Afwisselende rijkleuren */
|
||||
}
|
||||
|
||||
.styled-table tbody tr:hover {
|
||||
background-color: #d3d2d2; /* Hover effect */
|
||||
cursor: pointer;
|
||||
transition: background-color 0.3s ease;
|
||||
}
|
||||
|
||||
.styled-table tbody tr:last-of-type {
|
||||
border-bottom: none; /* Verwijdert de onderste scheidingslijn */
|
||||
}
|
||||
|
||||
.toolbar {
|
||||
button {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
margin-bottom: 12px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
|
||||
}
|
||||
|
||||
|
||||
71
src/app/pages/klanten/klanten.component.ts
Normal file
71
src/app/pages/klanten/klanten.component.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import {Component, OnInit} from '@angular/core';
|
||||
import {NgForOf, NgIf} from '@angular/common';
|
||||
import {Customer} from '../../models/customer';
|
||||
import {CustomerService} from '../../services/customer.service';
|
||||
import {TuiButton, TuiIcon} from '@taiga-ui/core';
|
||||
import {ModalComponent} from '../../components/modal/modal.component';
|
||||
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
||||
import {TuiInputCopyModule, TuiInputModule, TuiTextfieldControllerModule} from '@taiga-ui/legacy';
|
||||
import {CustomerDetailsComponent} from '../../components/customer-details/customer-details.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-klanten',
|
||||
imports: [
|
||||
NgForOf,
|
||||
TuiButton,
|
||||
TuiIcon,
|
||||
ModalComponent,
|
||||
NgIf,
|
||||
ReactiveFormsModule,
|
||||
TuiInputCopyModule,
|
||||
TuiInputModule,
|
||||
TuiTextfieldControllerModule,
|
||||
CustomerDetailsComponent
|
||||
],
|
||||
templateUrl: './klanten.component.html',
|
||||
styleUrl: './klanten.component.scss'
|
||||
})
|
||||
export class KlantenComponent implements OnInit {
|
||||
customers: Customer[];
|
||||
showNewCustomer: boolean = false;
|
||||
customerForm: FormGroup;
|
||||
selectedCustomer: Customer;
|
||||
|
||||
constructor(private customerService: CustomerService) {
|
||||
}
|
||||
|
||||
ngOnInit(): void {
|
||||
this.getCustomers();
|
||||
this.customerForm = new FormGroup({
|
||||
firstName: new FormControl('', Validators.required),
|
||||
lastName: new FormControl('', Validators.required),
|
||||
email: new FormControl('', [Validators.required, Validators.email]),
|
||||
})
|
||||
}
|
||||
|
||||
toggleCustomerModal() {
|
||||
this.showNewCustomer = !this.showNewCustomer;
|
||||
}
|
||||
|
||||
saveCustomer() {
|
||||
const firstName = this.customerForm.get('firstName').value
|
||||
const lastName = this.customerForm.get('lastName').value
|
||||
const email = this.customerForm.get('email').value
|
||||
const customer = new Customer(firstName, lastName, email);
|
||||
|
||||
this.customerService.addCustomer(customer).subscribe(() => {
|
||||
this.showNewCustomer = false;
|
||||
this.getCustomers()
|
||||
})
|
||||
}
|
||||
|
||||
getCustomers() {
|
||||
this.customerService.getCustomers().subscribe(customers => {
|
||||
this.customers = customers
|
||||
});
|
||||
}
|
||||
|
||||
selectCustomer(customer: Customer) {
|
||||
this.selectedCustomer = customer
|
||||
}
|
||||
}
|
||||
23
src/app/pages/login/login.component.html
Normal file
23
src/app/pages/login/login.component.html
Normal file
@@ -0,0 +1,23 @@
|
||||
<div class="container">
|
||||
<div class="center-container">
|
||||
<form tuiAppearance="floating" tuiCardLarge tuiForm="m" [formGroup]="form" [style.max-width.rem]="32">
|
||||
<header tuiHeader>
|
||||
<img class="header" src="assets/logo-minimal.png" alt="Logo" tuiHeaderIcon/>
|
||||
</header>
|
||||
<tui-textfield>
|
||||
<label tuiLabel>Gebruikersnaam</label>
|
||||
<input formControlName="username" placeholder="Voer je gebruikersnaam in" tuiTextfield/>
|
||||
</tui-textfield>
|
||||
<tui-textfield>
|
||||
<label tuiLabel>Wachtwoord</label>
|
||||
<input formControlName="password" type="password" placeholder="Voer je wachtwoord in" tuiTextfield/>
|
||||
</tui-textfield>
|
||||
<tui-error [error]="computedError" />
|
||||
<footer>
|
||||
<button tuiButton class="custom-button" type="submit" [disabled]="form.invalid" (click)="login()">
|
||||
Inloggen
|
||||
</button>
|
||||
</footer>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
49
src/app/pages/login/login.component.scss
Normal file
49
src/app/pages/login/login.component.scss
Normal file
@@ -0,0 +1,49 @@
|
||||
.center-container {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100vh;
|
||||
/* Adjust as needed */
|
||||
}
|
||||
|
||||
tui-error{
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.header {
|
||||
text-align: center;
|
||||
margin-bottom: 28px;
|
||||
max-width: 300px;
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
::ng-deep button.custom-button {
|
||||
background-color: #222222 !important;
|
||||
/* Pas kleur aan */
|
||||
color: white !important;
|
||||
/* Tekstkleur aanpassen */
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
--s: 200px; /* control the size */
|
||||
--c1: #1d1d1d;
|
||||
--c2: #4e4f51;
|
||||
--c3: #3c3c3c;
|
||||
|
||||
background: repeating-conic-gradient(
|
||||
from 30deg,
|
||||
#0000 0 120deg,
|
||||
var(--c3) 0 180deg
|
||||
) calc(0.5 * var(--s)) calc(0.5 * var(--s) * 0.577),
|
||||
repeating-conic-gradient(
|
||||
from 30deg,
|
||||
var(--c1) 0 60deg,
|
||||
var(--c2) 0 120deg,
|
||||
var(--c3) 0 180deg
|
||||
);
|
||||
background-size: var(--s) calc(var(--s) * 0.577);
|
||||
}
|
||||
57
src/app/pages/login/login.component.ts
Normal file
57
src/app/pages/login/login.component.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {FormControl, FormGroup, ReactiveFormsModule, Validators} from '@angular/forms';
|
||||
import {Router} from '@angular/router';
|
||||
import {TuiAppearance, TuiButton, TuiError, TuiTextfield,} from '@taiga-ui/core';
|
||||
import {TuiCardLarge, TuiForm, TuiHeader} from '@taiga-ui/layout';
|
||||
import {AuthService} from '../../services/auth.service';
|
||||
import {UserDto} from '../../models/user-dto';
|
||||
import {HttpErrorResponse} from '@angular/common/http';
|
||||
import {TuiValidationError} from '@taiga-ui/cdk';
|
||||
|
||||
@Component({
|
||||
selector: 'app-login',
|
||||
imports: [
|
||||
ReactiveFormsModule,
|
||||
TuiAppearance,
|
||||
TuiButton,
|
||||
TuiCardLarge,
|
||||
TuiForm,
|
||||
TuiHeader,
|
||||
TuiTextfield,
|
||||
TuiError,
|
||||
],
|
||||
templateUrl: './login.component.html',
|
||||
styleUrl: './login.component.scss'
|
||||
})
|
||||
export class LoginComponent {
|
||||
form: FormGroup;
|
||||
protected enabled = false;
|
||||
|
||||
protected error = new TuiValidationError('Ongeldige gebruikersnaam of wachtwoord.');
|
||||
|
||||
protected get computedError(): TuiValidationError | null {
|
||||
return this.enabled ? this.error : null;
|
||||
}
|
||||
|
||||
constructor(private router: Router, private authService: AuthService) {
|
||||
this.form = new FormGroup({
|
||||
username: new FormControl('', Validators.required),
|
||||
password: new FormControl('', Validators.required)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
login() {
|
||||
this.authService.login(this.form.get('username').value, this.form.get('password').value).subscribe({
|
||||
next: (user: UserDto) => {
|
||||
localStorage.setItem('token', user.token);
|
||||
this.router.navigate(['/home/agenda']);
|
||||
},
|
||||
error: (err: HttpErrorResponse) => {
|
||||
if (err.status === 401) {
|
||||
this.enabled = true;
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user