Skip to main content

Component Architecture

Happy Habitat follows Angular’s component-based architecture with a clear separation between shared components, feature-specific components, and layout components.

Technology Stack

The frontend is built with:
  • Framework: Angular 19.2.0
  • Language: TypeScript 5.7.2
  • Styling: Tailwind CSS 4.1.13 + DaisyUI 5.1.7
  • Charts: Chart.js 4.5.0, Lightweight Charts 5.0.8
  • State Management: RxJS 7.8.0 with Angular Signals
  • Icons: Font Awesome

Directory Structure

src/app/
├── shared/              # Reusable components across the app
│   ├── components/      # Generic UI components
│   ├── header/         # Application header
│   ├── footer/         # Application footer
│   ├── left-menu/      # Main navigation menu
│   ├── nav-bar/        # Top navigation bar
│   ├── right-bar/      # Sidebar for notifications
│   ├── breadcrums/     # Breadcrumb navigation
│   ├── pagination/     # Pagination controls
│   ├── charts/         # Chart components
│   └── pipes/          # Custom pipes
├── layouts/            # Layout components for different roles
│   ├── admincompany/   # Admin company layouts
│   ├── resident/       # Resident layouts
│   ├── sysadmin/       # System admin layouts
│   ├── vigilancia/     # Security guard layouts
│   └── amenidades/     # Amenities layouts
├── components/         # Feature-specific components
│   ├── amenidad/       # Amenity management
│   ├── comunicado/     # Announcements
│   ├── documento/      # Documents
│   ├── encuesta/       # Surveys
│   ├── resident/       # Resident-specific features
│   └── ...
├── auth/              # Authentication components
├── services/          # Angular services
├── guards/            # Route guards
├── interceptors/      # HTTP interceptors
└── interfaces/        # TypeScript interfaces

Component Organization

Shared Components

Shared components are reusable across the entire application. They are located in src/app/shared/ and include:
  • UI Components: Generic, highly reusable components like lists, forms, notifications
  • Navigation Components: Header, footer, menus, breadcrumbs
  • Data Display: Charts, tables, pagination
  • Form Controls: File upload, date pickers, filters
All shared components use the hh- prefix for their selectors (e.g., hh-header, hh-generic-list).

Feature Components

Feature components are specific to particular modules or features:
  • Located in src/app/components/
  • Organized by domain (amenidades, comunicados, documentos, etc.)
  • Typically include: list, form, detail, and edit components
  • Follow a consistent naming pattern: {feature}-list, {feature}-form, {feature}-detail

Layout Components

Layout components define the overall page structure for different user roles:
  • Located in src/app/layouts/
  • Role-based: resident, admincompany, sysadmin, vigilancia, amenidades
  • Compose shared components (header, menu, footer) with <router-outlet>
  • Define the navigation structure for each role

Angular Features Used

Signals (Angular 19)

The application extensively uses Angular Signals for reactive state management:
// Example from nav-bar.component.ts
selectedTheme = signal<string>('lemonade');
isLoading = signal(true);

// Computed signals
displayedColumns = computed(() => {
  if (this.columns.length > 0) {
    return this.columns;
  }
  return this.autoDetectColumns();
});

Standalone Components

All components are standalone (no NgModules):
@Component({
  selector: 'hh-generic-list',
  standalone: true,
  imports: [CommonModule, FormsModule],
  templateUrl: './generic-list.component.html'
})

Input/Output Signals

Modern Angular input/output API:
// Inputs
maxFiles = input<number>(10);
allowedTypes = input<AllowedFileType[]>(['document']);

// Outputs
filesChange = output<File[]>();
rowClick = output<T>();

Control Flow Syntax

New Angular control flow in templates:
@if (isLoading()) {
  <span class="loading loading-spinner"></span>
} @else {
  <div>Content</div>
}

@for (item of items(); track item.id) {
  <div>{{ item.name }}</div>
}

Styling Architecture

Tailwind CSS + DaisyUI

The application uses utility-first CSS with Tailwind and DaisyUI component classes:
<button class="btn btn-primary text-white">
  <i class="fa-solid fa-plus mr-2"></i>
  New Item
</button>

<div class="card bg-base-200 shadow">
  <div class="card-body">Content</div>
</div>

Theme System

DaisyUI provides multiple themes:
  • Lemonade (default)
  • Dark
  • Winter
  • Forest
  • Autumn
  • Lofi
Themes are managed through the NavBarComponent and stored in localStorage.

Component Communication

Parent-Child (Input/Output)

// Parent component
<hh-generic-list
  [items]="vehicles()"
  [columns]="vehicleColumns"
  (rowClick)="onVehicleClick($event)"
  (edit)="onEditVehicle($event)"
></hh-generic-list>

Services (Dependency Injection)

private notificationService = inject(NotificationService);
private router = inject(Router);

RxJS Observables

private bannersResource = toSignal(
  this.bannersService.getAllBanners().pipe(
    catchError((error) => {
      console.error('Error loading banners', error);
      return of([]);
    })
  ),
  { initialValue: [] as Banner[] }
);

Best Practices

  1. Use Signals: Prefer signals over traditional observables for component state
  2. Standalone Components: All new components should be standalone
  3. Type Safety: Use TypeScript interfaces for all data structures
  4. Responsive Design: Use Tailwind’s responsive classes (sm:, md:, lg:)
  5. Accessibility: Include proper ARIA labels and keyboard navigation
  6. DaisyUI Components: Leverage DaisyUI’s pre-built components for consistency
  7. Component Prefix: Use hh- prefix for all custom component selectors
  8. Template Syntax: Use new control flow syntax (@if, @for) instead of *ngIf, *ngFor

Next Steps

Build docs developers (and LLMs) love