Update Dockerfile and SimDetailsCard component for compatibility and enhancements
- Updated Prisma client generation command in Dockerfile to use version 6.14.0 for consistency. - Refactored SimDetailsCard component to improve type handling and UI elements, including re-exporting SimDetails for backwards compatibility. - Adjusted display logic for SIM details, including changes to how plan types and service dates are presented. - Enhanced button states in SimManagementSection for better clarity on invoice payment status. - Added reissueEsim method in sim-actions.service for handling eSIM reissue requests. - Introduced CatalogPriceInfo type in domain catalog for improved type definitions.
This commit is contained in:
parent
9fb54fd0fc
commit
c397eb51c7
@ -106,7 +106,7 @@ COPY --from=builder /app/apps/bff/prisma ./apps/bff/prisma
|
|||||||
|
|
||||||
# Generate Prisma client in production environment
|
# Generate Prisma client in production environment
|
||||||
WORKDIR /app/apps/bff
|
WORKDIR /app/apps/bff
|
||||||
RUN pnpm dlx prisma generate
|
RUN pnpm dlx prisma@6.14.0 generate
|
||||||
|
|
||||||
# Strip build toolchain to shrink image
|
# Strip build toolchain to shrink image
|
||||||
RUN apk del --no-cache python3 make g++ pkgconfig && rm -rf /root/.cache /var/cache/apk/*
|
RUN apk del --no-cache python3 make g++ pkgconfig && rm -rf /root/.cache /var/cache/apk/*
|
||||||
|
|||||||
@ -10,6 +10,10 @@ import {
|
|||||||
ExclamationTriangleIcon,
|
ExclamationTriangleIcon,
|
||||||
XCircleIcon,
|
XCircleIcon,
|
||||||
} from "@heroicons/react/24/outline";
|
} from "@heroicons/react/24/outline";
|
||||||
|
import type { SimDetails } from "@customer-portal/domain/sim";
|
||||||
|
|
||||||
|
// Re-export for backwards compatibility
|
||||||
|
export type { SimDetails };
|
||||||
|
|
||||||
// Inline formatPlanShort function
|
// Inline formatPlanShort function
|
||||||
function formatPlanShort(planCode?: string): string {
|
function formatPlanShort(planCode?: string): string {
|
||||||
@ -26,33 +30,6 @@ function formatPlanShort(planCode?: string): string {
|
|||||||
return planCode;
|
return planCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface SimDetails {
|
|
||||||
account: string;
|
|
||||||
msisdn: string;
|
|
||||||
iccid?: string;
|
|
||||||
imsi?: string;
|
|
||||||
eid?: string;
|
|
||||||
planCode: string;
|
|
||||||
status: "active" | "suspended" | "cancelled" | "pending";
|
|
||||||
simType: "physical" | "esim";
|
|
||||||
size: "standard" | "nano" | "micro" | "esim";
|
|
||||||
hasVoice: boolean;
|
|
||||||
hasSms: boolean;
|
|
||||||
remainingQuotaKb: number;
|
|
||||||
remainingQuotaMb: number;
|
|
||||||
startDate?: string;
|
|
||||||
ipv4?: string;
|
|
||||||
ipv6?: string;
|
|
||||||
voiceMailEnabled?: boolean;
|
|
||||||
callWaitingEnabled?: boolean;
|
|
||||||
internationalRoamingEnabled?: boolean;
|
|
||||||
networkType?: string;
|
|
||||||
pendingOperations?: Array<{
|
|
||||||
operation: string;
|
|
||||||
scheduledDate: string;
|
|
||||||
}>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SimDetailsCardProps {
|
interface SimDetailsCardProps {
|
||||||
simDetails: SimDetails;
|
simDetails: SimDetails;
|
||||||
isLoading?: boolean;
|
isLoading?: boolean;
|
||||||
@ -292,7 +269,7 @@ export function SimDetailsCard({
|
|||||||
<div>
|
<div>
|
||||||
<h3 className="text-lg font-medium text-gray-900">Physical SIM Details</h3>
|
<h3 className="text-lg font-medium text-gray-900">Physical SIM Details</h3>
|
||||||
<p className="text-sm text-gray-500">
|
<p className="text-sm text-gray-500">
|
||||||
{formatPlan(simDetails.planCode)} • {`${simDetails.size} SIM`}
|
{formatPlan(simDetails.planCode)} • {`${simDetails.simType} SIM`}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -321,12 +298,10 @@ export function SimDetailsCard({
|
|||||||
<p className="text-sm font-medium text-gray-900">{simDetails.msisdn}</p>
|
<p className="text-sm font-medium text-gray-900">{simDetails.msisdn}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{simDetails.simType === "physical" && (
|
<div>
|
||||||
<div>
|
<label className="text-xs text-gray-500">ICCID</label>
|
||||||
<label className="text-xs text-gray-500">ICCID</label>
|
<p className="text-sm font-mono text-gray-900 break-all">{simDetails.iccid}</p>
|
||||||
<p className="text-sm font-mono text-gray-900 break-all">{simDetails.iccid}</p>
|
</div>
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{simDetails.eid && (
|
{simDetails.eid && (
|
||||||
<div>
|
<div>
|
||||||
@ -342,10 +317,10 @@ export function SimDetailsCard({
|
|||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{simDetails.startDate && (
|
{simDetails.activatedAt && (
|
||||||
<div>
|
<div>
|
||||||
<label className="text-xs text-gray-500">Service Start Date</label>
|
<label className="text-xs text-gray-500">Service Start Date</label>
|
||||||
<p className="text-sm text-gray-900">{formatDate(simDetails.startDate)}</p>
|
<p className="text-sm text-gray-900">{formatDate(simDetails.activatedAt)}</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -368,37 +343,32 @@ export function SimDetailsCard({
|
|||||||
<div className="flex items-center space-x-4">
|
<div className="flex items-center space-x-4">
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<SignalIcon
|
<SignalIcon
|
||||||
className={`h-4 w-4 mr-1 ${simDetails.hasVoice ? "text-green-500" : "text-gray-400"}`}
|
className={`h-4 w-4 mr-1 ${simDetails.voiceMailEnabled ? "text-green-500" : "text-gray-400"}`}
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
className={`text-sm ${simDetails.hasVoice ? "text-green-600" : "text-gray-500"}`}
|
className={`text-sm ${simDetails.voiceMailEnabled ? "text-green-600" : "text-gray-500"}`}
|
||||||
>
|
>
|
||||||
Voice {simDetails.hasVoice ? "Enabled" : "Disabled"}
|
Voicemail {simDetails.voiceMailEnabled ? "Enabled" : "Disabled"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex items-center">
|
<div className="flex items-center">
|
||||||
<DevicePhoneMobileIcon
|
<DevicePhoneMobileIcon
|
||||||
className={`h-4 w-4 mr-1 ${simDetails.hasSms ? "text-green-500" : "text-gray-400"}`}
|
className={`h-4 w-4 mr-1 ${simDetails.callWaitingEnabled ? "text-green-500" : "text-gray-400"}`}
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
className={`text-sm ${simDetails.hasSms ? "text-green-600" : "text-gray-500"}`}
|
className={`text-sm ${simDetails.callWaitingEnabled ? "text-green-600" : "text-gray-500"}`}
|
||||||
>
|
>
|
||||||
SMS {simDetails.hasSms ? "Enabled" : "Disabled"}
|
Call Waiting {simDetails.callWaitingEnabled ? "Enabled" : "Disabled"}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{(simDetails.ipv4 || simDetails.ipv6) && (
|
{simDetails.internationalRoamingEnabled && (
|
||||||
<div>
|
<div className="flex items-center">
|
||||||
<label className="text-xs text-gray-500">IP Address</label>
|
<WifiIcon className="h-4 w-4 mr-1 text-green-500" />
|
||||||
<div className="space-y-1">
|
<span className="text-sm text-green-600">
|
||||||
{simDetails.ipv4 && (
|
International Roaming Enabled
|
||||||
<p className="text-sm font-mono text-gray-900">IPv4: {simDetails.ipv4}</p>
|
</span>
|
||||||
)}
|
|
||||||
{simDetails.ipv6 && (
|
|
||||||
<p className="text-sm font-mono text-gray-900">IPv6: {simDetails.ipv6}</p>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -406,21 +376,14 @@ export function SimDetailsCard({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Pending Operations */}
|
{/* Expiry Date */}
|
||||||
{simDetails.pendingOperations && simDetails.pendingOperations.length > 0 && (
|
{simDetails.expiresAt && (
|
||||||
<div className="mt-6 pt-6 border-t border-gray-200">
|
<div className="mt-6 pt-6 border-t border-gray-200">
|
||||||
<h4 className="text-sm font-medium text-gray-500 uppercase tracking-wider mb-3">
|
<div className="flex items-center text-sm">
|
||||||
Pending Operations
|
<ClockIcon className="h-4 w-4 text-amber-500 mr-2" />
|
||||||
</h4>
|
<span className="text-amber-800">
|
||||||
<div className="bg-blue-50 rounded-lg p-4">
|
Expires on {formatDate(simDetails.expiresAt)}
|
||||||
{simDetails.pendingOperations.map((operation, index) => (
|
</span>
|
||||||
<div key={index} className="flex items-center text-sm">
|
|
||||||
<ClockIcon className="h-4 w-4 text-blue-500 mr-2" />
|
|
||||||
<span className="text-blue-800">
|
|
||||||
{operation.operation} scheduled for {formatDate(operation.scheduledDate)}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -223,10 +223,10 @@ export function SimManagementSection({ subscriptionId }: SimManagementSectionPro
|
|||||||
</p>
|
</p>
|
||||||
<button
|
<button
|
||||||
onClick={handlePayInvoice}
|
onClick={handlePayInvoice}
|
||||||
disabled={createSsoLink.isPending || latestInvoice.status === 'paid'}
|
disabled={createSsoLink.isPending || latestInvoice.status === 'Paid'}
|
||||||
className="w-full px-4 py-2 bg-blue-600 text-white text-sm font-semibold rounded-lg hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed transition-colors"
|
className="w-full px-4 py-2 bg-blue-600 text-white text-sm font-semibold rounded-lg hover:bg-blue-700 disabled:bg-gray-400 disabled:cursor-not-allowed transition-colors"
|
||||||
>
|
>
|
||||||
{latestInvoice.status === 'paid' ? 'PAID' : createSsoLink.isPending ? 'Loading...' : 'PAY'}
|
{latestInvoice.status === 'Paid' ? 'PAID' : createSsoLink.isPending ? 'Loading...' : 'PAY'}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
@ -4,6 +4,7 @@ import type {
|
|||||||
SimTopUpRequest,
|
SimTopUpRequest,
|
||||||
SimPlanChangeRequest,
|
SimPlanChangeRequest,
|
||||||
SimCancelRequest,
|
SimCancelRequest,
|
||||||
|
SimReissueRequest,
|
||||||
} from "@customer-portal/domain/sim";
|
} from "@customer-portal/domain/sim";
|
||||||
|
|
||||||
// Types imported from domain - no duplication
|
// Types imported from domain - no duplication
|
||||||
@ -45,4 +46,11 @@ export const simActionsService = {
|
|||||||
|
|
||||||
return simInfoSchema.parse(response.data);
|
return simInfoSchema.parse(response.data);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async reissueEsim(subscriptionId: string, request: SimReissueRequest): Promise<void> {
|
||||||
|
await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/reissue-esim", {
|
||||||
|
params: { path: { subscriptionId } },
|
||||||
|
body: request,
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -11,6 +11,7 @@ export {
|
|||||||
type SalesforceProductFieldMap,
|
type SalesforceProductFieldMap,
|
||||||
type PricingTier,
|
type PricingTier,
|
||||||
type CatalogFilter,
|
type CatalogFilter,
|
||||||
|
type CatalogPriceInfo,
|
||||||
} from "./contract";
|
} from "./contract";
|
||||||
|
|
||||||
// Schemas (includes derived types)
|
// Schemas (includes derived types)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user