Add InfoCard component to display customizable card layouts
Introduced a reusable InfoCard component with support for a variety of props including images, colors, text, and buttons. This component enhances flexibility and consistency in displaying card-based UI elements across the application.
This commit is contained in:
142
frontend/src/components/info-card.tsx
Normal file
142
frontend/src/components/info-card.tsx
Normal file
@@ -0,0 +1,142 @@
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
import { Card } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface CardButton {
|
||||
text: string;
|
||||
href: string;
|
||||
backgroundColor?: string;
|
||||
textColor?: string;
|
||||
}
|
||||
|
||||
interface InfoCardProps {
|
||||
imageSrc?: string | null;
|
||||
imageAlt?: string;
|
||||
imagePosition?: "left" | "right";
|
||||
borderColor?: string;
|
||||
backgroundColor?: string;
|
||||
boxShadow?: string;
|
||||
headingText: string;
|
||||
headingStyle?: React.CSSProperties;
|
||||
bodyText?: string;
|
||||
bodyTextColor?: string;
|
||||
buttonProps?: CardButtonProps;
|
||||
}
|
||||
|
||||
interface CardButtonProps {
|
||||
text: string;
|
||||
href: string;
|
||||
backgroundColor?: string;
|
||||
textColor?: string;
|
||||
}
|
||||
|
||||
const InfoCard: React.FC<InfoCardProps> = ({
|
||||
imageSrc,
|
||||
imageAlt = "Image",
|
||||
imagePosition = "left",
|
||||
borderColor = "#ccc",
|
||||
backgroundColor = "rgba(240,233,214,0.7)",
|
||||
boxShadow = "0 2px 4px rgba(0, 0, 0, 0.05)",
|
||||
headingText,
|
||||
headingStyle = {},
|
||||
bodyText,
|
||||
bodyTextColor = "#555",
|
||||
buttonProps,
|
||||
}) => {
|
||||
const imageElement = (
|
||||
<div className="mb-4 hidden md:mb-0 md:block">
|
||||
<div
|
||||
className="flex h-28 w-28 items-center justify-center rounded-full border-2 md:h-32 md:w-32"
|
||||
style={{ borderColor }}
|
||||
>
|
||||
{imageSrc ? (
|
||||
<div className="relative h-24 w-24 md:h-28 md:w-28">
|
||||
<Image
|
||||
src={imageSrc}
|
||||
alt={imageAlt ?? "Image"}
|
||||
fill
|
||||
className="object-contain"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<p className="text-center text-sm">{imageAlt ?? "Image"}</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
"mb-10 flex flex-col items-center md:items-start md:space-x-6",
|
||||
imagePosition === "right"
|
||||
? "md:flex-row-reverse md:space-x-reverse"
|
||||
: "md:flex-row",
|
||||
)}
|
||||
>
|
||||
{imageElement}
|
||||
|
||||
<Card
|
||||
className="flex-1 relative overflow-hidden p-6"
|
||||
style={{ backgroundColor, borderColor, boxShadow }}
|
||||
>
|
||||
{imageSrc && (
|
||||
<div
|
||||
className={cn(
|
||||
"absolute bottom-0 h-32 w-32 opacity-20 md:hidden",
|
||||
imagePosition === "right" ? "left-0" : "right-0",
|
||||
)}
|
||||
style={{
|
||||
backgroundImage: `url(${imageSrc})`,
|
||||
backgroundSize: "contain",
|
||||
backgroundRepeat: "no-repeat",
|
||||
backgroundPosition:
|
||||
imagePosition === "right" ? "bottom left" : "bottom right",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<h3
|
||||
className="mb-2 text-center text-2xl font-bold md:text-left"
|
||||
style={headingStyle}
|
||||
>
|
||||
{headingText}
|
||||
</h3>
|
||||
|
||||
{bodyText && (
|
||||
<p
|
||||
className="text-center md:text-left"
|
||||
style={{ color: bodyTextColor }}
|
||||
>
|
||||
{bodyText}
|
||||
</p>
|
||||
)}
|
||||
|
||||
{buttonProps && (
|
||||
<div className="mt-4 text-center md:text-left">
|
||||
<Link
|
||||
href={buttonProps.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
<Button
|
||||
className="rounded-full"
|
||||
style={{
|
||||
backgroundColor: buttonProps.backgroundColor,
|
||||
color: buttonProps.textColor ?? "white",
|
||||
}}
|
||||
>
|
||||
{buttonProps.text}
|
||||
</Button>
|
||||
</Link>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default InfoCard;
|
||||
Reference in New Issue
Block a user