mirror of
https://github.com/SamyRai/turash.git
synced 2025-12-26 23:01:33 +00:00
- Remove nested git repository from bugulma/frontend/.git - Add all frontend files to main repository tracking - Convert from separate frontend/backend repos to unified monorepo - Preserve all frontend code and development history as tracked files - Eliminate nested repository complexity for simpler development workflow This creates a proper monorepo structure with frontend and backend coexisting in the same repository for easier development and deployment.
151 lines
5.4 KiB
TypeScript
151 lines
5.4 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);
|