Add prepaid resource credits with prorated deploy billing.
When users delete an app before plan expiry, remaining resources become credits for a new deploy. The deploy calculator shows covered vs additional charges, prices optional services correctly, and prorates extras to days left on the credit. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -566,9 +566,14 @@ export default function AppDetailPage() {
|
||||
|
||||
const deleteMutation = useMutation({
|
||||
mutationFn: () => api.delete(`/applications/${appId}`),
|
||||
onSuccess: () => {
|
||||
onSuccess: (res) => {
|
||||
queryClient.invalidateQueries({ queryKey: ['applications'] });
|
||||
toast.success('Application deleted');
|
||||
queryClient.invalidateQueries({ queryKey: ['resource-credits'] });
|
||||
if (res.data?.resourceCredit) {
|
||||
toast.success('Application deleted. Prepaid resources are on your dashboard.');
|
||||
} else {
|
||||
toast.success('Application deleted');
|
||||
}
|
||||
router.push('/dashboard/apps');
|
||||
},
|
||||
onError: () => toast.error('Failed to delete application'),
|
||||
@@ -862,7 +867,11 @@ export default function AppDetailPage() {
|
||||
const handleDelete = async () => {
|
||||
const ok = await confirm({
|
||||
title: `Delete "${app.name}"?`,
|
||||
message: 'This will permanently remove:\n• All Kubernetes resources (pods, services, ingress)\n• Database and volumes\n• All deployment records\n• Uploaded source code',
|
||||
message:
|
||||
'This will permanently remove all Kubernetes resources, data, and deployment records.\n\n' +
|
||||
(app.planExpiresAt && new Date(app.planExpiresAt) > new Date()
|
||||
? 'Your remaining paid resources will appear on the dashboard for use on a new app at no extra charge.'
|
||||
: ''),
|
||||
confirmText: 'Delete',
|
||||
variant: 'danger',
|
||||
});
|
||||
@@ -937,11 +946,12 @@ export default function AppDetailPage() {
|
||||
</>
|
||||
)}
|
||||
<button onClick={handleDelete} disabled={deleteMutation.isPending} className="btn-danger text-sm disabled:opacity-50">
|
||||
{deleteMutation.isPending ? <><Clock className="w-3 h-3 inline animate-spin" /></> : 'Delete'}
|
||||
{deleteMutation.isPending ? <><Clock className="w-3 h-3 inline animate-spin" /></> : 'Delete'}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{/* Renewal Banner for Expired/Suspended Apps */}
|
||||
{needsRenewal && (
|
||||
<div className={`rounded-xl p-4 border-2 ${
|
||||
|
||||
Reference in New Issue
Block a user