diff --git a/apps/bff/Dockerfile b/apps/bff/Dockerfile
index 8a7e499c..65f8c0a2 100644
--- a/apps/bff/Dockerfile
+++ b/apps/bff/Dockerfile
@@ -106,7 +106,7 @@ COPY --from=builder /app/apps/bff/prisma ./apps/bff/prisma
# Generate Prisma client in production environment
WORKDIR /app/apps/bff
-RUN pnpm dlx prisma generate
+RUN pnpm dlx prisma@6.14.0 generate
# Strip build toolchain to shrink image
RUN apk del --no-cache python3 make g++ pkgconfig && rm -rf /root/.cache /var/cache/apk/*
diff --git a/apps/portal/src/features/sim-management/components/SimDetailsCard.tsx b/apps/portal/src/features/sim-management/components/SimDetailsCard.tsx
index f2c93401..21052552 100644
--- a/apps/portal/src/features/sim-management/components/SimDetailsCard.tsx
+++ b/apps/portal/src/features/sim-management/components/SimDetailsCard.tsx
@@ -10,6 +10,10 @@ import {
ExclamationTriangleIcon,
XCircleIcon,
} from "@heroicons/react/24/outline";
+import type { SimDetails } from "@customer-portal/domain/sim";
+
+// Re-export for backwards compatibility
+export type { SimDetails };
// Inline formatPlanShort function
function formatPlanShort(planCode?: string): string {
@@ -26,33 +30,6 @@ function formatPlanShort(planCode?: string): string {
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 {
simDetails: SimDetails;
isLoading?: boolean;
@@ -292,7 +269,7 @@ export function SimDetailsCard({
Physical SIM Details
- {formatPlan(simDetails.planCode)} • {`${simDetails.size} SIM`}
+ {formatPlan(simDetails.planCode)} • {`${simDetails.simType} SIM`}
@@ -321,12 +298,10 @@ export function SimDetailsCard({
{simDetails.msisdn}
- {simDetails.simType === "physical" && (
-
-
-
{simDetails.iccid}
-
- )}
+
+
+
{simDetails.iccid}
+
{simDetails.eid && (
@@ -342,10 +317,10 @@ export function SimDetailsCard({
)}
- {simDetails.startDate && (
+ {simDetails.activatedAt && (
-
{formatDate(simDetails.startDate)}
+
{formatDate(simDetails.activatedAt)}
)}
@@ -368,37 +343,32 @@ export function SimDetailsCard({
- Voice {simDetails.hasVoice ? "Enabled" : "Disabled"}
+ Voicemail {simDetails.voiceMailEnabled ? "Enabled" : "Disabled"}
- SMS {simDetails.hasSms ? "Enabled" : "Disabled"}
+ Call Waiting {simDetails.callWaitingEnabled ? "Enabled" : "Disabled"}
- {(simDetails.ipv4 || simDetails.ipv6) && (
-
-
-
- {simDetails.ipv4 && (
-
IPv4: {simDetails.ipv4}
- )}
- {simDetails.ipv6 && (
-
IPv6: {simDetails.ipv6}
- )}
-
+ {simDetails.internationalRoamingEnabled && (
+
+
+
+ International Roaming Enabled
+
)}
@@ -406,21 +376,14 @@ export function SimDetailsCard({
)}
- {/* Pending Operations */}
- {simDetails.pendingOperations && simDetails.pendingOperations.length > 0 && (
+ {/* Expiry Date */}
+ {simDetails.expiresAt && (
-
- Pending Operations
-
-
- {simDetails.pendingOperations.map((operation, index) => (
-
-
-
- {operation.operation} scheduled for {formatDate(operation.scheduledDate)}
-
-
- ))}
+
+
+
+ Expires on {formatDate(simDetails.expiresAt)}
+
)}
diff --git a/apps/portal/src/features/sim-management/components/SimManagementSection.tsx b/apps/portal/src/features/sim-management/components/SimManagementSection.tsx
index 6d130672..b231ea5d 100644
--- a/apps/portal/src/features/sim-management/components/SimManagementSection.tsx
+++ b/apps/portal/src/features/sim-management/components/SimManagementSection.tsx
@@ -223,10 +223,10 @@ export function SimManagementSection({ subscriptionId }: SimManagementSectionPro
)}
diff --git a/apps/portal/src/features/subscriptions/services/sim-actions.service.ts b/apps/portal/src/features/subscriptions/services/sim-actions.service.ts
index 46720201..9a33f831 100644
--- a/apps/portal/src/features/subscriptions/services/sim-actions.service.ts
+++ b/apps/portal/src/features/subscriptions/services/sim-actions.service.ts
@@ -4,6 +4,7 @@ import type {
SimTopUpRequest,
SimPlanChangeRequest,
SimCancelRequest,
+ SimReissueRequest,
} from "@customer-portal/domain/sim";
// Types imported from domain - no duplication
@@ -45,4 +46,11 @@ export const simActionsService = {
return simInfoSchema.parse(response.data);
},
+
+ async reissueEsim(subscriptionId: string, request: SimReissueRequest): Promise {
+ await apiClient.POST("/api/subscriptions/{subscriptionId}/sim/reissue-esim", {
+ params: { path: { subscriptionId } },
+ body: request,
+ });
+ },
};
diff --git a/packages/domain/catalog/index.ts b/packages/domain/catalog/index.ts
index 1dd6b849..d35171fc 100644
--- a/packages/domain/catalog/index.ts
+++ b/packages/domain/catalog/index.ts
@@ -11,6 +11,7 @@ export {
type SalesforceProductFieldMap,
type PricingTier,
type CatalogFilter,
+ type CatalogPriceInfo,
} from "./contract";
// Schemas (includes derived types)