Billing Coupon Code
hextaui/billing-coupon-codeFreeComponent
Apply and manage discount coupon codes.
Install it
npx shadcn@latest add https://hextaui.com/r/billing-coupon-code.jsonSource
1"use client";23import { Check, Loader2, Tag, X } from "lucide-react";4import { useState } from "react";5import { cn } from "@/lib/utils";6import { Badge } from "@/registry/new-york/ui/badge";7import { Button } from "@/registry/new-york/ui/button";8import {9 Card,10 CardContent,11 CardDescription,12 CardHeader,13 CardTitle,14} from "@/registry/new-york/ui/card";15import {16 Field,17 FieldContent,18 FieldError,19 FieldLabel,20} from "@/registry/new-york/ui/field";21import {22 InputGroup,23 InputGroupAddon,24 InputGroupInput,25} from "@/registry/new-york/ui/input-group";26import { Separator } from "@/registry/new-york/ui/separator";2728export interface AppliedCoupon {29 code: string;30 type: "percentage" | "fixed";31 value: number;32 label?: string;33 expiresAt?: Date;34 description?: string;35}3637export interface BillingCouponCodeProps {38 onApply?: (code: string) => Promise<void>;39 onRemove?: () => Promise<void>;40 appliedCoupon?: AppliedCoupon | null;41 className?: string;42 currency?: string;43 isLoading?: boolean;44 error?: string;45}4647function formatPrice(amount: number, currency = "USD"): string {48 return new Intl.NumberFormat("en-US", {49 style: "currency",50 currency,51 minimumFractionDigits: 2,52 maximumFractionDigits: 2,53 }).format(amount);54}5556function formatDate(date: Date): string {57 const year = date.getFullYear();58 const month = date.toLocaleString("en-US", { month: "short" });59 const day = date.getDate();60 return `${month} ${day}, ${year}`;61}6263export default function BillingCouponCode({64 onApply,65 onRemove,66 appliedCoupon,67 className,68 currency = "USD",69 isLoading: externalLoading,70 error: externalError,71}: BillingCouponCodeProps) {72 const [code, setCode] = useState("");73 const [isLoading, setIsLoading] = useState(false);74 const [error, setError] = useState<string | null>(null);7576 const handleApply = async () => {77 if (!code.trim()) {78 setError("Please enter a coupon code");79 return;80 }8182 if (!onApply) return;8384 setIsLoading(true);85 setError(null);8687 try {88 await onApply(code.trim().toUpperCase());89 setCode("");90 } catch (err) {91 setError(92 err instanceof Error ? err.message : "Failed to apply coupon code"93 );94 } finally {95 setIsLoading(false);96 }97 };9899 const handleRemove = async () => {100 if (!onRemove) return;101102 setIsLoading(true);103 setError(null);104105 try {106 await onRemove();107 } catch (err) {108 setError(109// … truncated
What it pulls in
Other registry items
Files it writes
More from HextaUI
All 139 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| Accordionaccordion | HextaUI | Components | Free | 1 dep | |
| AI Chat Historyai-chat-history | HextaUI | Components | Free | no deps | |
| AI Citationsai-citations | HextaUI | Components | Free | no deps | |
| AI Conversationai-conversation | HextaUI | Components | Free | no deps | |
| AI Error Handlerai-error-handler | HextaUI | Components | Free | no deps | |
| AI File Uploadai-file-upload | HextaUI | Components | Free | no deps | |
| AI Messageai-message | HextaUI | Components | Free | 4 deps | |
| AI Model Selectorai-model-selector | HextaUI | Components | Free | no deps |
