feat: add new UI components for product reviews, promotions, seller summaries, support center, and request forms

- Created ProductReviewCard component for displaying product reviews with options to edit and delete.
- Implemented PromoCard component for promotional content with navigation support.
- Added RoundImageLabel component for displaying images with labels in a circular format.
- Developed SellerSummary component to showcase seller information and actions.
- Introduced SupportCenter component for user support with FAQs and action buttons.
- Created SupportRequestForm component for submitting support requests with attachments.
- Added Tabs component for organizing content into tabbed sections, including product descriptions and reviews.
- Implemented utility function for class name merging.
- Defined TypeScript interfaces for User, Product, Order, and OrderItem.
- Configured TypeScript settings in tsconfig.json for improved type checking and module resolution.
This commit is contained in:
2026-07-02 15:32:43 +05:30
commit 3d02889527
71 changed files with 12377 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
import { cn } from "@/lib/utils";
interface AddressRowProps {
name?: string;
phone?: string;
addressLines?: string[];
selected?: boolean;
showRadio?: boolean;
showDefaultBadge?: boolean;
showRemove?: boolean;
showEdit?: boolean;
showToggle?: boolean;
toggleEnabled?: boolean;
onSelect?: () => void;
onRemove?: () => void;
onEdit?: () => void;
onToggle?: () => void;
className?: string;
}
export default function AddressRow({
name = "Ashan Namal",
phone = "+94723452389",
addressLines = [
"29 Visakha Private Road, Colombo",
"Colombo - 05 , Western,SriLanka",
],
selected = true,
showRadio = true,
showDefaultBadge = true,
showRemove = true,
showEdit = true,
showToggle = false,
toggleEnabled = false,
onSelect,
onRemove,
onEdit,
onToggle,
className,
}: AddressRowProps) {
return (
<article
className={cn(
"flex w-full items-center gap-4 rounded-lg border border-gray-200 bg-white px-5 py-4 text-sm text-[#1f2440]",
className
)}
>
{showRadio && (
<button
type="button"
onClick={onSelect}
className="flex h-4 w-4 shrink-0 items-center justify-center rounded-full border-2 border-[#00AFC1]"
aria-label={`Select address for ${name}`}
>
{selected && <span className="h-2 w-2 rounded-full bg-[#00AFC1]" />}
</button>
)}
<div className="min-w-0 flex-1">
<p className="font-semibold text-gray-900">
{name} <span className="font-normal text-gray-600">| {phone}</span>
</p>
<div className="mt-2 space-y-1 text-xs text-gray-500">
{addressLines.map((line) => (
<p key={line}>{line}</p>
))}
</div>
{showDefaultBadge && (
<span className="mt-2 inline-flex rounded bg-cyan-50 px-3 py-1 text-[11px] font-medium text-[#00AFC1]">
Default
</span>
)}
</div>
<div className="flex shrink-0 items-center gap-5">
{showToggle && (
<button
type="button"
onClick={onToggle}
className={cn(
"relative h-6 w-11 rounded-full transition-colors",
toggleEnabled ? "bg-[#00AFC1]" : "bg-gray-200"
)}
aria-label="Toggle default address"
>
<span
className={cn(
"absolute top-1 h-4 w-4 rounded-full bg-white transition-transform",
toggleEnabled ? "translate-x-6" : "translate-x-1"
)}
/>
</button>
)}
{showRemove && (
<button
type="button"
onClick={onRemove}
className="text-xs font-medium text-red-500 transition-colors hover:text-red-600"
>
Remove
</button>
)}
{showEdit && (
<button
type="button"
onClick={onEdit}
className="text-xs font-medium text-[#00AFC1] transition-colors hover:text-[#008fa0]"
>
Edit
</button>
)}
</div>
</article>
);
}