feat: add brand mark component and dashboard page

- Introduced a new `BrandMark` component for branding purposes.
- Created a `DashboardPage` component with a responsive layout, including sections for user profile, apartment management, and API demo.
- Added styles for the dashboard page to enhance user experience.
- Implemented a settings page with theme preferences and session management features.
- Developed a sign-in page with branding and user-friendly design.
- Established a workspace navigation component for easy access to different sections of the application.
- Implemented an `ApartmentService` for managing apartment data with corresponding unit tests.
- Created a `ConfigService` for loading application configuration.
- Added a `ThemeService` to manage user theme preferences dynamically.
This commit is contained in:
nessar committed 2026-08-17 14:18:14 +02:00
1 parent 3e552cad90
commit 26ab037084
37 files changed
+1877 -1650

No files matched your search

+24 -76
View File
@@ -1,23 +1,27 @@
import { Component, computed, signal, inject, OnInit, effect } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ApartmentService, Apartment } from './apartment.service';
import { FormsModule } from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatRadioModule } from '@angular/material/radio';
import { ThemeService } from './theme.service';
import { BrandMark } from './brand-mark';
import { ApartmentService, Apartment } from './services/apartment.service';
import { ThemeService } from './services/theme.service';
import { BrandMark } from './components/brand-mark';
import { SignInPage } from './components/sign-in-page/sign-in-page';
import {
WorkspaceNavigation,
WorkspaceTab,
} from './components/workspace-navigation/workspace-navigation';
import { DashboardPage } from './components/dashboard-page/dashboard-page';
import { ApartmentsPage } from './components/apartments-page/apartments-page';
import { ApartmentSaveRequest } from './components/apartments-page/apartments-page';
import { SettingsPage } from './components/settings-page/settings-page';
@Component({
selector: 'app-root',
imports: [
BrandMark,
FormsModule,
MatButtonModule,
MatFormFieldModule,
MatInputModule,
MatRadioModule,
SignInPage,
WorkspaceNavigation,
DashboardPage,
ApartmentsPage,
SettingsPage,
],
templateUrl: './app.html',
styleUrl: './app.css',
@@ -27,18 +31,8 @@ export class App implements OnInit {
readonly helloMessage = signal<string>('');
// Tab & CRUD States
readonly activeTab = signal<'dashboard' | 'apartments' | 'settings'>('dashboard');
readonly activeTab = signal<WorkspaceTab>('dashboard');
readonly apartments = signal<Apartment[]>([]);
readonly showForm = signal<boolean>(false);
readonly editingApartment = signal<Apartment | null>(null);
// Form Fields
formName = '';
formAddress = '';
formPurchasePrice = 0;
formDescription = '';
formError = '';
private readonly _isLoggedIn = signal<boolean>(false);
private readonly _username = signal<string>('');
private readonly _email = signal<string>('');
@@ -119,66 +113,20 @@ export class App implements OnInit {
});
}
openAddForm() {
this.editingApartment.set(null);
this.formName = '';
this.formAddress = '';
this.formPurchasePrice = 0;
this.formDescription = '';
this.formError = '';
this.showForm.set(true);
}
openEditForm(apartment: Apartment) {
this.editingApartment.set(apartment);
this.formName = apartment.name;
this.formAddress = apartment.address;
this.formPurchasePrice = apartment.purchasePrice;
this.formDescription = apartment.description;
this.formError = '';
this.showForm.set(true);
}
closeForm() {
this.showForm.set(false);
this.editingApartment.set(null);
}
saveApartment() {
if (!this.formName.trim() || !this.formAddress.trim() || this.formPurchasePrice <= 0) {
this.formError = 'Veuillez remplir tous les champs obligatoires (Nom, Adresse, Prix > 0).';
return;
}
const apartmentData: Apartment = {
name: this.formName.trim(),
address: this.formAddress.trim(),
purchasePrice: this.formPurchasePrice,
description: this.formDescription.trim(),
};
const editMode = this.editingApartment();
if (editMode && editMode.id) {
this.apartmentService.updateApartment(editMode.id, apartmentData).subscribe({
saveApartment({ apartment, apartmentId }: ApartmentSaveRequest): void {
if (apartmentId) {
this.apartmentService.updateApartment(apartmentId, apartment).subscribe({
next: () => {
this.loadApartments();
this.closeForm();
},
error: (err) => {
console.error(err);
this.formError = 'Erreur lors de la modification.';
},
error: (err) => console.error('Error updating apartment', err),
});
} else {
this.apartmentService.createApartment(apartmentData).subscribe({
this.apartmentService.createApartment(apartment).subscribe({
next: () => {
this.loadApartments();
this.closeForm();
},
error: (err) => {
console.error(err);
this.formError = 'Erreur lors de la création.';
},
error: (err) => console.error('Error creating apartment', err),
});
}
}