- Add TOTP-based MFA with setup, verify, disable, backup codes, and challenge flow - Add PII field encryption middleware with AES-256-GCM and deterministic search hashes - Add agents, inquiries, and leads domain modules with entities, events, value objects - Add web dashboard pages for inquiries and leads with detail dialogs - Add 30+ component tests (valuation, charts, listings, search, providers, UI) - Add Prisma migrations for encryption hash columns and MFA TOTP support - Fix all ESLint errors (unused imports, duplicate imports, lint auto-fixes) - Update dependencies and lock file - Clean up obsolete exploration/QA docs, add audit documentation Co-Authored-By: Paperclip <noreply@paperclip.ing>
60 lines
1.8 KiB
TypeScript
60 lines
1.8 KiB
TypeScript
import { apiClient } from './api-client';
|
|
|
|
// ─── Types ──────────────────────────────────────────────
|
|
|
|
export interface InquiryReadDto {
|
|
id: string;
|
|
listingId: string;
|
|
listingTitle: string;
|
|
userId: string;
|
|
userName: string;
|
|
userPhone: string;
|
|
message: string;
|
|
phone: string | null;
|
|
isRead: boolean;
|
|
createdAt: string;
|
|
}
|
|
|
|
export interface PaginatedResult<T> {
|
|
data: T[];
|
|
total: number;
|
|
page: number;
|
|
limit: number;
|
|
totalPages: number;
|
|
}
|
|
|
|
export interface ListInquiriesParams {
|
|
page?: number;
|
|
limit?: number;
|
|
}
|
|
|
|
// ─── API Functions ──────────────────────────────────────
|
|
|
|
export const inquiriesApi = {
|
|
/** List all inquiries for current agent */
|
|
getMyInquiries: (params: ListInquiriesParams = {}) => {
|
|
const query = new URLSearchParams();
|
|
if (params.page) query.append('page', String(params.page));
|
|
if (params.limit) query.append('limit', String(params.limit));
|
|
const qs = query.toString();
|
|
return apiClient.get<PaginatedResult<InquiryReadDto>>(
|
|
`/inquiries/agent/me${qs ? `?${qs}` : ''}`,
|
|
);
|
|
},
|
|
|
|
/** List inquiries by listing */
|
|
getByListing: (listingId: string, params: ListInquiriesParams = {}) => {
|
|
const query = new URLSearchParams();
|
|
if (params.page) query.append('page', String(params.page));
|
|
if (params.limit) query.append('limit', String(params.limit));
|
|
const qs = query.toString();
|
|
return apiClient.get<PaginatedResult<InquiryReadDto>>(
|
|
`/inquiries/listing/${listingId}${qs ? `?${qs}` : ''}`,
|
|
);
|
|
},
|
|
|
|
/** Mark an inquiry as read */
|
|
markAsRead: (id: string) =>
|
|
apiClient.patch<{ success: boolean }>(`/inquiries/${id}/read`),
|
|
};
|