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:
tema 2025-09-08 18:45:00 +09:00
parent c9356cad65
commit 2325cf2753
5 changed files with 4 additions and 44 deletions

View File

@ -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,
};

View File

@ -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
}

View File

@ -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,

View File

@ -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>

View File

@ -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>