feat(claimFilesMetadata) - Added feature for having claims uploaded files metadata
This commit is contained in:
@@ -48,6 +48,11 @@ import {
|
||||
} from "@/utils/procedureCombosMapping";
|
||||
import { COMBO_CATEGORIES, PROCEDURE_COMBOS } from "@/utils/procedureCombos";
|
||||
|
||||
interface ClaimFileMeta {
|
||||
filename: string;
|
||||
mimeType: string;
|
||||
}
|
||||
|
||||
interface ClaimFormData {
|
||||
patientId: number;
|
||||
appointmentId: number;
|
||||
@@ -63,6 +68,7 @@ interface ClaimFormData {
|
||||
status: string; // default "pending"
|
||||
serviceLines: InputServiceLine[];
|
||||
claimId?: number;
|
||||
claimFiles?: ClaimFileMeta[];
|
||||
}
|
||||
|
||||
interface ClaimFormProps {
|
||||
@@ -341,6 +347,13 @@ export function ClaimForm({
|
||||
(line) => line.procedureCode.trim() !== ""
|
||||
);
|
||||
const { uploadedFiles, insuranceSiteKey, ...formToCreateClaim } = form;
|
||||
|
||||
// build claimFiles metadata from uploadedFiles (only filename + mimeType)
|
||||
const claimFilesMeta: ClaimFileMeta[] = (uploadedFiles || []).map((f) => ({
|
||||
filename: f.name,
|
||||
mimeType: f.type,
|
||||
}));
|
||||
|
||||
const createdClaim = await onSubmit({
|
||||
...formToCreateClaim,
|
||||
serviceLines: filteredServiceLines,
|
||||
@@ -348,6 +361,7 @@ export function ClaimForm({
|
||||
patientId: patientId,
|
||||
insuranceProvider: "MassHealth",
|
||||
appointmentId: appointmentId!,
|
||||
claimFiles: claimFilesMeta,
|
||||
});
|
||||
|
||||
// 4. sending form data to selenium service
|
||||
@@ -415,6 +429,13 @@ export function ClaimForm({
|
||||
(line) => line.procedureCode.trim() !== ""
|
||||
);
|
||||
const { uploadedFiles, insuranceSiteKey, ...formToCreateClaim } = form;
|
||||
|
||||
// build claimFiles metadata from uploadedFiles (only filename + mimeType)
|
||||
const claimFilesMeta: ClaimFileMeta[] = (uploadedFiles || []).map((f) => ({
|
||||
filename: f.name,
|
||||
mimeType: f.type,
|
||||
}));
|
||||
|
||||
const createdClaim = await onSubmit({
|
||||
...formToCreateClaim,
|
||||
serviceLines: filteredServiceLines,
|
||||
@@ -422,6 +443,7 @@ export function ClaimForm({
|
||||
patientId: patientId,
|
||||
insuranceProvider: "MassHealth",
|
||||
appointmentId: appointmentId!,
|
||||
claimFiles: claimFilesMeta,
|
||||
});
|
||||
|
||||
// 4. Close form
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
import { Button } from "@/components/ui/button";
|
||||
import React from "react";
|
||||
import { formatDateToHumanReadable } from "@/utils/dateUtils";
|
||||
import { ClaimWithServiceLines } from "@repo/db/types";
|
||||
import { ClaimFileMeta, ClaimWithServiceLines } from "@repo/db/types";
|
||||
import { FileText, Paperclip } from "lucide-react";
|
||||
|
||||
type ClaimViewModalProps = {
|
||||
isOpen: boolean;
|
||||
@@ -25,6 +26,40 @@ export default function ClaimViewModal({
|
||||
claim,
|
||||
onEditClaim,
|
||||
}: ClaimViewModalProps) {
|
||||
// Normalizer: supports both ClaimFile[] and nested-create shape { create: ClaimFile[] }
|
||||
const getClaimFilesArray = (
|
||||
c: ClaimWithServiceLines | null
|
||||
): ClaimFileMeta[] => {
|
||||
if (!c) return [];
|
||||
|
||||
// If it's already a plain array (runtime from Prisma include), return it
|
||||
const maybeFiles = (c as any).claimFiles;
|
||||
if (!maybeFiles) return [];
|
||||
|
||||
if (Array.isArray(maybeFiles)) {
|
||||
// ensure each item has filename field (best-effort)
|
||||
return maybeFiles.map((f: any) => ({
|
||||
id: f?.id,
|
||||
filename: String(f?.filename ?? ""),
|
||||
mimeType: f?.mimeType ?? f?.mime ?? null,
|
||||
}));
|
||||
}
|
||||
|
||||
// Nested-create shape: { create: [...] }
|
||||
if (maybeFiles && Array.isArray(maybeFiles.create)) {
|
||||
return maybeFiles.create.map((f: any) => ({
|
||||
id: f?.id,
|
||||
filename: String(f?.filename ?? ""),
|
||||
mimeType: f?.mimeType ?? f?.mime ?? null,
|
||||
}));
|
||||
}
|
||||
|
||||
// No recognized shape -> empty
|
||||
return [];
|
||||
};
|
||||
|
||||
const claimFiles = getClaimFilesArray(claim);
|
||||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-[700px] max-h-[90vh] overflow-y-auto">
|
||||
@@ -204,6 +239,37 @@ export default function ClaimViewModal({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Claim Files (metadata) */}
|
||||
<div className="pt-4">
|
||||
<h4 className="font-medium text-gray-900 flex items-center space-x-2">
|
||||
<Paperclip className="w-4 h-4 inline-block" />
|
||||
<span>Attached Files</span>
|
||||
</h4>
|
||||
|
||||
{claimFiles.length > 0 ? (
|
||||
<ul className="mt-3 space-y-2">
|
||||
{claimFiles.map((f) => (
|
||||
<li
|
||||
key={f.id ?? f.filename}
|
||||
className="flex items-center justify-between border rounded-md p-3 bg-white"
|
||||
>
|
||||
<div className="flex items-start space-x-3">
|
||||
<FileText className="w-5 h-5 text-gray-500 mt-1" />
|
||||
<div>
|
||||
<div className="font-medium">{f.filename}</div>
|
||||
<div className="text-xs text-gray-500">
|
||||
{f.mimeType || "unknown"}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
) : (
|
||||
<p className="mt-2 text-gray-500">No files attached.</p>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="flex justify-end space-x-2 pt-4">
|
||||
<Button variant="outline" onClick={() => onOpenChange(false)}>
|
||||
Close
|
||||
|
||||
Reference in New Issue
Block a user