update for shrink image size.
ci-cd-vm / ci-cd (push) Successful in 1m23s

This commit is contained in:
Chris Chen
2026-06-23 13:30:20 -07:00
parent 62592c29ae
commit 5dfca873dd
5 changed files with 68 additions and 16 deletions
@@ -1,7 +1,8 @@
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Observable, from, switchMap } from 'rxjs';
import { ApiConfigService } from '../../../core/services/api-config.service';
import { ImageUtils } from '../../../shared/utilities/image-utils';
import {
PagedResult, ExpenseListItemDto, ExpenseDto, CreateExpenseRequest, UpdateExpenseRequest,
RejectExpenseRequest, PayExpenseRequest,
@@ -39,8 +40,15 @@ export class ExpenseApiService {
reject(id: number, r: RejectExpenseRequest): Observable<void> { return this.http.post<void>(`${this.endpoint}/${id}/reject`, r); }
pay(id: number, r: PayExpenseRequest): Observable<void> { return this.http.post<void>(`${this.endpoint}/${id}/pay`, r); }
uploadReceipt(id: number, file: File): Observable<void> {
const form = new FormData(); form.append('file', file);
return this.http.post<void>(`${this.endpoint}/${id}/receipt`, form);
// Resize/re-encode phone photos client-side first — a raw 12MP camera JPEG
// is several MB and would 413 on mobile. PDFs pass through untouched.
return from(ImageUtils.compressForUpload(file)).pipe(
switchMap(prepared => {
const form = new FormData();
form.append('file', prepared);
return this.http.post<void>(`${this.endpoint}/${id}/receipt`, form);
}),
);
}
/**
* Fetches the receipt as a Blob via HttpClient so the auth interceptor attaches
@@ -1,5 +1,5 @@
import imageCompression from 'browser-image-compression';
import { PDFDocument } from 'pdf-lib';
import { ImageUtils } from '../../../shared/utilities/image-utils';
/**
* Builds a single merged PDF from a list of paper-proof attachments (mostly phone photos).
@@ -12,11 +12,6 @@ import { PDFDocument } from 'pdf-lib';
* All work happens client-side; the resulting Blob is uploaded as the session's proof.pdf.
*/
// Tunables — adjust if proofs look too soft (raise) or files are too large (lower).
const MAX_EDGE_PX = 2000; // longest image edge after compression
const JPEG_QUALITY = 0.72; // 0..1
const MAX_SIZE_MB = 1; // target ceiling per image
// US Letter, in PDF points (72pt = 1in).
const PAGE_W = 612;
const PAGE_H = 792;
@@ -42,13 +37,7 @@ export async function buildProofPdf(files: File[]): Promise<ProofBuildResult> {
}
if (file.type.startsWith('image/')) {
const compressed = await imageCompression(file, {
maxWidthOrHeight: MAX_EDGE_PX,
maxSizeMB: MAX_SIZE_MB,
initialQuality: JPEG_QUALITY,
fileType: 'image/jpeg',
useWebWorker: true,
});
const compressed = await ImageUtils.compressForUpload(file);
const jpgBytes = new Uint8Array(await compressed.arrayBuffer());
const img = await doc.embedJpg(jpgBytes);