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.
105 lines
3.6 KiB
TypeScript
105 lines
3.6 KiB
TypeScript
import React, { useCallback, useMemo, useState } from 'react';
|
|
import {
|
|
useProposalsForOrganization,
|
|
useUpdateProposalStatus,
|
|
} from '@/hooks/api/useProposalsAPI.ts';
|
|
import { useTranslation } from '@/hooks/useI18n.tsx';
|
|
import { useOrganizations } from '@/hooks/useOrganizations.ts';
|
|
import { Organization } from '@/types.ts';
|
|
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/Tabs.tsx';
|
|
import ProposalCard from '@/components/organization/ProposalCard.tsx';
|
|
|
|
interface ProposalListProps {
|
|
organization: Organization;
|
|
}
|
|
|
|
const ProposalList = ({ organization }: ProposalListProps) => {
|
|
const { t } = useTranslation();
|
|
const { organizations } = useOrganizations();
|
|
const { data: proposalsData, isLoading } = useProposalsForOrganization(organization.ID);
|
|
const updateProposalStatus = useUpdateProposalStatus();
|
|
const [activeTab, setActiveTab] = useState('incoming');
|
|
|
|
// Memoize proposals arrays to prevent unnecessary recalculations
|
|
const incoming = useMemo(
|
|
() => (Array.isArray(proposalsData?.incoming) ? proposalsData.incoming : []),
|
|
[proposalsData]
|
|
);
|
|
const outgoing = useMemo(
|
|
() => (Array.isArray(proposalsData?.outgoing) ? proposalsData.outgoing : []),
|
|
[proposalsData]
|
|
);
|
|
|
|
// Memoize findOrg function to prevent recreation
|
|
const findOrg = useCallback(
|
|
(id: string) => {
|
|
if (!id || !organizations || !Array.isArray(organizations)) return undefined;
|
|
return organizations.find((o) => o?.ID === id);
|
|
},
|
|
[organizations]
|
|
);
|
|
|
|
// Memoize status update handler
|
|
const handleStatusUpdate = useCallback(
|
|
(id: string, status: 'pending' | 'accepted' | 'rejected') => {
|
|
updateProposalStatus.mutate({ id, status });
|
|
},
|
|
[updateProposalStatus]
|
|
);
|
|
|
|
const renderProposalList = useCallback(
|
|
(proposals: typeof incoming, type: 'incoming' | 'outgoing') => {
|
|
if (isLoading) {
|
|
return <p className="text-center text-muted-foreground py-8">{t('common.loading')}</p>;
|
|
}
|
|
|
|
if (!Array.isArray(proposals) || proposals.length === 0) {
|
|
return (
|
|
<p className="text-center text-muted-foreground py-8">
|
|
{t('organizationPage.partnershipHub.noProposals')}
|
|
</p>
|
|
);
|
|
}
|
|
return (
|
|
<div className="space-y-3 max-h-96 overflow-y-auto pr-2">
|
|
{proposals
|
|
.filter((p) => p?.id) // Filter out invalid proposals
|
|
.map((p) => {
|
|
const partnerOrg = type === 'incoming' ? findOrg(p.fromOrgId) : findOrg(p.toOrgId);
|
|
if (!partnerOrg) return null;
|
|
return (
|
|
<ProposalCard
|
|
key={p.id}
|
|
proposal={p}
|
|
partner={partnerOrg}
|
|
type={type}
|
|
onStatusUpdate={handleStatusUpdate}
|
|
/>
|
|
);
|
|
})
|
|
.filter(Boolean)}{' '}
|
|
{/* Remove null entries */}
|
|
</div>
|
|
);
|
|
},
|
|
[isLoading, t, findOrg, handleStatusUpdate]
|
|
);
|
|
|
|
return (
|
|
<Tabs value={activeTab} onValueChange={setActiveTab} className="mt-2">
|
|
<TabsList className="w-full grid grid-cols-2">
|
|
<TabsTrigger value="incoming">
|
|
{t('organizationPage.partnershipHub.incoming')} ({incoming.length})
|
|
</TabsTrigger>
|
|
<TabsTrigger value="outgoing">
|
|
{t('organizationPage.partnershipHub.outgoing')} ({outgoing.length})
|
|
</TabsTrigger>
|
|
</TabsList>
|
|
<TabsContent value="incoming">{renderProposalList(incoming, 'incoming')}</TabsContent>
|
|
<TabsContent value="outgoing">{renderProposalList(outgoing, 'outgoing')}</TabsContent>
|
|
</Tabs>
|
|
);
|
|
};
|
|
|
|
export default React.memo(ProposalList);
|