)}
diff --git a/apps/portal/src/features/catalog/components/base/AddressConfirmation.tsx b/apps/portal/src/features/catalog/components/base/AddressConfirmation.tsx
index 67767203..60da9d56 100644
--- a/apps/portal/src/features/catalog/components/base/AddressConfirmation.tsx
+++ b/apps/portal/src/features/catalog/components/base/AddressConfirmation.tsx
@@ -407,30 +407,28 @@ export function AddressConfirmation({
)}
{/* Action buttons */}
-
-
- {/* Primary action when pending for Internet orders */}
- {isInternetOrder && !addressConfirmed && !editing && (
-
- )}
-
+
+ {/* Primary action when pending for Internet orders */}
+ {isInternetOrder && !addressConfirmed && !editing && (
+
+ )}
- {/* Edit button - always on the right */}
+ {/* Edit button */}
{billingInfo.isComplete && !editing && (
)}
diff --git a/apps/portal/src/features/catalog/components/base/CardBadge.tsx b/apps/portal/src/features/catalog/components/base/CardBadge.tsx
new file mode 100644
index 00000000..377107b0
--- /dev/null
+++ b/apps/portal/src/features/catalog/components/base/CardBadge.tsx
@@ -0,0 +1,46 @@
+"use client";
+
+export type BadgeVariant =
+ | "gold"
+ | "platinum"
+ | "silver"
+ | "recommended"
+ | "family"
+ | "new"
+ | "default";
+
+interface CardBadgeProps {
+ text: string;
+ variant?: BadgeVariant;
+ size?: "sm" | "md";
+}
+
+export function CardBadge({ text, variant = "default", size = "md" }: CardBadgeProps) {
+ const getVariantClasses = () => {
+ switch (variant) {
+ case "gold":
+ return "bg-yellow-50 text-yellow-700 border-yellow-200";
+ case "platinum":
+ return "bg-indigo-50 text-indigo-700 border-indigo-200";
+ case "silver":
+ return "bg-gray-50 text-gray-700 border-gray-200";
+ case "recommended":
+ return "bg-green-50 text-green-700 border-green-200";
+ case "family":
+ return "bg-blue-50 text-blue-700 border-blue-200";
+ case "new":
+ return "bg-purple-50 text-purple-700 border-purple-200";
+ default:
+ return "bg-gray-50 text-gray-700 border-gray-200";
+ }
+ };
+
+ const sizeClasses = size === "sm" ? "text-xs px-2 py-0.5" : "text-xs px-2.5 py-1";
+
+ return (
+
+ {text}
+
+ );
+}
+
diff --git a/apps/portal/src/features/catalog/components/base/CardPricing.tsx b/apps/portal/src/features/catalog/components/base/CardPricing.tsx
new file mode 100644
index 00000000..1d387e7a
--- /dev/null
+++ b/apps/portal/src/features/catalog/components/base/CardPricing.tsx
@@ -0,0 +1,78 @@
+"use client";
+
+import { CurrencyYenIcon } from "@heroicons/react/24/outline";
+
+interface CardPricingProps {
+ monthlyPrice?: number | null;
+ oneTimePrice?: number | null;
+ size?: "sm" | "md" | "lg";
+ alignment?: "left" | "right";
+}
+
+export function CardPricing({
+ monthlyPrice,
+ oneTimePrice,
+ size = "md",
+ alignment = "right"
+}: CardPricingProps) {
+ const sizeClasses = {
+ sm: {
+ monthlyPrice: "text-xl",
+ monthlyLabel: "text-xs",
+ icon: "h-5 w-5",
+ oneTimePrice: "text-sm",
+ oneTimeLabel: "text-xs",
+ },
+ md: {
+ monthlyPrice: "text-2xl",
+ monthlyLabel: "text-sm",
+ icon: "h-6 w-6",
+ oneTimePrice: "text-base",
+ oneTimeLabel: "text-xs",
+ },
+ lg: {
+ monthlyPrice: "text-3xl",
+ monthlyLabel: "text-base",
+ icon: "h-7 w-7",
+ oneTimePrice: "text-lg",
+ oneTimeLabel: "text-sm",
+ },
+ };
+
+ const alignClass = alignment === "right" ? "text-right" : "text-left";
+ const justifyClass = alignment === "right" ? "justify-end" : "justify-start";
+
+ if (!monthlyPrice && !oneTimePrice) {
+ return null;
+ }
+
+ const classes = sizeClasses[size];
+
+ return (
+
+ {monthlyPrice && monthlyPrice > 0 && (
+
+
+
+ {monthlyPrice.toLocaleString()}
+
+
+ /month
+
+
+ )}
+ {oneTimePrice && oneTimePrice > 0 && (
+
+
+
+ {oneTimePrice.toLocaleString()}
+
+
+ one-time
+
+
+ )}
+
+ );
+}
+
diff --git a/apps/portal/src/features/catalog/components/base/index.ts b/apps/portal/src/features/catalog/components/base/index.ts
new file mode 100644
index 00000000..4dd7f5f7
--- /dev/null
+++ b/apps/portal/src/features/catalog/components/base/index.ts
@@ -0,0 +1,12 @@
+export { CardPricing } from "./CardPricing";
+export { CardBadge } from "./CardBadge";
+export type { BadgeVariant } from "./CardBadge";
+export { ProductCard } from "./ProductCard";
+export type { ProductCardProps } from "./ProductCard";
+export { CatalogHero } from "./CatalogHero";
+export type { CatalogHeroProps } from "./CatalogHero";
+export { CatalogBackLink } from "./CatalogBackLink";
+export { OrderSummary } from "./OrderSummary";
+export { PricingDisplay } from "./PricingDisplay";
+export type { PricingDisplayProps } from "./PricingDisplay";
+
diff --git a/apps/portal/src/features/catalog/components/common/FeatureCard.tsx b/apps/portal/src/features/catalog/components/common/FeatureCard.tsx
index 98bcbae5..f3bec459 100644
--- a/apps/portal/src/features/catalog/components/common/FeatureCard.tsx
+++ b/apps/portal/src/features/catalog/components/common/FeatureCard.tsx
@@ -1,7 +1,6 @@
"use client";
import React from "react";
-import { AnimatedCard } from "@/components/molecules/AnimatedCard/AnimatedCard";
export function FeatureCard({
icon,
@@ -13,12 +12,14 @@ export function FeatureCard({
description: string;
}) {
return (
-
-
-
{icon}
+
+
+ {icon}
-
{title}
-
{description}
-
+
+
{title}
+
{description}
+
+
);
}
diff --git a/apps/portal/src/features/catalog/components/common/ServiceHeroCard.tsx b/apps/portal/src/features/catalog/components/common/ServiceHeroCard.tsx
index 3939d46e..cbf0fe74 100644
--- a/apps/portal/src/features/catalog/components/common/ServiceHeroCard.tsx
+++ b/apps/portal/src/features/catalog/components/common/ServiceHeroCard.tsx
@@ -22,38 +22,35 @@ export function ServiceHeroCard({
}) {
const colorClasses = {
blue: {
- bg: "bg-blue-50",
- border: "border-blue-200",
iconBg: "bg-blue-100",
iconText: "text-blue-600",
- button: "bg-blue-600 hover:bg-blue-700",
- hoverBorder: "hover:border-blue-300",
+ border: "border-blue-100",
+ hoverBorder: "hover:border-blue-200",
},
green: {
- bg: "bg-green-50",
- border: "border-green-200",
iconBg: "bg-green-100",
iconText: "text-green-600",
- button: "bg-green-600 hover:bg-green-700",
- hoverBorder: "hover:border-green-300",
+ border: "border-green-100",
+ hoverBorder: "hover:border-green-200",
},
purple: {
- bg: "bg-purple-50",
- border: "border-purple-200",
iconBg: "bg-purple-100",
iconText: "text-purple-600",
- button: "bg-purple-600 hover:bg-purple-700",
- hoverBorder: "hover:border-purple-300",
+ border: "border-purple-100",
+ hoverBorder: "hover:border-purple-200",
},
} as const;
const colors = colorClasses[color];
return (
-
-
-
-
+
+
+ {/* Icon and Title */}
+
+
@@ -61,32 +58,31 @@ export function ServiceHeroCard({
-
{description}
+ {/* Description */}
+
{description}
-