mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
145 lines
5.3 KiB
TypeScript
145 lines
5.3 KiB
TypeScript
import React from 'react';
|
|
import { useNavigate } from 'react-router-dom';
|
|
// No longer needs SECTORS - uses getTranslatedSectorName directly
|
|
import { useTranslation } from '@/hooks/useI18n.tsx';
|
|
import { getTranslatedSectorName } from '@/lib/sector-mapper.ts';
|
|
import { getOrganizationSubtypeLabel } from '@/schemas/organizationSubtype.ts';
|
|
import type { Organization } from '@/types.ts';
|
|
import { Briefcase, MapPin, Building2 } from 'lucide-react';
|
|
import Badge from '@/components/ui/Badge.tsx';
|
|
import Button from '@/components/ui/Button.tsx';
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card.tsx';
|
|
import VerifiedBadge from '@/components/ui/VerifiedBadge.tsx';
|
|
|
|
interface OrganizationCardProps {
|
|
organization: Organization;
|
|
showDetails?: boolean;
|
|
onClick?: (organization: Organization) => void;
|
|
}
|
|
|
|
const OrganizationCard = ({ organization, showDetails = true, onClick }: OrganizationCardProps) => {
|
|
const { t } = useTranslation();
|
|
const navigate = useNavigate();
|
|
|
|
// Sector display handled by getTranslatedSectorName
|
|
|
|
const handleCardClick = () => {
|
|
if (onClick) {
|
|
onClick(organization);
|
|
} else {
|
|
navigate(`/organization/${organization.ID}`);
|
|
}
|
|
};
|
|
|
|
const handleViewDetails = (e: React.MouseEvent) => {
|
|
e.stopPropagation();
|
|
navigate(`/organization/${organization.ID}`);
|
|
};
|
|
|
|
return (
|
|
<Card
|
|
className="hover:shadow-lg transition-all duration-200 cursor-pointer group"
|
|
onClick={handleCardClick}
|
|
>
|
|
<CardHeader className="pb-3">
|
|
<div className="flex items-start justify-between">
|
|
<div className="flex items-center gap-3">
|
|
<div className="w-12 h-12 rounded-lg bg-muted flex items-center justify-center shrink-0 overflow-hidden">
|
|
{organization.LogoURL ? (
|
|
<img
|
|
src={organization.LogoURL}
|
|
alt={organization.Name}
|
|
className="w-full h-full object-cover"
|
|
loading="lazy"
|
|
/>
|
|
) : (
|
|
<Building2 className="h-6 w-6 text-muted-foreground" />
|
|
)}
|
|
</div>
|
|
<div className="min-w-0 flex-1">
|
|
<CardTitle className="text-lg group-hover:text-primary transition-colors truncate">
|
|
{organization.Name}
|
|
</CardTitle>
|
|
<div className="flex items-center gap-2 mt-1">
|
|
<Badge variant="outline" className="text-xs">
|
|
{getOrganizationSubtypeLabel(organization.Subtype)}
|
|
</Badge>
|
|
{organization.Verified && <VerifiedBadge />}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</CardHeader>
|
|
|
|
<CardContent className="pt-0">
|
|
<div className="space-y-3">
|
|
{/* Sector and Location */}
|
|
<div className="flex items-center justify-between text-sm">
|
|
<div className="flex items-center gap-1">
|
|
<Briefcase className="h-4 text-current text-muted-foreground w-4" />
|
|
<span className="text-muted-foreground">
|
|
{getTranslatedSectorName(organization.Sector)}
|
|
</span>
|
|
</div>
|
|
{organization.Address && (
|
|
<div className="flex items-center gap-1">
|
|
<MapPin className="h-4 text-current text-muted-foreground w-4" />
|
|
<span className="text-muted-foreground truncate max-w-32">
|
|
{organization.Address}
|
|
</span>
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Description */}
|
|
{organization.Description && showDetails && (
|
|
<p className="text-sm text-muted-foreground line-clamp-2">{organization.Description}</p>
|
|
)}
|
|
|
|
{/* Key Stats */}
|
|
{showDetails && (
|
|
<div className="grid grid-cols-3 gap-2 pt-2 border-t">
|
|
<div className="text-center">
|
|
<div className="text-lg font-semibold text-primary">
|
|
{organization.ResourceFlows?.length || 0}
|
|
</div>
|
|
<div className="text-xs text-muted-foreground">
|
|
{t('organizationCard.resourceFlows')}
|
|
</div>
|
|
</div>
|
|
<div className="text-center">
|
|
<div className="text-lg font-semibold text-success">
|
|
{organization.Matches?.length || 0}
|
|
</div>
|
|
<div className="text-xs text-muted-foreground">{t('organizationCard.matches')}</div>
|
|
</div>
|
|
<div className="text-center">
|
|
<div className="text-lg font-semibold text-warning">
|
|
{organization.Proposals?.length || 0}
|
|
</div>
|
|
<div className="text-xs text-muted-foreground">
|
|
{t('organizationCard.proposals')}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{/* Action Button */}
|
|
<div className="pt-2">
|
|
<Button
|
|
variant="outline"
|
|
size="sm"
|
|
onClick={handleViewDetails}
|
|
className="w-full group-hover:bg-primary group-hover:text-primary-foreground transition-colors"
|
|
>
|
|
{t('organizationCard.viewDetails')}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
);
|
|
};
|
|
|
|
export default React.memo(OrganizationCard);
|