SPB Git

spb/vquant Public MIT

VibeQuant — AI-powered institutional-grade financial intelligence platform.

TypeScript 84.3% Python 11.7% JavaScript 1.6% CSS 1.5% HTML 0.7%
6.4 KB · 218 lines tsx
Raw Blame History
1/*2 * =============================================================================3 *  VibeQuant (vquant) — AI-Powered Financial Intelligence Platform4 * -----------------------------------------------------------------------------5 *  File:      client/src/components/chat/download-buttons.tsx6 *7 *  Author:    Simon-Pierre Boucher8 *  Contact:   contact@spboucher.ai9 *  Website:   https://www.spboucher.ai10 *  Demo:      https://www.vquant.ai11 *  License:   MIT (see LICENSE)12 *13 *  Copyright © 2026 Simon-Pierre Boucher. All rights reserved.14 * =============================================================================15 */1617import { FileText, FileDown, FileType, Loader2, Presentation } from "lucide-react";18import { Button } from "@/components/ui/button";19import { useState } from "react";20import { useToast } from "@/hooks/use-toast";21import { useLocation } from "wouter";2223interface DownloadButtonsProps {24  question: string;25  answer: string;26  contentRef?: React.RefObject<HTMLElement>;27  figureUrls?: string[];28}2930export function DownloadButtons({ question, answer, contentRef, figureUrls = [] }: DownloadButtonsProps) {31  const [isGeneratingPDF, setIsGeneratingPDF] = useState(false);32  const [isGeneratingDOCX, setIsGeneratingDOCX] = useState(false);33  const { toast } = useToast();34  const [, setLocation] = useLocation();3536  const handleDownloadMarkdown = () => {37    const content = answer;38    const blob = new Blob([content], { type: 'text/markdown' });39    const url = URL.createObjectURL(blob);40    const a = document.createElement('a');41    a.href = url;42    a.download = `vibequant-${Date.now()}.md`;43    document.body.appendChild(a);44    a.click();45    document.body.removeChild(a);46    URL.revokeObjectURL(url);4748    toast({49      title: "Téléchargement réussi",50      description: "Le fichier Markdown a été téléchargé avec succès.",51    });52  };5354  const handleDownloadPDF = async () => {55    setIsGeneratingPDF(true);5657    try {58      const response = await fetch('/api/generate-pdf', {59        method: 'POST',60        headers: {61          'Content-Type': 'application/json',62        },63        body: JSON.stringify({64          question,65          answer66        }),67      });6869      if (!response.ok) {70        throw new Error('Failed to generate PDF');71      }7273      const blob = await response.blob();74      const url = URL.createObjectURL(blob);75      const a = document.createElement('a');76      a.href = url;77      a.download = `vibequant-${Date.now()}.pdf`;78      document.body.appendChild(a);79      a.click();80      document.body.removeChild(a);81      URL.revokeObjectURL(url);8283      toast({84        title: "PDF généré avec succès",85        description: "Le rapport PDF a été téléchargé.",86      });87    } catch (error) {88      console.error('Error generating PDF:', error);89      toast({90        title: "Erreur de génération",91        description: "Une erreur s'est produite lors de la génération du PDF. Veuillez réessayer.",92        variant: "destructive",93      });94    } finally {95      setIsGeneratingPDF(false);96    }97  };9899  const handleDownloadDOCX = async () => {100    setIsGeneratingDOCX(true);101102    try {103      const response = await fetch('/api/generate-docx', {104        method: 'POST',105        headers: {106          'Content-Type': 'application/json',107        },108        body: JSON.stringify({109          question,110          answer111        }),112      });113114      if (!response.ok) {115        throw new Error('Failed to generate Word document');116      }117118      const blob = await response.blob();119      const url = URL.createObjectURL(blob);120      const a = document.createElement('a');121      a.href = url;122      a.download = `vibequant-${Date.now()}.docx`;123      document.body.appendChild(a);124      a.click();125      document.body.removeChild(a);126      URL.revokeObjectURL(url);127128      toast({129        title: "Word généré avec succès",130        description: "Le document Word a été téléchargé.",131      });132    } catch (error) {133      console.error('Error generating DOCX:', error);134      toast({135        title: "Erreur de génération",136        description: "Une erreur s'est produite lors de la génération du Word. Veuillez réessayer.",137        variant: "destructive",138      });139    } finally {140      setIsGeneratingDOCX(false);141    }142  };143144  const handleConvertToSlides = () => {145    // Store content in sessionStorage to pass to slides generator page146    sessionStorage.setItem('slidesContent', JSON.stringify({ question, answer, figureUrls }));147    setLocation('/slides-generator');148149    toast({150      title: "Redirection...",151      description: "Ouverture du générateur de slides",152    });153  };154155  return (156    <>157      <Button158        variant="outline"159        size="sm"160        onClick={handleDownloadMarkdown}161        className="gap-2 hover:bg-muted transition-colors"162        disabled={isGeneratingPDF}163      >164        <FileText className="w-4 h-4" />165        <span className="hidden sm:inline">Télécharger MD</span>166      </Button>167      <Button168        variant="outline"169        size="sm"170        onClick={handleDownloadPDF}171        className="gap-2 hover:bg-muted transition-colors"172        disabled={isGeneratingPDF}173      >174        {isGeneratingPDF ? (175          <>176            <Loader2 className="w-4 h-4 animate-spin" />177            <span className="hidden sm:inline">Génération...</span>178          </>179        ) : (180          <>181            <FileDown className="w-4 h-4" />182            <span className="hidden sm:inline">Télécharger PDF</span>183          </>184        )}185      </Button>186      <Button187        variant="outline"188        size="sm"189        onClick={handleDownloadDOCX}190        className="gap-2 hover:bg-muted transition-colors"191        disabled={isGeneratingDOCX}192      >193        {isGeneratingDOCX ? (194          <>195            <Loader2 className="w-4 h-4 animate-spin" />196            <span className="hidden sm:inline">Génération...</span>197          </>198        ) : (199          <>200            <FileType className="w-4 h-4" />201            <span className="hidden sm:inline">Télécharger Word</span>202          </>203        )}204      </Button>205      <Button206        variant="outline"207        size="sm"208        onClick={handleConvertToSlides}209        className="gap-2 hover:bg-muted transition-colors"210        disabled={isGeneratingPDF || isGeneratingDOCX || !question || !answer}211      >212        <Presentation className="w-4 h-4" />213        <span className="hidden sm:inline">Convertir en Slides</span>214      </Button>215    </>216  );217}218