import React, { useState } from "react"; import { FaBullseye, FaPlus, FaEdit, FaTrash, FaDollarSign, FaCalendar, FaArrowUp, FaUser, FaBuilding, } from "react-icons/fa"; import { CrmOpportunity, OpportunityStageEnum } from "../../../types/crm"; import DataTable, { Column } from "../../../components/common/DataTable"; import { mockBusinessParties } from "../../../mocks/mockBusinessParties"; import { mockOpportunities } from "../../../mocks/mockOpportunities"; import OpportunityForm from "./OpportunityForm"; import OpportunityDetails from "./OpportunityDetails"; import { BusinessParty } from "../../../types/common"; import Widget from "../../../components/common/Widget"; import { getOpportunityProbabilityColor, getOpportunityStageColor, getOpportunityStageText, } from "../../../utils/erp"; // Mock data - replace with actual data fetching const OpportunityManagement: React.FC = () => { const [opportunities, setOpportunities] = useState(mockOpportunities); const [customers] = useState(mockBusinessParties); const [searchTerm, setSearchTerm] = useState(""); const [selectedStage, setSelectedStage] = useState< OpportunityStageEnum | "all" >("all"); const [selectedCustomer, setSelectedCustomer] = useState("all"); // Modal states const [isFormOpen, setIsFormOpen] = useState(false); const [isDetailsOpen, setIsDetailsOpen] = useState(false); const [selectedOpportunity, setSelectedOpportunity] = useState(null); const [formMode, setFormMode] = useState<"create" | "edit">("create"); const handleAdd = () => { setSelectedOpportunity(null); setFormMode("create"); setIsFormOpen(true); }; const handleEdit = (opportunity: CrmOpportunity) => { setSelectedOpportunity(opportunity); setFormMode("edit"); setIsFormOpen(true); }; const handleDelete = (id: string) => { if (confirm("Bu fırsatı silmek istediğinizden emin misiniz?")) { setOpportunities((prev) => prev.filter((opp) => opp.id !== id)); } }; const handleViewDetails = (opportunity: CrmOpportunity) => { setSelectedOpportunity(opportunity); setIsDetailsOpen(true); }; const handleSaveOpportunity = (opportunity: CrmOpportunity) => { if (formMode === "create") { setOpportunities((prev) => [...prev, opportunity]); } else { setOpportunities((prev) => prev.map((opp) => (opp.id === opportunity.id ? opportunity : opp)) ); } }; const handleCloseForm = () => { setIsFormOpen(false); setSelectedOpportunity(null); }; const handleCloseDetails = () => { setIsDetailsOpen(false); setSelectedOpportunity(null); }; const handleEditFromDetails = (opportunity: CrmOpportunity) => { setIsDetailsOpen(false); handleEdit(opportunity); }; const filteredOpportunities = opportunities.filter((opportunity) => { if ( searchTerm && !opportunity.title.toLowerCase().includes(searchTerm.toLowerCase()) && !opportunity.description?.toLowerCase().includes(searchTerm.toLowerCase()) ) { return false; } if (selectedStage !== "all" && opportunity.stage !== selectedStage) { return false; } if ( selectedCustomer !== "all" && opportunity.customerId !== selectedCustomer ) { return false; } return true; }); const columns: Column[] = [ { key: "title", header: "Fırsat Başlığı", sortable: true, render: (opportunity: CrmOpportunity) => (
{opportunity.title}
{opportunity.opportunityNumber}
), }, { key: "customer", header: "Müşteri", render: (opportunity: CrmOpportunity) => { const customer = customers.find((c) => c.id === opportunity.customerId); return customer ? (
{customer.name}
) : ( "-" ); }, }, { key: "stage", header: "Aşama", render: (opportunity: CrmOpportunity) => ( {getOpportunityStageText(opportunity.stage)} ), }, { key: "estimatedValue", header: "Tahmini Değer", render: (opportunity: CrmOpportunity) => (
₺{opportunity.estimatedValue.toLocaleString()}
), }, { key: "probability", header: "Olasılık", render: (opportunity: CrmOpportunity) => (
%{opportunity.probability}
), }, { key: "expectedCloseDate", header: "Beklenen Kapanış", render: (opportunity: CrmOpportunity) => (
{new Date(opportunity.expectedCloseDate).toLocaleDateString( "tr-TR" )}
), }, { key: "assignedTo", header: "Sorumlu", render: (opportunity: CrmOpportunity) => (
{opportunity.assigned?.fullName}
), }, { key: "actions", header: "İşlemler", render: (opportunity: CrmOpportunity) => (
), }, ]; // Calculate statistics const totalOpportunities = opportunities.length; const activeOpportunities = opportunities.filter( (o) => o.stage !== OpportunityStageEnum.ClosedWon && o.stage !== OpportunityStageEnum.ClosedLost ).length; const totalValue = opportunities.reduce( (sum, opp) => sum + opp.estimatedValue, 0 ); const averageProbability = opportunities.reduce((sum, opp) => sum + opp.probability, 0) / opportunities.length || 0; // Stage distribution const stageDistribution = Object.values(OpportunityStageEnum).map( (stage) => ({ stage, count: opportunities.filter((o) => o.stage === stage).length, value: opportunities .filter((o) => o.stage === stage) .reduce((sum, o) => sum + o.estimatedValue, 0), }) ); return (
{/* Header */}

Teklif & Fırsat Yönetimi

Satış fırsatları ve teklif takibi

{/* Stats Cards */}
{/* Stage Pipeline */}

Satış Aşamaları

{stageDistribution.map(({ stage, count, value }) => (
{getOpportunityStageText(stage)}
{count}
₺{value.toLocaleString()}
))}
{/* Win Rate Analysis */}

Başarı Oranı Analizi

{ opportunities.filter( (o) => o.stage === OpportunityStageEnum.ClosedWon ).length }

Kazanılan Fırsat

{ opportunities.filter( (o) => o.stage === OpportunityStageEnum.ClosedLost ).length }

Kaybedilen Fırsat

{Math.round( (opportunities.filter( (o) => o.stage === OpportunityStageEnum.ClosedWon ).length / Math.max( opportunities.filter( (o) => o.stage === OpportunityStageEnum.ClosedWon || o.stage === OpportunityStageEnum.ClosedLost ).length, 1 )) * 100 )} %

Kazanma Oranı

{/* Filters */}
setSearchTerm(e.target.value)} className="w-full px-3 py-1.5 text-sm border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500" />
{/* Data Table */}
{filteredOpportunities.length === 0 && (

Fırsat bulunamadı

Arama kriterlerinizi değiştirmeyi deneyin.

)} {/* Modals */}
); }; export default OpportunityManagement;