Files
itinova-budget-si/client/src/pages/TableauBordFinance.tsx

181 lines
8.1 KiB
TypeScript

// TableauBordFinance.tsx — Tableau de bord Finance
// Permet d'accéder au dossier d'analyse budget sur le poste de l'utilisateur
import { useState } from 'react';
import { AppSidebar } from '../components/AppSidebar';
import {
LayoutDashboard,
FolderOpen,
Copy,
CheckCheck,
ExternalLink,
Info,
FolderSearch,
} from 'lucide-react';
const DEFAULT_PATH = 'C:\\Users\\o.pareige\\OneDrive - ITINOVA\\@ITINOVA\\Pilotage\\Budget\\Analyse budget de mon poste';
export default function TableauBordFinance() {
const [sidebarCollapsed, setSidebarCollapsed] = useState(false);
const [copied, setCopied] = useState(false);
const [customPath, setCustomPath] = useState(DEFAULT_PATH);
const [editingPath, setEditingPath] = useState(false);
const handleCopy = async () => {
try {
await navigator.clipboard.writeText(customPath);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
} catch {
// fallback
const el = document.createElement('textarea');
el.value = customPath;
document.body.appendChild(el);
el.select();
document.execCommand('copy');
document.body.removeChild(el);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
}
};
// Construire l'URL file:// pour tenter l'ouverture directe
// Remplace les backslashes par des slashes et encode les espaces
const fileUrl = 'file:///' + customPath.replace(/\\/g, '/');
return (
<div className="min-h-screen flex bg-background">
<AppSidebar collapsed={sidebarCollapsed} onToggle={() => setSidebarCollapsed(c => !c)} />
<main className="flex-1 flex flex-col min-w-0 overflow-hidden">
{/* En-tête */}
<header className="bg-card border-b border-border px-6 py-4 flex-shrink-0">
<div className="flex items-center gap-3">
<div className="w-9 h-9 rounded-lg bg-blue-500/20 flex items-center justify-center">
<LayoutDashboard className="w-5 h-5 text-blue-500" />
</div>
<div>
<h1 className="text-xl font-bold text-foreground" style={{ fontFamily: 'Sora, sans-serif' }}>
Tableau de bord Finance
</h1>
<p className="text-sm text-muted-foreground mt-0.5">
Accès aux dossiers d'analyse budgétaire
</p>
</div>
</div>
</header>
{/* Contenu */}
<div className="flex-1 overflow-y-auto px-6 py-6">
<div className="max-w-2xl mx-auto space-y-6">
{/* Carte principale — dossier OneDrive */}
<div className="bg-card border border-border rounded-xl shadow-sm overflow-hidden">
<div className="px-5 py-4 border-b border-border flex items-center gap-3">
<FolderSearch className="w-5 h-5 text-blue-500 flex-shrink-0" />
<div>
<h2 className="text-sm font-semibold text-foreground">Analyse budget de mon poste</h2>
<p className="text-xs text-muted-foreground mt-0.5">Dossier OneDrive — Pilotage Budget</p>
</div>
</div>
<div className="px-5 py-4 space-y-4">
{/* Chemin du dossier */}
<div>
<label className="text-xs font-medium text-muted-foreground uppercase tracking-wide block mb-1.5">
Chemin du dossier
</label>
{editingPath ? (
<div className="flex gap-2">
<input
type="text"
value={customPath}
onChange={e => setCustomPath(e.target.value)}
className="flex-1 text-sm font-mono bg-muted/50 border border-border rounded-lg px-3 py-2 focus:outline-none focus:ring-2 focus:ring-primary/30 focus:border-primary"
autoFocus
/>
<button
onClick={() => setEditingPath(false)}
className="px-3 py-2 text-xs font-medium bg-primary text-primary-foreground rounded-lg hover:bg-primary/90 transition-colors"
>
OK
</button>
</div>
) : (
<div
className="flex items-center gap-2 bg-muted/40 border border-border rounded-lg px-3 py-2.5 cursor-pointer group hover:bg-muted/70 transition-colors"
onClick={() => setEditingPath(true)}
title="Cliquer pour modifier le chemin"
>
<FolderOpen className="w-4 h-4 text-amber-500 flex-shrink-0" />
<span className="flex-1 text-xs font-mono text-foreground/80 truncate">{customPath}</span>
<span className="text-[10px] text-muted-foreground opacity-0 group-hover:opacity-100 transition-opacity">modifier</span>
</div>
)}
</div>
{/* Actions */}
<div className="flex flex-col sm:flex-row gap-3">
{/* Bouton copier le chemin */}
<button
onClick={handleCopy}
className={`flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium transition-all duration-150 flex-1 ${
copied
? 'bg-emerald-500/20 text-emerald-600 border border-emerald-500/30'
: 'bg-muted/50 border border-border text-foreground hover:bg-muted hover:border-border/80'
}`}
>
{copied ? (
<>
<CheckCheck className="w-4 h-4" />
Chemin copié !
</>
) : (
<>
<Copy className="w-4 h-4" />
Copier le chemin
</>
)}
</button>
{/* Bouton ouvrir dans l'explorateur */}
<a
href={fileUrl}
className="flex items-center justify-center gap-2 px-4 py-2.5 rounded-lg text-sm font-medium bg-blue-500/15 border border-blue-500/30 text-blue-600 hover:bg-blue-500/25 transition-all duration-150 flex-1"
title="Tenter d'ouvrir le dossier (selon le navigateur)"
>
<ExternalLink className="w-4 h-4" />
Ouvrir le dossier
</a>
</div>
{/* Instructions */}
<div className="bg-amber-50 dark:bg-amber-950/30 border border-amber-200 dark:border-amber-800/50 rounded-lg px-4 py-3 flex gap-3">
<Info className="w-4 h-4 text-amber-600 dark:text-amber-400 flex-shrink-0 mt-0.5" />
<div className="text-xs text-amber-800 dark:text-amber-300 space-y-1">
<p className="font-semibold">Comment accéder au dossier</p>
<p>
<strong>Option 1 :</strong> Cliquez sur <em>"Ouvrir le dossier"</em> fonctionne sur certains navigateurs (Edge, Firefox) si le dossier est synchronisé localement.
</p>
<p>
<strong>Option 2 :</strong> Copiez le chemin puis collez-le dans la barre d'adresse de l'Explorateur Windows (<kbd className="bg-amber-100 dark:bg-amber-900 px-1 rounded">Win + E</kbd>, puis collez dans la barre d'adresse).
</p>
<p>
<strong>Option 3 :</strong> Ouvrez directement OneDrive et naviguez vers <em>@ITINOVA Pilotage Budget Analyse budget de mon poste</em>.
</p>
</div>
</div>
</div>
</div>
{/* Note de personnalisation */}
<p className="text-xs text-muted-foreground text-center">
Le chemin peut être modifié en cliquant dessus il sera conservé pour cette session.
</p>
</div>
</div>
</main>
</div>
);
}