Localize shared modal, overlay and deployment-progress components.

Localize the confirm modal, delete button, deleting overlays/modal, the
build-progress modal, deployment progress bar/manager and the resource
upgrade modal via a shared components dictionary. Build-phase labels now
resolve from the dictionary; deleting overlays take name/kind and build
their own localized message (callers updated).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
keyhan
2026-06-11 13:23:44 +03:30
parent f8ee1ca168
commit e99ab789ba
14 changed files with 205 additions and 86 deletions
@@ -1,6 +1,7 @@
'use client';
import { AlertTriangle, CheckCircle, Clock, CreditCard, Wallet } from 'lucide-react';
import { useT } from '@/i18n/I18nProvider';
export type UpgradeCostSummary = {
proratedAmount: number;
@@ -24,6 +25,8 @@ export function ResourceUpgradeConfirmModal({
onCancel: () => void;
onConfirm: () => void;
}) {
const t = useT();
const c = t.components;
if (!open || !upgradeCostData) return null;
const needsPay = upgradeCostData.proratedAmount > 0;
@@ -33,34 +36,32 @@ export function ResourceUpgradeConfirmModal({
return (
<div className="fixed inset-0 bg-black/50 flex items-center justify-center z-50 p-4">
<div className="bg-white rounded-2xl shadow-2xl max-w-md w-full p-6 animate-fade-in">
<h2 className="text-xl font-bold text-gray-900 mb-2">Confirm Resource Upgrade</h2>
<h2 className="text-xl font-bold text-gray-900 mb-2">{c.upgradeTitle}</h2>
<p className="text-sm text-gray-500 mb-6">
{needsPay
? 'This upgrade requires payment for the remaining billing period.'
: 'No additional cost for this change.'}
{needsPay ? c.upgradeNeedsPay : c.upgradeNoCost}
</p>
<div className="bg-gray-50 rounded-xl p-4 mb-6 space-y-3">
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Current hourly cost</span>
<span className="text-sm text-gray-600">{c.currentHourlyCost}</span>
<span className="text-sm font-medium text-gray-900">
{upgradeCostData.currentCost.hourly.toLocaleString()} Toman/hour
{c.tomanPerHour.replace('{n}', upgradeCostData.currentCost.hourly.toLocaleString('en-US'))}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">New hourly cost</span>
<span className="text-sm text-gray-600">{c.newHourlyCost}</span>
<span className="text-sm font-medium text-gray-900">
{upgradeCostData.newCost.hourly.toLocaleString()} Toman/hour
{c.tomanPerHour.replace('{n}', upgradeCostData.newCost.hourly.toLocaleString('en-US'))}
</span>
</div>
<div className="flex items-center justify-between">
<span className="text-sm text-gray-600">Remaining hours in period</span>
<span className="text-sm font-medium text-gray-900">{upgradeCostData.remainingHours} hours</span>
<span className="text-sm text-gray-600">{c.remainingHoursInPeriod}</span>
<span className="text-sm font-medium text-gray-900">{c.hoursUnit.replace('{n}', String(upgradeCostData.remainingHours))}</span>
</div>
<div className="border-t pt-3 flex items-center justify-between">
<span className="text-sm font-semibold text-gray-700">Prorated amount to pay</span>
<span className="text-sm font-semibold text-gray-700">{c.proratedAmountToPay}</span>
<span className="text-lg font-bold text-primary-600">
{upgradeCostData.proratedAmount.toLocaleString()} Toman
{c.tomanUnit.replace('{n}', upgradeCostData.proratedAmount.toLocaleString('en-US'))}
</span>
</div>
</div>
@@ -68,20 +69,21 @@ export function ResourceUpgradeConfirmModal({
<div className="bg-blue-50 rounded-xl p-4 mb-6 flex items-center justify-between">
<div className="flex items-center gap-3">
<Wallet className="w-5 h-5 text-blue-500" />
<span className="text-sm text-blue-700">Wallet Balance</span>
<span className="text-sm text-blue-700">{c.walletBalance}</span>
</div>
<span className="text-lg font-bold text-blue-900">
{walletBalance?.toLocaleString() ?? 0} Toman
{c.tomanUnit.replace('{n}', (walletBalance ?? 0).toLocaleString('en-US'))}
</span>
</div>
{walletShort && (
<div className="bg-amber-50 border border-amber-200 rounded-lg p-3 mb-4">
<p className="text-sm text-amber-700">
<AlertTriangle className="w-4 h-4 inline mr-1" />
Wallet is short by{' '}
{(upgradeCostData.proratedAmount - (walletBalance ?? 0)).toLocaleString()} Toman. You can pay the
delta by gateway on the invoice page.
<AlertTriangle className="w-4 h-4 inline mr-1 rtl:mr-0 rtl:ml-1" />
{c.walletShortBy.replace(
'{n}',
(upgradeCostData.proratedAmount - (walletBalance ?? 0)).toLocaleString('en-US'),
)}
</p>
</div>
)}
@@ -92,7 +94,7 @@ export function ResourceUpgradeConfirmModal({
onClick={onCancel}
className="flex-1 px-4 py-2.5 border border-gray-200 rounded-xl font-medium text-gray-700 hover:bg-gray-50 transition-all"
>
Cancel
{t.common.cancel}
</button>
<button
type="button"
@@ -102,15 +104,15 @@ export function ResourceUpgradeConfirmModal({
>
{isPending ? (
<>
<Clock className="w-4 h-4 animate-spin" /> Applying
<Clock className="w-4 h-4 animate-spin" /> {c.applying}
</>
) : needsPay ? (
<>
<CreditCard className="w-4 h-4" /> Create Invoice & Pay
<CreditCard className="w-4 h-4" /> {c.createInvoicePay}
</>
) : (
<>
<CheckCircle className="w-4 h-4" /> Apply Changes
<CheckCircle className="w-4 h-4" /> {c.applyChanges}
</>
)}
</button>