79 lines
2.4 KiB
TypeScript
79 lines
2.4 KiB
TypeScript
|
|
import React from 'react';
|
||
|
|
import Button from './Button'; // Import the Button component
|
||
|
|
|
||
|
|
// Define a basic interface for a service offer, exported for potential use elsewhere
|
||
|
|
export interface ServiceOffer {
|
||
|
|
id: string;
|
||
|
|
title: string;
|
||
|
|
description: string;
|
||
|
|
price?: string;
|
||
|
|
imageUrl?: string;
|
||
|
|
imageAlt?: string;
|
||
|
|
actionText?: string;
|
||
|
|
onAction?: (id: string) => void;
|
||
|
|
themeColor?: 'purple' | 'blue' | 'teal' | 'amber'; // Optional theme color
|
||
|
|
}
|
||
|
|
|
||
|
|
interface ServiceOfferCardProps {
|
||
|
|
offer: ServiceOffer;
|
||
|
|
}
|
||
|
|
|
||
|
|
const ServiceOfferCard: React.FC<ServiceOfferCardProps> = ({ offer }) => {
|
||
|
|
const handleActionClick = () => {
|
||
|
|
if (offer.onAction) {
|
||
|
|
offer.onAction(offer.id);
|
||
|
|
}
|
||
|
|
};
|
||
|
|
|
||
|
|
return (
|
||
|
|
<div
|
||
|
|
className="bg-white rounded-xl transition-all duration-300 ease-in-out overflow-hidden flex flex-col h-full group"
|
||
|
|
role="article"
|
||
|
|
aria-labelledby={`offer-title-${offer.id}`}
|
||
|
|
>
|
||
|
|
{offer.imageUrl && (
|
||
|
|
<div className="w-full h-48 sm:h-56 bg-slate-200 overflow-hidden">
|
||
|
|
<img
|
||
|
|
src={offer.imageUrl}
|
||
|
|
alt={offer.imageAlt || `Visual for ${offer.title}`}
|
||
|
|
className="w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-300"
|
||
|
|
loading="lazy"
|
||
|
|
/>
|
||
|
|
</div>
|
||
|
|
)}
|
||
|
|
<div className="p-5 md:p-6 flex flex-col flex-grow">
|
||
|
|
<h3
|
||
|
|
id={`offer-title-${offer.id}`}
|
||
|
|
className={`font-quicksand text-xl sm:text-2xl font-bold text-slate-900 mb-2 group-hover:text-black transition-colors`}
|
||
|
|
>
|
||
|
|
{offer.title}
|
||
|
|
</h3>
|
||
|
|
<p className="font-inter text-slate-600 text-sm leading-relaxed mb-4 flex-grow">
|
||
|
|
{offer.description}
|
||
|
|
</p>
|
||
|
|
|
||
|
|
<div className="flex flex-wrap items-center justify-between mt-auto">
|
||
|
|
{offer.price && (
|
||
|
|
<p className={`font-quicksand text-xl font-bold text-slate-700 mb-3 sm:mb-0`}>
|
||
|
|
{offer.price}
|
||
|
|
</p>
|
||
|
|
)}
|
||
|
|
{offer.actionText && offer.onAction && (
|
||
|
|
<Button
|
||
|
|
variant="outline"
|
||
|
|
size="md"
|
||
|
|
onClick={handleActionClick}
|
||
|
|
className={`${!offer.price ? 'ml-auto' : ''}`}
|
||
|
|
aria-label={`${offer.actionText} for ${offer.title}`}
|
||
|
|
>
|
||
|
|
{offer.actionText}
|
||
|
|
</Button>
|
||
|
|
)}
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
</div>
|
||
|
|
);
|
||
|
|
};
|
||
|
|
|
||
|
|
export default ServiceOfferCard;
|