Files
DentalManagement2025/apps/Frontend/src/components/settings/npiProviderForm.tsx
2026-01-23 09:32:51 +05:30

150 lines
4.0 KiB
TypeScript

import { useEffect, useState } from "react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@/lib/queryClient";
import { toast } from "@/hooks/use-toast";
type Props = {
onClose: () => void;
defaultValues?: {
id?: number;
npiNumber: string;
providerName: string;
};
};
export function NpiProviderForm({ onClose, defaultValues }: Props) {
const [npiNumber, setNpiNumber] = useState(
defaultValues?.npiNumber || ""
);
const [providerName, setProviderName] = useState(
defaultValues?.providerName || ""
);
const queryClient = useQueryClient();
const mutation = useMutation({
mutationFn: async () => {
const payload = {
npiNumber: npiNumber.trim(),
providerName: providerName.trim(),
};
const url = defaultValues?.id
? `/api/npiProviders/${defaultValues.id}`
: "/api/npiProviders/";
const method = defaultValues?.id ? "PUT" : "POST";
const res = await apiRequest(method, url, payload);
if (!res.ok) {
const err = await res.json().catch(() => null);
throw new Error(err?.message || "Failed to save NPI provider");
}
return res.json();
},
onSuccess: () => {
toast({
title: `NPI provider ${
defaultValues?.id ? "updated" : "created"
}.`,
});
queryClient.invalidateQueries({
queryKey: ["/api/npiProviders/"],
});
onClose();
},
onError: (error: any) => {
toast({
title: "Error",
description: error.message,
variant: "destructive",
});
},
});
useEffect(() => {
setNpiNumber(defaultValues?.npiNumber || "");
setProviderName(defaultValues?.providerName || "");
}, [defaultValues]);
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
if (!npiNumber || !providerName) {
toast({
title: "Error",
description: "All fields are required.",
variant: "destructive",
});
return;
}
mutation.mutate();
};
return (
<div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
<div className="bg-white rounded-lg p-6 w-full max-w-md shadow-lg">
<h2 className="text-lg font-bold mb-4">
{defaultValues?.id
? "Edit NPI Provider"
: "Create NPI Provider"}
</h2>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label className="block text-sm font-medium">
NPI Number
</label>
<input
type="text"
value={npiNumber}
onChange={(e) => setNpiNumber(e.target.value)}
className="mt-1 p-2 border rounded w-full"
placeholder="e.g., 1489890992"
/>
</div>
<div>
<label className="block text-sm font-medium">
Provider Name
</label>
<input
type="text"
value={providerName}
onChange={(e) => setProviderName(e.target.value)}
className="mt-1 p-2 border rounded w-full"
placeholder="e.g., Kai Gao"
/>
</div>
<div className="flex justify-end gap-2">
<button
type="button"
onClick={onClose}
className="text-gray-600 hover:underline"
>
Cancel
</button>
<button
type="submit"
disabled={mutation.isPending}
className="bg-blue-600 text-white px-4 py-2 rounded hover:bg-blue-700 disabled:opacity-50"
>
{mutation.isPending
? defaultValues?.id
? "Updating..."
: "Creating..."
: defaultValues?.id
? "Update"
: "Create"}
</button>
</div>
</form>
</div>
</div>
);
}