82 lines
2.8 KiB
TypeScript
82 lines
2.8 KiB
TypeScript
import { useState } from "react";
|
|
import { apiPatch } from "../api/http";
|
|
import { formatDateInTimezone } from "../utils/timezone";
|
|
|
|
interface EarlyFundingModalProps {
|
|
planId: string;
|
|
planName: string;
|
|
nextDueDate?: string;
|
|
timezone: string;
|
|
onClose: () => void;
|
|
}
|
|
|
|
export default function EarlyFundingModal({ planId, planName, nextDueDate, timezone, onClose }: EarlyFundingModalProps) {
|
|
const [loading, setLoading] = useState(false);
|
|
|
|
const handleResponse = async (enableEarlyFunding: boolean) => {
|
|
setLoading(true);
|
|
try {
|
|
await apiPatch(`/fixed-plans/${planId}/early-funding`, { enableEarlyFunding });
|
|
onClose();
|
|
} catch (error) {
|
|
console.error("Failed to update early funding:", error);
|
|
// Still close the modal even if it fails
|
|
onClose();
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
const nextDueLabel = nextDueDate
|
|
? formatDateInTimezone(nextDueDate, timezone, {
|
|
month: 'long',
|
|
day: 'numeric',
|
|
year: 'numeric'
|
|
})
|
|
: "next billing cycle";
|
|
|
|
return (
|
|
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
|
|
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-md w-full p-6 space-y-4">
|
|
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">
|
|
Start Funding Early?
|
|
</h2>
|
|
|
|
<p className="text-gray-700 dark:text-gray-300">
|
|
You've paid <strong>{planName}</strong> which is due on <strong>{nextDueLabel}</strong>.
|
|
</p>
|
|
|
|
<p className="text-gray-700 dark:text-gray-300">
|
|
Would you like to start funding for the next payment now, or wait until closer to the due date?
|
|
</p>
|
|
|
|
<div className="flex flex-col sm:flex-row gap-3 pt-4">
|
|
<button
|
|
onClick={() => handleResponse(true)}
|
|
disabled={loading}
|
|
className="flex-1 px-4 py-2 bg-blue-600 hover:bg-blue-700 disabled:bg-blue-400
|
|
text-white font-medium rounded-md transition-colors"
|
|
>
|
|
{loading ? "Starting..." : "Yes, Start Now"}
|
|
</button>
|
|
|
|
<button
|
|
onClick={() => handleResponse(false)}
|
|
disabled={loading}
|
|
className="flex-1 px-4 py-2 bg-gray-200 hover:bg-gray-300 dark:bg-gray-700
|
|
dark:hover:bg-gray-600 disabled:bg-gray-100 text-gray-900 dark:text-white
|
|
font-medium rounded-md transition-colors"
|
|
>
|
|
Wait Until Rollover
|
|
</button>
|
|
</div>
|
|
|
|
<p className="text-sm text-gray-500 dark:text-gray-400 pt-2">
|
|
<strong>Start Now:</strong> Your next income will begin funding this bill.<br/>
|
|
<strong>Wait:</strong> Funding will resume automatically on {nextDueLabel}.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|