Sage100/src/pages/crm/OpportunitiesPage.jsx
2026-01-20 11:06:26 +03:00

115 lines
4 KiB
JavaScript

import React, { useState } from 'react';
import { Helmet } from 'react-helmet';
import { Plus } from 'lucide-react';
import KanbanBoard from '@/components/KanbanBoard';
import PrimaryButton from '@/components/PrimaryButton';
import SmartForm from '@/components/SmartForm';
import FormModal from '@/components/FormModal';
import { mockOpportunities } from '@/data/mockData';
import { z } from 'zod';
import { toast } from '@/components/ui/use-toast';
const opportunitySchema = z.object({
name: z.string().min(3, "Le nom est requis"),
clientId: z.string().min(1, "Le client est requis"),
amount: z.string().min(1, "Le montant est requis"),
stage: z.string().min(1, "L'étape est requise"),
probability: z.string().optional(),
closeDate: z.string().min(1, "Date requise"),
description: z.string().optional()
});
const OpportunitiesPage = () => {
const [items, setItems] = useState(mockOpportunities);
const [isModalOpen, setIsModalOpen] = useState(false);
const columns = [
{ id: 'new', title: 'Nouveau' },
{ id: 'qualification', title: 'Qualification' },
{ id: 'proposal', title: 'Proposition' },
{ id: 'negotiation', title: 'Négociation' },
{ id: 'won', title: 'Gagné' },
{ id: 'lost', title: 'Perdu' }
];
const handleDragEnd = (result) => {
if (!result.destination) return;
const { source, destination, draggableId } = result;
if (source.droppableId === destination.droppableId) return;
const newItems = items.map(item =>
item.id.toString() === draggableId
? { ...item, stage: destination.droppableId }
: item
);
setItems(newItems);
toast({
title: "Étape mise à jour",
description: "L'opportunité a changé d'étape avec succès.",
});
};
const handleCreate = (data) => {
// Simulation
const newOpp = {
id: Math.random(),
...data,
amount: parseFloat(data.amount),
probability: parseInt(data.probability) || 0,
client: "Client Simulé", // In real app, lookup client name
owner: "Jean Dupont"
};
setItems([...items, newOpp]);
setIsModalOpen(false);
toast({ title: "Opportunité créée", description: `${data.name} a été ajouté au pipeline.` });
};
return (
<>
<Helmet>
<title>Pipeline - Bijou ERP</title>
</Helmet>
<div className="h-[calc(100vh-120px)] flex flex-col">
<div className="flex justify-between items-center mb-6">
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">Pipeline</h1>
<PrimaryButton icon={Plus} onClick={() => setIsModalOpen(true)}>Nouvelle opportunité</PrimaryButton>
</div>
<div className="flex-1 overflow-hidden">
<KanbanBoard
columns={columns}
items={items}
onDragEnd={handleDragEnd}
onItemClick={(item) => toast({ title: "Détail", description: `Ouverture de ${item.name}` })}
/>
</div>
</div>
<FormModal
isOpen={isModalOpen}
onClose={() => setIsModalOpen(false)}
title="Nouvelle opportunité"
>
<SmartForm
schema={opportunitySchema}
onSubmit={handleCreate}
onCancel={() => setIsModalOpen(false)}
fields={[
{ name: 'name', label: 'Nom de l\'opportunité', placeholder: 'Ex: Contrat annuel 2025' },
{ name: 'clientId', label: 'Client', type: 'select', options: [{ value: '1', label: 'ACME Corp' }, { value: '2', label: 'TechStart' }] },
{ name: 'amount', label: 'Montant (€)', type: 'number' },
{ name: 'stage', label: 'Étape', type: 'select', options: columns.map(c => ({ value: c.id, label: c.title })) },
{ name: 'probability', label: 'Probabilité (%)', type: 'number' },
{ name: 'closeDate', label: 'Date de clôture estimée', type: 'date' },
{ name: 'description', label: 'Description', type: 'textarea', fullWidth: true },
]}
/>
</FormModal>
</>
);
};
export default OpportunitiesPage;