Refactor Freebit plan change request and improve error handling
- Updated FreebititPlanChangeRequest interface to use 'planCode' instead of 'plancode' for consistency. - Enhanced error handling in WhmcsInvoiceService to provide a default message for payment errors. - Removed unused state variables for global IP assignment and scheduling in SIM change plan components to streamline the user interface.
This commit is contained in:
parent
c9356cad65
commit
2325cf2753
@ -467,7 +467,7 @@ export class FreebititService {
|
||||
try {
|
||||
const request: Omit<FreebititPlanChangeRequest, 'authKey'> = {
|
||||
account,
|
||||
plancode: newPlanCode,
|
||||
planCode: newPlanCode,
|
||||
globalip: options.assignGlobalIp ? '1' : '0',
|
||||
runTime: options.scheduledAt,
|
||||
};
|
||||
|
||||
@ -164,7 +164,7 @@ export interface FreebititQuotaHistoryResponse {
|
||||
export interface FreebititPlanChangeRequest {
|
||||
authKey: string;
|
||||
account: string;
|
||||
plancode: string;
|
||||
planCode: string;
|
||||
globalip?: '0' | '1'; // 0=no IP, 1=assign global IP
|
||||
runTime?: string; // YYYYMMDD - optional, immediate if omitted
|
||||
}
|
||||
|
||||
@ -370,7 +370,7 @@ export class WhmcsInvoiceService {
|
||||
});
|
||||
|
||||
// Return user-friendly error message instead of technical API error
|
||||
const userFriendlyError = this.getUserFriendlyPaymentError(response.message || response.error);
|
||||
const userFriendlyError = this.getUserFriendlyPaymentError(response.message || response.error || 'Unknown payment error');
|
||||
|
||||
return {
|
||||
success: false,
|
||||
|
||||
@ -20,8 +20,6 @@ export default function SimChangePlanPage() {
|
||||
const subscriptionId = parseInt(params.id as string);
|
||||
const [currentPlanCode] = useState<string>("");
|
||||
const [newPlanCode, setNewPlanCode] = useState<"" | PlanCode>("");
|
||||
const [assignGlobalIp, setAssignGlobalIp] = useState(false);
|
||||
const [scheduledAt, setScheduledAt] = useState("");
|
||||
const [message, setMessage] = useState<string | null>(null);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@ -40,8 +38,6 @@ export default function SimChangePlanPage() {
|
||||
try {
|
||||
await authenticatedApi.post(`/subscriptions/${subscriptionId}/sim/change-plan`, {
|
||||
newPlanCode,
|
||||
assignGlobalIp,
|
||||
scheduledAt: scheduledAt ? scheduledAt.replace(/-/g, "") : undefined,
|
||||
});
|
||||
setMessage("Plan change submitted successfully");
|
||||
} catch (e: any) {
|
||||
@ -78,16 +74,6 @@ export default function SimChangePlanPage() {
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center">
|
||||
<input id="globalip" type="checkbox" checked={assignGlobalIp} onChange={(e)=>setAssignGlobalIp(e.target.checked)} className="h-4 w-4 text-blue-600 border-gray-300 rounded" />
|
||||
<label htmlFor="globalip" className="ml-2 text-sm text-gray-700">Assign global IP</label>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-2">Schedule (optional)</label>
|
||||
<input type="date" value={scheduledAt} onChange={(e)=>setScheduledAt(e.target.value)} className="w-full px-3 py-2 border border-gray-300 rounded-md" />
|
||||
</div>
|
||||
|
||||
<div className="flex gap-3">
|
||||
<button type="submit" disabled={loading} className="px-4 py-2 rounded-md bg-blue-600 text-white text-sm disabled:opacity-50">{loading ? 'Processing…' : 'Submit Plan Change'}</button>
|
||||
<Link href={`/subscriptions/${subscriptionId}#sim-management`} className="px-4 py-2 rounded-md border border-gray-300 text-sm text-gray-700 bg-white hover:bg-gray-50">Back</Link>
|
||||
|
||||
@ -25,8 +25,6 @@ export function ChangePlanModal({ subscriptionId, currentPlanCode, onClose, onSu
|
||||
const allowedPlans = (PLAN_CODES as readonly PlanCode[]).filter(code => code !== (currentPlanCode || ''));
|
||||
|
||||
const [newPlanCode, setNewPlanCode] = useState<"" | PlanCode>("");
|
||||
const [assignGlobalIp, setAssignGlobalIp] = useState(false);
|
||||
const [scheduledAt, setScheduledAt] = useState(""); // YYYY-MM-DD
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const submit = async () => {
|
||||
@ -38,8 +36,6 @@ export function ChangePlanModal({ subscriptionId, currentPlanCode, onClose, onSu
|
||||
try {
|
||||
await authenticatedApi.post(`/subscriptions/${subscriptionId}/sim/change-plan`, {
|
||||
newPlanCode: newPlanCode,
|
||||
assignGlobalIp,
|
||||
scheduledAt: scheduledAt ? scheduledAt.replaceAll("-", "") : undefined,
|
||||
});
|
||||
onSuccess();
|
||||
} catch (e: any) {
|
||||
@ -78,29 +74,7 @@ export function ChangePlanModal({ subscriptionId, currentPlanCode, onClose, onSu
|
||||
<option key={code} value={code}>{PLAN_LABELS[code]}</option>
|
||||
))}
|
||||
</select>
|
||||
<p className="mt-1 text-xs text-gray-500">Only plans different from your current plan are listed.</p>
|
||||
</div>
|
||||
<div className="flex items-center">
|
||||
<input
|
||||
id="assignGlobalIp"
|
||||
type="checkbox"
|
||||
checked={assignGlobalIp}
|
||||
onChange={(e) => setAssignGlobalIp(e.target.checked)}
|
||||
className="h-4 w-4 text-blue-600 border-gray-300 rounded"
|
||||
/>
|
||||
<label htmlFor="assignGlobalIp" className="ml-2 block text-sm text-gray-700">
|
||||
Assign global IP address
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700">Schedule Date (optional)</label>
|
||||
<input
|
||||
type="date"
|
||||
value={scheduledAt}
|
||||
onChange={(e) => setScheduledAt(e.target.value)}
|
||||
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500 text-sm"
|
||||
/>
|
||||
<p className="mt-1 text-xs text-gray-500">If empty, the plan change is processed immediately.</p>
|
||||
<p className="mt-1 text-xs text-gray-500">Only plans different from your current plan are listed. The change will be scheduled for the 1st of the next month.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user