Profile Page (before rewards)

PHOTO EMBED

Wed Aug 07 2024 21:31:35 GMT+0000 (Coordinated Universal Time)

Saved by @iamkatmakhafola

//html
<div class="container-fluid" style="margin-top: 60px;">
  <div class="row justify-content-start">
    <!-- Back Button -->
    <div class="col-6">
      <i class="bi bi-arrow-left-circle header-icon" (click)="goBack()"></i>
    </div>

    <!-- My Profile Heading -->
    <div class="col-6">
      <h2 class="text-left">My Profile</h2>
      <span style="float: right;">
        <a class="navbar-brand" href="#" data-bs-toggle="modal" data-bs-target="#helpModal">
            <i class="bi bi-info-circle-fill">Help</i>
          </a>
      </span>
    </div>

    <!-- Left Side Menu -->
    <div class="col-md-3">
      <div routerLink="/orders" *ngIf="userTypeID === 3">
        <h5 class="small-heading">
          <i class="bi bi-cart4"></i>
          Orders
        </h5>
      </div>  
      <br>
      <h5 class="small-heading">
        <i class="bi bi-bell-fill"></i>
        Notifications
      </h5>
      <!-- Notification placeholder -->
      <div class="card mt-3">
        <div class="card-body">
          <div *ngIf="unredeemedRewards.length === 0" class="notification-item">
            <span>No Notifications</span>
          </div>
          <div *ngFor="let reward of unredeemedRewards" class="notification-item">
            <span style="float:left">{{ reward.rewardTypeName }}</span>
            <span style="float: right"><button class="btn btn-sm btn-primary" (click)="openRedeemModal(reward)">Redeem</button></span>
          </div>
        </div>
      </div>
    </div>

    

    <!-- Vertical Line Separator -->
    <div class="col-md-1">
      <div class="vertical-line"></div>
    </div>

    <!-- Right Side Form -->
    <div class="col-md-6">
      <form [formGroup]="profileForm" (ngSubmit)="onSubmit()">
        <h5 class="small-heading">
          <i class="bi bi-house-gear-fill"></i>
          Personal Details
        </h5>
        <div class="text-center mb-3">
          <div class="profile-photo-wrapper">
            <img [src]="userProfileImage" alt="Profile Photo" class="img-fluid rounded-circle profile-photo" *ngIf="userProfileImage">
            <div class="edit-photo-wrapper">
              <a href="#" (click)="enableEditMode($event)" class="edit-link">Edit</a>
              <label [class.disabled-icon]="!isEditMode" for="photoUpload" class="photo-upload-icon">
                <i class="bi bi-camera"></i>
              </label>
            </div>
            <input type="file" id="photoUpload" formControlName="photo" class="d-none" (change)="onPhotoChange($event)" [readonly]="!isEditMode" >
          </div>
        </div>
        

        <br>

      
        <div class="row">
          <div class="col-md-6 mb-3">
            <div class="form-group">
              <label for="name" class="form-label">Name</label>
              <input type="text" class="form-control" id="name" formControlName="name" [readonly]="!isEditMode" [ngClass]="{'disabled-input': !isEditMode}">
              <div *ngIf="profileForm.controls['name'].invalid && (profileForm.controls['name'].dirty || profileForm.controls['name'].touched)" class="alert">
                <div *ngIf="profileForm.controls['name'].errors?.['required']">Name is required.</div>
                <div *ngIf="profileForm.controls['name'].errors?.['minlength']">Name must be at least 2 characters long.</div>
                <div *ngIf="profileForm.controls['name'].errors?.['maxlength']">Name must be at most 20 characters long.</div>
              </div>
            </div>
          </div>

          <div class="col-md-6 mb-3">
            <div class="form-group">            
              <label for="surname" class="form-label">Surname</label>
              <input type="text" class="form-control" id="surname" formControlName="surname" [readonly]="!isEditMode" [ngClass]="{'disabled-input': !isEditMode}">
              <div *ngIf="profileForm.controls['surname'].invalid && (profileForm.controls['surname'].dirty || profileForm.controls['surname'].touched)" class="alert">
                <div *ngIf="profileForm.controls['surname'].errors?.['required']">Surname is required.</div>
                <div *ngIf="profileForm.controls['surname'].errors?.['minlength']">Surname must be at least 2 characters long.</div>
                <div *ngIf="profileForm.controls['surname'].errors?.['maxlength']">Surname must be at most 20 characters long.</div>
              </div>
            </div>
          </div>

          <div class="col-md-6 mb-3">
            <div class="form-group">
              <label for="email" class="form-label">Email Address</label>
              <input type="email" class="form-control" id="email" formControlName="email" [readonly]="!isEditMode" [ngClass]="{'disabled-input': !isEditMode}">
              <div *ngIf="profileForm.controls['email'].invalid && (profileForm.controls['email'].dirty || profileForm.controls['email'].touched)" class="alert">
                <div *ngIf="profileForm.controls['email'].errors?.['required']">Email is required.</div>
                <div *ngIf="profileForm.controls['email'].errors?.['email']">Email is invalid.</div>
              </div>
            </div>
          </div>

          <div class="col-md-6 mb-3">
            <div class="form-group">
              <label for="phoneNumber" class="form-label">Phone Number</label>
              <input type="text" class="form-control" id="phoneNumber" formControlName="phoneNumber" [readonly]="!isEditMode" [ngClass]="{'disabled-input': !isEditMode}">
              <div *ngIf="profileForm.controls['phoneNumber'].invalid && (profileForm.controls['phoneNumber'].dirty || profileForm.controls['phoneNumber'].touched)" class="alert">
                <div *ngIf="profileForm.controls['phoneNumber'].errors?.['required']">Phone Number is required.</div>
                <div *ngIf="profileForm.controls['phoneNumber'].errors?.['minlength']">Phone Number must be a valid 10-digit number.</div>
                <div *ngIf="profileForm.controls['phoneNumber'].errors?.['maxlength']">Phone Number must be a valid 10-digit number.</div>
              </div>
            </div>
          </div>

          <div class="col-md-6 mb-3">
            <div class="form-group">
              <label for="physical_Address" class="form-label">Physical Address</label>
              <input type="text" class="form-control" id="physical_Address" formControlName="physical_Address" [readonly]="!isEditMode" [ngClass]="{'disabled-input': !isEditMode}">
              <div *ngIf="profileForm.controls['physical_Address'].invalid && (profileForm.controls['physical_Address'].dirty || profileForm.controls['physical_Address'].touched)" class="alert">
                <div *ngIf="profileForm.controls['physical_Address'].errors?.['required']">Physical address is required.</div>
                <div *ngIf="profileForm.controls['physical_Address'].errors?.['minlength']">Physical Address must be at least 7 characters long.</div>
                <div *ngIf="profileForm.controls['physical_Address'].errors?.['maxlength']">Physical Address must be at most 100 characters long.</div>
              </div>
            </div>
          </div>
        </div>

        <div class="d-flex justify-content-end">
          <button type="button" class="btn btn-primary me-2" (click)="openSaveModal()" [disabled]="!isEditMode">Save</button>
          <button type="button" class="btn btn-info" (click)="changePassword()" [disabled]="!isEditMode">Change Password</button>
        </div>
      </form>
    </div>
  </div>
</div>

<!-- Save Confirmation Modal -->
<div class="modal fade" id="saveConfirmationModal" tabindex="-1" role="dialog" aria-labelledby="saveConfirmationModalTitle" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="saveConfirmationModalTitle">Save Changes</h5>
      </div>
      <div class="modal-body">
        Are you sure you want to update your profile details?
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" (click)="dismissModal()">Cancel</button>
        <button type="button" class="btn btn-primary" (click)="confirmSave()">Confirm</button>
      </div>
    </div>
  </div>
</div>

<!-- Error Modal -->
<div class="modal fade" id="errorModal" tabindex="-1" role="dialog" aria-labelledby="errorModalTitle" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="errorModalTitle">Error</h5>
      </div>
      <div class="modal-body">
        Please enter a valid input for the following fields:
        <ul id="errorList"></ul>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-primary" (click)="dismissErrorModal()">OK</button>
      </div>
    </div>
  </div>
</div>

<!-- Redeem Reward Modal -->
<div class="modal fade" id="redeemRewardModal" tabindex="-1" role="dialog" aria-labelledby="redeemRewardModalTitle" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="redeemRewardModalTitle">Redeem Reward</h5>
      </div>
      <div class="modal-body">
        Are you sure you want to redeem the reward <strong>{{ selectedReward?.rewardTypeName }}</strong>?
        <br>
        <p>The reward criteria met: <strong>{{ selectedReward?.rewardCriteria }}</strong></p>
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" (click)="dismissRedeemModal()">No</button>
        <button type="button" class="btn btn-primary" (click)="confirmRedeem()">Yes</button>
      </div>
    </div>
  </div>
</div>

<!-- Success Modal -->
<div class="modal fade" id="successModal" tabindex="-1" role="dialog" aria-labelledby="successModalTitle" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered" role="document">
    <div class="modal-content">
      <div class="modal-header">
        <strong><h5 class="modal-title" id="successModalTitle">Congratulations</h5></strong>
      </div>
      <div class="modal-body">
        <strong>Congratulations!</strong> You've successfully redeemed this reward <strong>{{ selectedReward?.rewardTypeName }}</strong>. Please contact the gym and provide this code <strong>{{ verificationCode }}</strong> for further instructions.
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" (click)="dismissSuccessModal()">Close</button>
      </div>
    </div>
  </div>
</div>


<!-- help-modal.component.html -->
<div class="modal fade" id="helpModal" tabindex="-1" aria-labelledby="helpModalLabel" aria-hidden="true">
  <div class="modal-dialog modal-dialog-scrollable">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
        <h5 class="modal-title mx-auto" id="helpModalLabel">Help Guide</h5>
        <div class="search-bar-container">
          <input type="text" class="form-control search-bar" placeholder="Search help" [(ngModel)]="searchTerm" (input)="filterHelpContent()">
        </div>
      </div>
      <div class="modal-body">
        <div *ngFor="let item of filteredContent">
          <h5>{{ item.title }}</h5>
          <p [innerHTML]="item.content"></p>
        </div>
      </div>
    </div>
  </div>
</div>

//ts
import { Component, OnDestroy, OnInit } from '@angular/core';
import { FormGroup, Validators, FormBuilder, FormsModule } from '@angular/forms';
import { UserService } from '../Services/userprofile.service';
import { Router, RouterLink } from '@angular/router';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';
import { Member, updateUser } from '../shared/update-user';
import { Subscription, catchError } from 'rxjs';
import { RewardRedeemViewModel, UnredeemedRewardModel } from '../shared/reward';
import { RewardService } from '../Services/reward.service';

declare var $: any; // Import jQuery

@Component({
  selector: 'app-profile-page',
  standalone: true,
  imports: [CommonModule, ReactiveFormsModule, RouterLink, FormsModule],
  templateUrl: './profile-page.component.html',
  styleUrls: ['./profile-page.component.css']
})
export class ProfilePageComponent implements OnInit, OnDestroy {
  profileForm: FormGroup;
  user: updateUser | undefined;
  member: Member | undefined;
  isEditMode = false;
  errorMessage = '';  
  userProfileImage: string | null = null;
  photoFile: File | null = null;
  unredeemedRewards: UnredeemedRewardModel[] = [];
  selectedReward: UnredeemedRewardModel | null = null;
  verificationCode: string | null = null;
  userTypeID: number | null = null;
  helpContent: any[] = [];
  filteredContent: any[] = [];
  searchTerm: string = '';

  private userSubscription: Subscription | undefined;
  private memberSubscription: Subscription | undefined;
  private redeemSubscription: Subscription | undefined;
  
  constructor(
    private userService: UserService,
    private rewardService: RewardService,
    private router: Router,
    private fb: FormBuilder
  ) {
    this.profileForm = this.fb.group({
      email: ['', [Validators.required, Validators.email]],
      name: ['', [Validators.required, Validators.minLength(2), Validators.maxLength(20)]],
      surname: ['', [Validators.required, Validators.minLength(2), Validators.maxLength(20)]],
      phoneNumber: ['', [Validators.required, Validators.minLength(10), Validators.maxLength(10)]],
      physical_Address: ['', [Validators.required, Validators.minLength(7), Validators.maxLength(100)]],
      photo: ['']
    });
  }

  ngOnInit(): void {
    const userTypeId = JSON.parse(localStorage.getItem('User') || '{}').userTypeId;
    this.userTypeID = userTypeId;
    console.log('User Type ID',userTypeId);
    const userId = JSON.parse(localStorage.getItem('User') || '{}').userId;
    console.log('User ID from local storage:', userId);
    this.loadUserProfile(userId);
    this.isEditMode = false;    


    // Initialize help content
    this.helpContent = [
      {
        title: 'Profile Page Context-Sensitive Help',
        content: `
          <p><strong>Overview:</strong> The Profile Page allows users to view and update their personal information. This includes details such as username, email, and profile picture.</p>
          <p><strong>Elements and Features:</strong></p>`
      },
      {
        title: '1. Back Button',
        content: `
          <ul>
            <li><strong>Description:</strong> An arrow icon located in the header that allows you to return to the previous page.</li>
            <li><strong>Functionality:</strong> Clicking the back button navigates to the previous page you visited.</li>
            <li><strong>Helpful Tips:</strong>
              <ul>
                <li>Use the back button if you want to return to your previous page without losing your current context.</li>
              </ul>
            </li>
          </ul>`
      },
      {
        title: '2. Header Title',
        content: `
          <ul>
            <li><strong>Description:</strong> Displays the title "Profile" to indicate the purpose of the screen.</li>
            <li><strong>Functionality:</strong> Provides a clear indication of the current screen's functionality.</li>
          </ul>`
      },
      {
        title: '3. Profile Information',
        content: `
          <ul>
            <li><strong>Description:</strong> Displays your personal information such as username, email, and profile picture.</li>
            <li><strong>Functionality:</strong> Allows you to view and edit your personal details.</li>
          </ul>`
      },
      {
        title: '4. Change Password Button',
        content: `
          <ul>
            <li><strong>Description:</strong> A button that navigates you to the Change Password screen.</li>
            <li><strong>Functionality:</strong> Allows you to update your password securely.</li>
          </ul>`
      },
      {
        title: 'Technical Details:',
        content: `
          <ul>
            <li>Dynamic Data: The profile information is dynamically updated based on the data retrieved from the backend.</li>
            <li>Navigation: Utilizes Angular's Router for smooth transitions between different sections of the application.</li>
          </ul>`
      },
      {
        title: 'Common Questions:',
        content: `
          <p><strong>Q:</strong> How do I update my profile information?</p>
          <p><strong>A:</strong> Click on the edit button next to the information you want to update, make your changes, and click save.</p>
          <p><strong>Q:</strong> How do I change my password?</p>
          <p><strong>A:</strong> Click the "Change Password" button to navigate to the Change Password screen.</p>
          <p><strong>Q:</strong> What should I do if I encounter an error?</p>
          <p><strong>A:</strong> Refresh the page or contact support for assistance.</p>`
      },
      {
        title: 'Troubleshooting:',
        content: `
          <p><strong>Problem:</strong> The profile information is not loading.</p>
          <p><strong>Solution:</strong> Ensure you are connected to the internet and logged in. If the problem persists, try refreshing the page or contact technical support.</p>
          <p><strong>Problem:</strong> Unable to update profile information.</p>
          <p><strong>Solution:</strong> Check your internet connection and ensure all required fields are filled out correctly. If the issue continues, contact support.</p>`
      }
    ];

    // Initialize filtered content
    this.filteredContent = [...this.helpContent];
  }

  filterHelpContent(): void {
    const term = this.searchTerm.toLowerCase();
    this.filteredContent = this.helpContent.filter(item =>
      item.title.toLowerCase().includes(term) || item.content.toLowerCase().includes(term)
    );
  }

  ngOnDestroy(): void {
    // Clean up subscriptions
    if (this.userSubscription) {
      this.userSubscription.unsubscribe();
    }
    if (this.memberSubscription) {
      this.memberSubscription.unsubscribe();
    }
    if (this.redeemSubscription) {
      this.redeemSubscription.unsubscribe();
    }
  }

  loadUserProfile(userId: number): void {
    this.userSubscription = this.userService.getUserById(userId).pipe(
      catchError(error => {
        console.error('Error fetching user profile:', error);
        return [];
      })
    ).subscribe({
      next: (result) => {
        console.log('User data received:', result);
        this.user = result; 

        // Patch non-file form values
        this.profileForm.patchValue({
          email: this.user.email,
          name: this.user.name,
          surname: this.user.surname,
          phoneNumber: this.user.phoneNumber,
          physical_Address: this.user.physical_Address,
        });

        // Log photo to debug
        console.log('Photo:', this.user.photo);        
        // Set user profile image
        this.userProfileImage = `data:image/jpeg;base64,${this.user.photo}`;
        console.log('User:', this.user);

        const userTypeId = JSON.parse(localStorage.getItem('User') || '{}').userTypeId;
        this.userTypeID = userTypeId;
        if (this.userTypeID === 3) {
          this.loadMemberProfile(userId);
        }
      },
      complete: () => {
        console.log('getUserById subscription completed');
      }
    });
  }

  loadMemberProfile(userId: number): void {
    this.memberSubscription = this.userService.getMemberByUserId(userId).pipe(
      catchError(error => {
        console.error('Error fetching member profile:', error);
        return [];
      })
    ).subscribe({
      next: (result) => {
        this.member = result;
        if (this.member) {
          console.log('Member data received:', this.member); // Detailed debug statement
          console.log('Member ID:', this.member.member_ID); // Debug statement
          this.loadUnredeemedRewards(this.member.member_ID);
        }
      },
      complete: () => {
        console.log('getMemberByUserId subscription completed');
      }
    });
  }

  clearForm() {
    this.profileForm.reset();
  }

  enableEditMode(event: Event) {
    event.preventDefault();
    this.isEditMode = true;
    this.profileForm.enable();
  }

  openSaveModal() {
    if (this.profileForm.invalid) {
      this.showValidationErrors();
      $('#errorModal').modal('show');
      return;
    }
    $('#saveConfirmationModal').modal('show');
  }

  showValidationErrors() {
    const invalidFields: string[] = [];
    Object.keys(this.profileForm.controls).forEach(key => {
      const controlErrors = this.profileForm.get(key)?.errors;
      if (controlErrors) {
        Object.keys(controlErrors).forEach(errorKey => {
          invalidFields.push(`${key}: ${errorKey}`);
        });
      }
    });
    this.errorMessage = `Please enter a valid input: ${invalidFields.join(', ')}`;
  }

  dismissModal() {
    $('#saveConfirmationModal').modal('hide');
  }

  dismissErrorModal() {
    $('#errorModal').modal('hide');
  }

  confirmSave() {
    this.dismissModal();
    this.onSubmit();
    this.isEditMode = false; // Disable edit mode after confirmation
  }

  onSubmit() {
    if (this.profileForm.valid) {
        const userId = JSON.parse(localStorage.getItem('User')!).userId;
        const formValue = this.profileForm.value;

        // If no new photo is selected, use the existing photo
        let photoFile: File | null = this.photoFile;
        if (!photoFile && this.user?.photo) {
          // Ensure the Base64 string is valid
          const base64Prefix = 'data:image/jpeg;base64,';
          let base64String = this.user.photo;
          if (base64String.startsWith(base64Prefix)) {
            base64String = base64String.replace(base64Prefix, '');
          }
          try {
            const byteString = atob(base64String);
            const arrayBuffer = new ArrayBuffer(byteString.length);
            const intArray = new Uint8Array(arrayBuffer);
            for (let i = 0; i < byteString.length; i++) {
              intArray[i] = byteString.charCodeAt(i);
            }
            const blob = new Blob([intArray], { type: 'image/jpeg' });
            photoFile = new File([blob], 'photo.jpg', { type: 'image/jpeg' });
          } catch (e) {
            console.error('Invalid Base64 string:', e);
          }
        }

        // Create the user object
        const user: updateUser = {
            name: formValue.name,
            surname: formValue.surname,
            email: formValue.email,
            physical_Address: formValue.physical_Address,
            phoneNumber: formValue.phoneNumber,
            photo: this.user?.photo ?? '', // Ensure photo is included even if it's not updated
            user_Type_ID: this.user?.user_Type_ID ?? 0
        };

        this.userService.updateUser(userId, user, photoFile).subscribe({
            next: (result) => {
                console.log('User updated successfully:', result);
                this.router.navigateByUrl(`/ProfilePage/${userId}`);
                alert('Successfully updated profile');
            },
            error: (error) => {
                console.error('Error updating user profile:', error);
                alert('Error updating profile.');
            }
        });
    } else {
        console.warn('Form is invalid:', this.profileForm.errors);
    }
  }

  onPhotoChange(event: Event): void {
    if (!this.isEditMode) return;

    const input = event.target as HTMLInputElement;
    if (input.files && input.files[0]) {
        const file = input.files[0];
        
        // Ensure file is an image
        if (!file.type.startsWith('image/')) {
            console.error('Selected file is not an image.');
            alert('Please select a valid image file.');
            return;
        }

        const reader = new FileReader();

        reader.onload = (e: any) => {
          if (e.target && e.target.result) {
              this.userProfileImage = e.target.result; // Update the image source for preview
              this.photoFile = file; // Set the file for form submission
              console.log('Base64 string of the image:', this.userProfileImage);
          }
      };

        reader.onerror = (e) => {
            console.error('Error reading file:', e);
            alert('There was an error reading the file. Please try again.');
        };

        reader.onabort = (e) => {
            console.warn('File read aborted:', e);
            alert('File read was aborted. Please try again.');
        };

        reader.onloadend = () => {
            console.log('File read completed.');
        };

        try {
            reader.readAsDataURL(file);
            this.photoFile = file; 
        } catch (error) {
            console.error('An error occurred while reading the file:', error);
            alert('An error occurred while reading the file. Please try again.');
        }
    } else {
        console.error('No file selected or input element is invalid.');
    }
  }


  goBack() {
    const userTypeId = JSON.parse(localStorage.getItem('User')!).userTypeId;
    const userId = JSON.parse(localStorage.getItem('User')!).userId;
    if (userTypeId === 1) {  // Ensure userTypeID is compared as string
      this.router.navigateByUrl(`/OwnerHome/${userId}`);
    } else if (userTypeId === 2) {
      this.router.navigateByUrl(`/EmployeeHome/${userId}`);
    } else if (userTypeId === 3) {
      this.router.navigateByUrl(`/Home/${userId}`);
    }
  }

  changePassword() {
    this.router.navigateByUrl('/ChangePasswordPage');
  }

  // Method to load rewards for the current user
  loadUnredeemedRewards(memberId: number): void {
    console.log('Loading unredeemed rewards for member ID:', memberId); 
    this.rewardService.getUnredeemedRewardsForMember(memberId).subscribe({
      next: rewards => {
        this.unredeemedRewards = rewards;
        console.log("reward", rewards)
      },
      error: error => {
        console.error('Error fetching unredeemed rewards:', error);
      },
      complete: () => {
        console.log('Fetching unredeemed rewards completed.');
      }
    });
  }

  // Method to open redeem modal for a reward
  openRedeemModal(reward: UnredeemedRewardModel): void {
    this.selectedReward = reward;
    $('#redeemRewardModal').modal('show');
  }

  // Method to dismiss redeem modal
  dismissRedeemModal(): void {
    $('#redeemRewardModal').modal('hide');
  }

  // Method to confirm redeeming a reward
  confirmRedeem(): void {
    if (!this.selectedReward) {
      return;
    }
    const redeemRequest = new RewardRedeemViewModel();
    redeemRequest.MemberId = this.member?.member_ID ?? 0;
    redeemRequest.RewardId = this.selectedReward.reward_ID;

    // Call backend service to redeem the reward
    this.redeemSubscription = this.rewardService.redeemReward(redeemRequest).subscribe({
      next: () => {
        // Show success modal on successful redemption
        this.verificationCode = this.generateSixDigitCode(); // Generate code when opening modal
        console.log('Generated verification code:', this.verificationCode); 
        $('#successModal').modal('show');
        // Remove redeemed reward from the list
        this.unredeemedRewards = this.unredeemedRewards.filter(r => r.reward_ID !== this.selectedReward?.reward_ID);
      },
      error: (error) => {
        console.error('Error redeeming reward:', error);
        // Handle error
      }
    });
    this.dismissRedeemModal();
  }

  // Method to dismiss success modal
  dismissSuccessModal(): void {
    $('#successModal').modal('hide');
  }

  generateSixDigitCode(): string {
    const code = Math.floor(100000 + Math.random() * 900000).toString();
    return `${code.slice(0, 3)}-${code.slice(3)}`;
  }
}
content_copyCOPY