Skip to main content
The driver profile system manages all driver-related information including personal details, vehicle information, account settings, and verification status. This data is essential for trip matching, regulatory compliance, and customer trust.

User Profile Model

The app uses several user models depending on the context:

UserProfile (Basic)

Used for authentication and basic profile display:
interface UserProfile {
  id: string | null;
  name: string | null;
  email: string | null;
  phoneNumber?: string | null;
  profilePictureUrl?: string | null;
  createdAt?: string;
}
Retrieving Profile:
me(useCookie: boolean = true): Observable<UserProfile> {
  const url = `${this.baseUrl}/users/profile`;
  const options = useCookie ? { withCredentials: true } : {};
  return this.http
    .get<{ success: boolean; message?: string; data?: UserProfile }>(url, options)
    .pipe(
      map(res => {
        if (!res || typeof res.data !== 'object' || res.data === null) {
          throw new Error('Profile response malformed');
        }
        return res.data as UserProfile;
      }),
      catchError(err => this.handleErrorAsApiError(err, url))
    );
}

UserListItem (List View)

Used when displaying drivers in lists or search results:
interface UserListItem {
  id: string;
  name: string;
  email: string;
  profilePictureUrl?: string;
  userType: UserType;
  status: UserStatus;
  phoneNumber?: string;
  createdAt: string;
}

User (Complete)

Full user model with all details for profile management:
interface User {
  id: string;
  name: string;
  email: string;
  emailVerified: boolean;
  phoneNumber?: string;
  phoneNumberVerified: boolean;
  userType: UserType;
  profilePictureUrl?: string;
  currentLocation?: Geolocation;
  vehicles: string[];  // Array of vehicle IDs
  status: UserStatus;
  preferredLanguage?: string;
  termsAcceptedAt?: string;
  privacyPolicyAcceptedAt?: string;
  createdAt: string;
  deletedAt?: string;
}

User Types & Status

User Type Enum

enum UserType {
  Passenger = 'passenger',
  Driver = 'driver',
  Admin = 'admin',
}
Type-Specific Features:
  • Request rides
  • Track drivers
  • Rate trips
  • Payment methods

User Status Enum

enum UserStatus {
  Active = 'active',
  Inactive = 'inactive',
  Banned = 'banned',
}
Status Meanings:
StatusDescriptionCan Drive?Can Login?
ActiveAccount in good standingYesYes
InactiveTemporarily disabled or dormantNoYes
BannedViolated terms of serviceNoNo
Banned Accounts: Banned drivers cannot log in or accept trips. This status is typically permanent and requires support intervention to reverse.

App Audience

The authentication system supports multiple app audiences:
type AppAudience = 'driver_app' | 'passenger_app' | 'admin_panel' | 'api_client';
Audience Context:
  • driver_app: Mobile app for drivers
  • passenger_app: Mobile app for passengers
  • admin_panel: Web dashboard for administrators
  • api_client: External integrations and services

Location Information

Driver location is tracked for trip matching and navigation:
interface Location {
  latitude: number;
  longitude: number;
}
Usage in User Model:
interface User {
  // ...
  currentLocation?: Location;
}
Example Location:
{
  "latitude": 23.1136,
  "longitude": -82.3666
}
Privacy Note: Location data is only collected when the driver app is active and the driver is online. Drivers can control their online/offline status.

Vehicle Management

Drivers can manage multiple vehicles associated with their account:
interface User {
  // ...
  vehicles: string[];  // Array of vehicle IDs
}
Vehicle Selection:
1

Register Vehicle

Driver adds vehicle details including make, model, year, license plate, and insurance information.
2

Verification

Admin reviews and approves vehicle documentation before it can be used for trips.
3

Select Active Vehicle

Driver chooses which registered vehicle they’re currently driving before going online.
4

Trip Assignment

System matches trips based on selected vehicle’s category and capacity.

Vehicle Information

While not shown in the user model excerpt, vehicles typically include:
interface Vehicle {
  id: string;
  driverId: string;
  make: string;
  model: string;
  year: number;
  color: string;
  licensePlate: string;
  category: VehicleCategory;
  capacity: number;
  status: 'pending' | 'approved' | 'rejected';
  insuranceExpiresAt?: string;
  inspectionExpiresAt?: string;
  photos: string[];
}

Verification Status

Driver accounts track verification of critical information:
interface User {
  // ...
  emailVerified: boolean;
  phoneNumberVerified: boolean;
}
Verification Requirements:

Email Verification

Required before driver can go online. Confirmed via email link.

Phone Verification

Required for account security and passenger contact. Confirmed via SMS code.

Identity Verification

Government ID upload and review (not shown in basic profile).

Background Check

Required in some markets for regulatory compliance.
The system tracks acceptance of legal documents:
interface User {
  // ...
  termsAcceptedAt?: string;
  privacyPolicyAcceptedAt?: string;
}
Agreement Flow:
Version Tracking: When terms or privacy policy are updated, drivers may need to re-accept. The timestamp helps track which version was accepted.

Preferred Language

Support for multiple languages:
interface User {
  // ...
  preferredLanguage?: string;  // ISO 639-1 code (e.g., "es", "en")
}
Supported Languages:
  • es - Spanish (Español)
  • en - English
  • Additional languages as needed
Language Selection:
async updatePreferredLanguage(language: string): Promise<void> {
  await this.userService.updateProfile({
    preferredLanguage: language
  });
  
  // Update app language
  this.translateService.use(language);
  
  // Store preference locally
  localStorage.setItem('preferredLanguage', language);
}

OAuth Integration

Support for social login providers:
interface OAuthProviders {
  googleId?: string;
  facebookId?: string;
  appleId?: string;
}
Authentication Methods:
enum AuthMethod {
  LOCAL = 'local',
  GOOGLE = 'google',
  FACEBOOK = 'facebook',
  APPLE = 'apple',
}
Traditional email/password authentication:
{
  method: AuthMethod.LOCAL,
  email: '[email protected]',
  password: '••••••••'
}

Profile Component

The profile component is currently minimal but can be extended:
export default class ProfileComponent implements OnInit {
  constructor() { }

  ngOnInit() {}
}
Recommended Enhancements:
1

Inject Services

Add AuthFacade, UserService, and other dependencies:
export default class ProfileComponent implements OnInit {
  private auth = inject(AuthFacade);
  private userService = inject(UserService);
  
  profile = signal<UserProfile | null>(null);
}
2

Load Profile Data

Fetch user profile on initialization:
async ngOnInit() {
  try {
    const profile = await this.auth.me().pipe(take(1)).toPromise();
    this.profile.set(profile);
  } catch (error) {
    console.error('Failed to load profile:', error);
  }
}
3

Add Update Methods

Implement profile update functionality:
async updateProfile(updates: Partial<UserProfile>) {
  try {
    const updated = await this.userService.updateProfile(updates);
    this.profile.set(updated);
  } catch (error) {
    // Handle error
  }
}
4

Add Photo Upload

Implement profile picture upload:
async uploadPhoto(file: File) {
  const formData = new FormData();
  formData.append('photo', file);
  
  const url = await this.userService.uploadProfilePhoto(formData);
  await this.updateProfile({ profilePictureUrl: url });
}

Profile Template Enhancement

The current template is minimal:
<p>
  profile works!
</p>
Suggested Template Structure:
<ion-header>
  <ion-toolbar>
    <ion-title>Mi Perfil</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  @if (profile(); as p) {
    <ion-card class="profile-card">
      <ion-card-content>
        <div class="profile-photo">
          <img [src]="p.profilePictureUrl || 'assets/default-avatar.png'" />
          <ion-button size="small" (click)="changePhoto()">
            <ion-icon name="camera"></ion-icon>
          </ion-button>
        </div>
        
        <div class="profile-info">
          <h2>{{ p.name }}</h2>
          <p>{{ p.email }}</p>
          <p>{{ p.phoneNumber }}</p>
        </div>
      </ion-card-content>
    </ion-card>

    <ion-card class="settings-card">
      <ion-list>
        <ion-item>
          <ion-label>Nombre</ion-label>
          <ion-input [(ngModel)]="p.name"></ion-input>
        </ion-item>
        
        <ion-item>
          <ion-label>Teléfono</ion-label>
          <ion-input [(ngModel)]="p.phoneNumber"></ion-input>
        </ion-item>
        
        <ion-item>
          <ion-label>Idioma</ion-label>
          <ion-select [(ngModel)]="preferredLanguage">
            <ion-select-option value="es">Español</ion-select-option>
            <ion-select-option value="en">English</ion-select-option>
          </ion-select>
        </ion-item>
      </ion-list>
    </ion-card>

    <ion-button expand="block" (click)="saveChanges()">
      Guardar Cambios
    </ion-button>
  }
</ion-content>

Best Practices

Data Validation

Validate all profile updates on both client and server to maintain data integrity.

Privacy Controls

Allow drivers to control what information is shared with passengers and other drivers.

Photo Optimization

Compress and resize profile photos before upload to reduce bandwidth and storage costs.

Verification Badges

Display verification status prominently to build passenger trust.

Security Considerations

Sensitive Data: Never expose sensitive information like full phone numbers, home addresses, or government IDs to passengers. Use masked or partial data where appropriate.
Data Protection:
  • Encrypt sensitive data in transit and at rest
  • Implement rate limiting on profile updates
  • Log all profile changes for audit trail
  • Require re-authentication for sensitive changes
  • Implement GDPR/privacy law compliance

Build docs developers (and LLMs) love