refactor: extract shared utility functions to eliminate duplication
This commit is contained in:
parent
b720013a08
commit
1037ff164d
10 changed files with 85 additions and 110 deletions
37
frontend/src/utils/format.ts
Normal file
37
frontend/src/utils/format.ts
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* Shared formatting utility functions.
|
||||
*
|
||||
* Consolidates duplicated formatters that were previously defined inline in
|
||||
* PropertyCard, ListingDetail, MobileBottomSheet, and StatsBar.
|
||||
*/
|
||||
|
||||
/** Format a number as a compact GBP string, e.g. "£1.2k" or "£950". */
|
||||
export function formatCurrency(value: number): string {
|
||||
if (value >= 1000) return `£${(value / 1000).toFixed(1)}k`;
|
||||
return `£${Math.round(value)}`;
|
||||
}
|
||||
|
||||
/** Format a duration in seconds as a human-readable string, e.g. "12m" or "1h30m". */
|
||||
export function formatDuration(seconds: number): string {
|
||||
const minutes = Math.round(seconds / 60);
|
||||
if (minutes < 60) return `${minutes}m`;
|
||||
const hours = Math.floor(minutes / 60);
|
||||
const mins = minutes % 60;
|
||||
return mins > 0 ? `${hours}h${mins}m` : `${hours}h`;
|
||||
}
|
||||
|
||||
/** Format an ISO date string as a localised short date (e.g. "3 Jan 2025"). */
|
||||
export function formatDate(value: string): string {
|
||||
const date = new Date(value);
|
||||
if (isNaN(date.getTime())) return value;
|
||||
return date.toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' });
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the price per square metre as a formatted string, e.g. "£4,500/m²".
|
||||
* Returns null when square metres data is unavailable.
|
||||
*/
|
||||
export function formatPricePerSqm(price: number, sqm: number | null | undefined): string | null {
|
||||
if (sqm == null || sqm <= 0) return null;
|
||||
return `£${Math.round(price / sqm).toLocaleString()}/m²`;
|
||||
}
|
||||
40
frontend/src/utils/taskUtils.ts
Normal file
40
frontend/src/utils/taskUtils.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Shared task-related utility functions.
|
||||
*
|
||||
* Consolidates helpers that were duplicated across App.tsx, TaskIndicator.tsx,
|
||||
* TaskProgressDrawer.tsx, and useTaskProgress.ts.
|
||||
*/
|
||||
|
||||
import type { TaskState, TaskResult } from '@/types';
|
||||
|
||||
/** Returns true when the status represents a terminal (finished) task state. */
|
||||
export function isTerminalStatus(status: string): boolean {
|
||||
return status === 'SUCCESS' || status === 'FAILURE' || status === 'REVOKED';
|
||||
}
|
||||
|
||||
/** Convert a TaskState into a TaskResult (for the drawer). */
|
||||
export function taskStateToResult(ts: TaskState): TaskResult {
|
||||
return {
|
||||
progress: ts.progress ?? 0,
|
||||
processed: ts.processed,
|
||||
total: ts.total,
|
||||
phase: ts.phase,
|
||||
message: ts.message,
|
||||
subqueries_probed: ts.subqueries_probed,
|
||||
subqueries_initial: ts.subqueries_initial,
|
||||
estimated_results: ts.estimated_results,
|
||||
subqueries_total: ts.subqueries_total,
|
||||
subqueries_completed: ts.subqueries_completed,
|
||||
ids_collected: ts.ids_collected,
|
||||
pages_fetched: ts.pages_fetched,
|
||||
fetching_done: ts.fetching_done,
|
||||
details_fetched: ts.details_fetched,
|
||||
images_downloaded: ts.images_downloaded,
|
||||
ocr_completed: ts.ocr_completed,
|
||||
failed: ts.failed,
|
||||
elapsed_seconds: ts.elapsed_seconds,
|
||||
rate_per_second: ts.rate_per_second,
|
||||
eta_seconds: ts.eta_seconds,
|
||||
logs: ts.logs,
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue