S SmartDocs
Série: Golden-Hour-backend-layer-2 typescript 257 lignes · Mis à jour 2026-02-22

InvoiceManagement.tsx

Golden-Hour-backend-layer-2/pages/InvoiceManagement.tsx


import React, { useState, useRef } from 'react';

type InvoiceType = 'Company Invoices' | 'Customer Invoices' | 'Supplier Invoices' | 'Procurement Invoices' | 'Settings';

interface InvoiceRecord {
  id: string;
  entity: string;
  amount: string;
  date: string;
  status: 'Paid' | 'Overdue' | 'Draft';
  type: InvoiceType;
}

interface InvoiceManagementProps {
  view?: InvoiceType;
}

const ScanModal: React.FC<{ isOpen: boolean; onClose: () => void }> = ({ isOpen, onClose }) => {
  const [isScanning, setIsScanning] = useState(false);
  const [scanProgress, setScanProgress] = useState(0);
  const fileInputRef = useRef<HTMLInputElement>(null);

  if (!isOpen) return null;

  const handleFileSelect = () => {
    setIsScanning(true);
    let progress = 0;
    const interval = setInterval(() => {
      progress += 5;
      setScanProgress(progress);
      if (progress >= 100) {
        clearInterval(interval);
        setTimeout(() => {
          setIsScanning(false);
          setScanProgress(0);
          onClose();
        }, 1000);
      }
    }, 100);
  };

  return (
    <div className="fixed inset-0 z-[100] flex items-center justify-center p-8 bg-slate-900/60 backdrop-blur-xl fade-in-section">
      <div className="bg-white rounded-[3.5rem] gallery-shadow w-full max-w-xl border border-[#c5a059]/20 flex flex-col relative overflow-hidden">
        <div className="absolute top-0 left-0 right-0 h-1.5 bg-[#c5a059]"></div>
        
        <div className="p-16 text-center space-y-10">
          <div className="mx-auto w-20 h-20 rounded-full border border-[#c5a059]/10 flex items-center justify-center relative">
             <i className={`fa-solid ${isScanning ? 'fa-fingerprint animate-pulse text-[#c5a059]' : 'fa-file-invoice text-slate-200'} text-3xl`}></i>
          </div>
          
          <div>
            <h3 className="font-serif italic text-4xl text-slate-900">Archive Scan Protocol</h3>
            <p className="text-[9px] font-bold uppercase tracking-[0.4em] text-slate-400 mt-3">Registering Physical Assets to Ledger</p>
          </div>

          <div className="relative">
            {isScanning ? (
              <div className="space-y-6">
                <div className="h-1 w-full bg-slate-100 rounded-full overflow-hidden relative">
                   <div className="absolute top-0 bottom-0 left-0 bg-[#c5a059] transition-all duration-300" style={{ width: `${scanProgress}%` }}></div>
                </div>
                <p className="text-[8px] font-black uppercase tracking-[0.3em] text-[#c5a059] animate-pulse italic font-serif">Harvesting OCR Data Points — {scanProgress}%</p>
              </div>
            ) : (
              <div 
                onClick={() => fileInputRef.current?.click()}
                className="p-12 rounded-[2.5rem] bg-[#fdfcf9] border-2 border-dashed border-[#c5a059]/10 hover:border-[#c5a059]/40 transition-all cursor-pointer group"
              >
                <i className="fa-solid fa-cloud-arrow-up text-3xl text-slate-200 mb-6 group-hover:text-[#c5a059] transition-colors"></i>
                <p className="text-[10px] font-bold uppercase tracking-[0.3em] text-slate-400">Upload or Capture Ledger Image</p>
                <p className="text-[8px] font-serif italic text-slate-300 mt-3">Photographs, Scans, or Documents (PDF, JPG)</p>
                <input ref={fileInputRef} type="file" className="hidden" onChange={handleFileSelect} />
              </div>
            )}
          </div>

          <div className="grid grid-cols-2 gap-4">
             <button onClick={onClose} className="px-8 py-4 rounded-full text-[9px] font-black uppercase tracking-[0.3em] text-slate-300 hover:text-slate-900 transition-all">Abort Protocol</button>
             <button disabled={isScanning} className="bg-black text-white px-8 py-4 rounded-full text-[9px] font-black uppercase tracking-[0.3em] hover:bg-[#c5a059] transition-all disabled:opacity-20">Manual Registry</button>
          </div>
        </div>
      </div>
    </div>
  );
};

const InvoiceManagement: React.FC<InvoiceManagementProps> = ({ view = 'Customer Invoices' }) => {
  const [isScanOpen, setIsScanOpen] = useState(false);

  const invoices: InvoiceRecord[] = [
    { id: 'INV-GH-401', entity: 'Private Client: James Bond', amount: '€4,200', date: '2025-05-12', status: 'Paid', type: 'Customer Invoices' },
    { id: 'INV-GH-402', entity: 'EcoClean Provence Co.', amount: '€1,150', date: '2025-05-14', status: 'Overdue', type: 'Supplier Invoices' },
    { id: 'INV-GH-403', entity: 'Atelier Office Supplies', amount: '€450', date: '2025-05-15', status: 'Draft', type: 'Procurement Invoices' },
    { id: 'INV-GH-404', entity: 'Internal: Marketing Dept', amount: '€2,400', date: '2025-05-10', status: 'Paid', type: 'Company Invoices' },
  ];

  const filteredInvoices = invoices.filter(inv => inv.type === view);

  const viewMetadata: Record<InvoiceType, { title: string; sub: string }> = {
    'Company Invoices': { title: 'Corporate Ledger', sub: 'Internal Asset & Expense Registry' },
    'Customer Invoices': { title: 'Acquisition Archive', sub: 'Client Transactional Records' },
    'Supplier Invoices': { title: 'Supply Chain Ledger', sub: 'Provisioning & Logistics Billing' },
    'Procurement Invoices': { title: 'Procurement Dossier', sub: 'Atelier Acquisitions & Inventory' },
    'Settings': { title: 'Fiscal Configuration', sub: 'Taxation & Registry Standards' }
  };

  const renderInvoiceTable = () => (
    <div className="bg-white rounded-[2.5rem] border border-[#c5a059]/10 shadow-sm overflow-hidden fade-in-section">
      <div className="overflow-x-auto">
        <table className="w-full text-left">
          <thead className="bg-[#fdfcf9] border-b border-[#c5a059]/5 text-[7px] font-bold uppercase tracking-widest text-slate-300 italic font-serif">
            <tr>
              <th className="px-10 py-6">Ref. Registry ID</th>
              <th className="px-10 py-6">Identity / Entity</th>
              <th className="px-10 py-6">Fiscal Value</th>
              <th className="px-10 py-6">Date d'édition</th>
              <th className="px-10 py-6">Current State</th>
              <th className="px-10 py-6 text-center">Protocol</th>
            </tr>
          </thead>
          <tbody className="divide-y divide-[#c5a059]/5">
            {filteredInvoices.length > 0 ? filteredInvoices.map((inv) => (
              <tr key={inv.id} className="hover:bg-[#fdfcf9]/50 group transition-all duration-700">
                <td className="px-10 py-8 serif-numeral text-sm text-[#c5a059]">{inv.id}</td>
                <td className="px-10 py-8">
                   <p className="font-serif italic text-lg text-slate-800 leading-tight">{inv.entity}</p>
                </td>
                <td className="px-10 py-8 font-serif italic text-xl text-slate-900 tracking-tighter">{inv.amount}</td>
                <td className="px-10 py-8 text-[9px] font-bold uppercase tracking-widest text-slate-400 font-serif italic">{inv.date}</td>
                <td className="px-10 py-8">
                  <span className={`text-[7px] font-black uppercase px-3 py-1 rounded-full border tracking-widest ${
                    inv.status === 'Paid' ? 'border-emerald-100 text-emerald-600 bg-emerald-50/5' : 
                    inv.status === 'Overdue' ? 'border-rose-100 text-rose-600 bg-rose-50/5' : 'border-slate-100 text-slate-400'
                  }`}>
                    {inv.status}
                  </span>
                </td>
                <td className="px-10 py-8">
                  <div className="flex justify-center space-x-6 opacity-0 group-hover:opacity-100 transition-all duration-700">
                     <button className="text-slate-200 hover:text-[#c5a059] transition-all"><i className="fa-solid fa-eye text-xs"></i></button>
                     <button className="text-slate-200 hover:text-[#c5a059] transition-all"><i className="fa-solid fa-download text-xs"></i></button>
                     <button className="text-slate-200 hover:text-rose-600 transition-all"><i className="fa-solid fa-ellipsis-vertical text-xs"></i></button>
                  </div>
                </td>
              </tr>
            )) : (
              <tr>
                <td colSpan={6} className="px-10 py-32 text-center text-slate-200 font-serif italic text-2xl opacity-40">
                  No records found in this category archive.
                </td>
              </tr>
            )}
          </tbody>
        </table>
      </div>
    </div>
  );

  const renderSettingsView = () => (
    <div className="grid grid-cols-1 md:grid-cols-2 gap-10 fade-in-section">
      <div className="bg-white p-12 rounded-[2.5rem] border border-[#c5a059]/10 gallery-shadow">
         <h3 className="font-serif italic text-3xl text-slate-900 mb-8">Statutory Logic</h3>
         <div className="space-y-6">
            <div className="p-6 rounded-2xl bg-[#fdfcf9] border border-[#c5a059]/5 flex justify-between items-center">
               <div>
                  <p className="text-[10px] font-black uppercase tracking-widest text-slate-800">Standard VAT Protocol</p>
                  <p className="text-[8px] font-serif italic text-slate-400 mt-1">Applied to all customer transactions: 21%</p>
               </div>
               <button className="text-[8px] font-black text-[#c5a059] uppercase tracking-widest border border-[#c5a059]/10 px-4 py-2 rounded-full">Adjust</button>
            </div>
            <div className="p-6 rounded-2xl bg-[#fdfcf9] border border-[#c5a059]/5 flex justify-between items-center">
               <div>
                  <p className="text-[10px] font-black uppercase tracking-widest text-slate-800">Currency Formatting</p>
                  <p className="text-[8px] font-serif italic text-slate-400 mt-1">EUR (€) - Postfix format</p>
               </div>
               <button className="text-[8px] font-black text-[#c5a059] uppercase tracking-widest border border-[#c5a059]/10 px-4 py-2 rounded-full">Change</button>
            </div>
         </div>
      </div>
      <div className="bg-[#1a1a1a] p-12 rounded-[2.5rem] gallery-shadow text-white relative overflow-hidden">
         <div className="absolute top-0 right-0 w-32 h-32 bg-[#c5a059]/10 rounded-full blur-3xl -mr-16 -mt-16"></div>
         <h3 className="font-serif italic text-3xl mb-8 relative z-10">Export Protocol</h3>
         <p className="text-slate-400 text-sm italic font-serif leading-relaxed mb-10 relative z-10">
           Configure the automated delivery of financial ledgers to your accounting bureau. 
           Supported formats: CSV, XML, PDF.
         </p>
         <button className="w-full py-5 bg-white text-black rounded-full text-[9px] font-black uppercase tracking-[0.4em] hover:bg-[#c5a059] hover:text-white transition-all">Setup Scheduled Export</button>
      </div>
    </div>
  );

  return (
    <div className="relative pb-32">
      <div className="space-y-16 fade-in-section">
        {/* Dynamic Header */}
        <div className="flex flex-col md:flex-row md:items-end justify-between border-b border-[#c5a059]/10 pb-12 gap-8">
          <div>
            <h2 className="text-4xl font-serif italic text-slate-900 tracking-tight">
              {viewMetadata[view].title}
            </h2>
            <p className="text-[10px] font-black uppercase tracking-[0.5em] text-[#c5a059] mt-3 font-serif italic">
              {viewMetadata[view].sub}
            </p>
          </div>
          
          <div className="flex items-center space-x-6">
            <button 
              onClick={() => setIsScanOpen(true)}
              className="bg-[#fdfcf9] border border-[#c5a059]/20 text-[#c5a059] px-10 py-3.5 rounded-full text-[9px] font-black uppercase tracking-[0.3em] hover:bg-[#c5a059] hover:text-white transition-all shadow-xl hover:scale-105 active:scale-95 flex items-center"
            >
              <i className="fa-solid fa-maximize mr-4"></i> Register via Scan
            </button>
            <button className="bg-black text-white px-10 py-3.5 rounded-full text-[9px] font-black uppercase tracking-[0.3em] hover:bg-[#c5a059] transition-all shadow-xl">
              <i className="fa-solid fa-plus mr-3"></i> Manual Registry
            </button>
          </div>
        </div>

        {/* Financial Analytics Summary */}
        <div className="grid grid-cols-1 md:grid-cols-3 gap-10">
          {[
            { label: 'Cumulative Outstanding', value: '€12,450', sub: '08 Ledgers pending', color: 'text-slate-900' },
            { label: 'Secured This Cycle', value: '€84,200', sub: '142 Transactions verified', color: 'text-[#c5a059]' },
            { label: 'Total Overdue', value: '€1,150', sub: 'High Priority Protocol', color: 'text-rose-600' },
          ].map((stat, idx) => (
            <div key={idx} className="bg-white p-10 rounded-[2.5rem] border border-[#c5a059]/10 gallery-shadow">
               <span className="text-[8px] font-black uppercase tracking-[0.3em] text-slate-300 block mb-3">{stat.label}</span>
               <h3 className={`font-serif italic text-4xl leading-none tracking-tighter ${stat.color}`}>{stat.value}</h3>
               <p className="text-[8px] font-serif italic text-slate-400 mt-4 uppercase tracking-widest">{stat.sub}</p>
            </div>
          ))}
        </div>

        {view === 'Settings' ? renderSettingsView() : renderInvoiceTable()}
      </div>

      <ScanModal isOpen={isScanOpen} onClose={() => setIsScanOpen(false)} />

      {/* Persistent Protocol Bar */}
      <div className="fixed bottom-12 left-1/2 -translate-x-1/2 bg-white/90 backdrop-blur-md border border-[#c5a059]/20 px-10 py-5 rounded-full gallery-shadow flex items-center space-x-12 z-50 transition-all hover:border-[#c5a059]/40 group">
        <button className="flex items-center space-x-3 text-slate-400 hover:text-slate-900 transition-all">
          <i className="fa-solid fa-print text-[9px] text-[#c5a059]"></i>
          <span className="text-[8px] font-bold uppercase tracking-[0.3em]">Batch Print</span>
        </button>
        <div className="w-[0.5px] h-4 bg-[#c5a059]/20"></div>
        <button className="flex items-center space-x-3 text-slate-400 hover:text-slate-900 transition-all">
          <i className="fa-solid fa-magnifying-glass text-[9px] text-[#c5a059]"></i>
          <span className="text-[8px] font-bold uppercase tracking-[0.3em]">Audit Query</span>
        </button>
      </div>
    </div>
  );
};

export default InvoiceManagement;

Articles liés