āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā ā š shadcn/directory/creativetimofficial/ui/components/software-purchase-card ā āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
<ComponentPreview name="software-purchase-card-demo" description="A software purchase approval card." />
npx shadcn@latest add software-purchase-card
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
npm install lucide-react
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="software-purchase-card" title="components/cards/software-purchase.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps> </TabsContent> </CodeTabs>import { SoftwarePurchaseCard } from "@/components/cards/software-purchase"
<SoftwarePurchaseCard
softwareName="Enterprise Cloud Suite"
startDate="2025-01-15"
seats={50}
pricingType="per-seat"
price="$2,500"
onApprove={() => console.log("Approved")}
onDiscard={() => console.log("Discarded")}
/>
<SoftwarePurchaseCard
softwareName="Design Tools Pro"
startDate="2025-02-01"
seats={25}
pricingType="flat-rate"
price="$999"
onApprove={handleApprove}
onDiscard={handleDiscard}
/>
<SoftwarePurchaseCard
softwareName="API Gateway Service"
startDate="2025-01-20"
seats={10}
pricingType="usage-based"
price="$0.05/request"
onApprove={handleApprove}
onDiscard={handleDiscard}
/>
The main card component for displaying software purchase details.
| Prop | Type | Default | Description |
| ------------ | -------------------------------------------- | -------------------------- | --------------------------------------------- |
| softwareName | string | "Enterprise Cloud Suite" | Name of the software |
| startDate | string | "2025-01-15" | Start date in ISO format (YYYY-MM-DD) |
| seats | number | 50 | Number of user seats/licenses |
| pricingType | "per-seat" \| "flat-rate" \| "usage-based" | "per-seat" | Type of pricing model |
| price | string | "$2,500" | Price display string (can include formatting) |
| onApprove | () => void | undefined | Callback function when approve button clicked |
| onDiscard | () => void | undefined | Callback function when discard button clicked |
function PurchaseApproval() {
const [status, setStatus] = useState<"pending" | "approved" | "discarded">(
"pending"
)
const handleApprove = () => {
setStatus("approved")
// API call to approve purchase
approvePurchase(purchaseId)
}
const handleDiscard = () => {
setStatus("discarded")
// API call to discard purchase
discardPurchase(purchaseId)
}
return (
<SoftwarePurchaseCard
softwareName="Marketing Automation Suite"
startDate="2025-03-01"
seats={75}
pricingType="per-seat"
price="$3,750"
onApprove={handleApprove}
onDiscard={handleDiscard}
/>
)
}
function PurchaseApprovalWithLoading() {
const [loading, setLoading] = useState(false)
const handleApprove = async () => {
setLoading(true)
try {
await approvePurchaseRequest()
toast.success("Purchase approved successfully")
} catch (error) {
toast.error("Failed to approve purchase")
} finally {
setLoading(false)
}
}
return (
<SoftwarePurchaseCard
softwareName="Analytics Platform"
startDate="2025-02-15"
seats={100}
pricingType="flat-rate"
price="$5,000"
onApprove={handleApprove}
onDiscard={() => {}}
/>
)
}
function PurchaseRequestList() {
const requests = [
{
id: 1,
softwareName: "CRM Software",
startDate: "2025-01-15",
seats: 50,
pricingType: "per-seat" as const,
price: "$2,500",
},
{
id: 2,
softwareName: "Project Management Tool",
startDate: "2025-02-01",
seats: 30,
pricingType: "flat-rate" as const,
price: "$999",
},
]
return (
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{requests.map((request) => (
<SoftwarePurchaseCard
key={request.id}
{...request}
onApprove={() => handleApprove(request.id)}
onDiscard={() => handleDiscard(request.id)}
/>
))}
</div>
)
}
For a full-page implementation with detailed purchase information, check out the software-purchase-01 block.
toLocaleDateString with US localelucide-react are used for visual clarity (Calendar, Users, CreditCard, DollarSign)md (28rem)ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā ā
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā