@wakastellar/ui 2.4.0 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/dist/blocks/antivirus-dashboard/index.d.ts +44 -0
  2. package/dist/blocks/clamav-service-status/index.d.ts +35 -0
  3. package/dist/blocks/file-scan-uploader/index.d.ts +29 -0
  4. package/dist/blocks/index.d.ts +18 -9
  5. package/dist/blocks/quarantine-manager/index.d.ts +27 -0
  6. package/dist/blocks/scan-history-log/index.d.ts +28 -0
  7. package/dist/blocks/scan-policy-editor/index.d.ts +27 -0
  8. package/dist/blocks/scan-report-generator/index.d.ts +47 -0
  9. package/dist/blocks/signature-database-manager/index.d.ts +39 -0
  10. package/dist/blocks/threat-alert-banner/index.d.ts +26 -0
  11. package/dist/components/index.d.ts +4 -4
  12. package/dist/components/waka-signature-pad/index.d.ts +1 -1
  13. package/dist/exceljs.min-BcLLX0PC.js +29 -0
  14. package/dist/exceljs.min-KOayaaQ4.mjs +23013 -0
  15. package/dist/export.cjs.js +1 -1
  16. package/dist/export.d.ts +2 -2
  17. package/dist/export.es.js +1 -1
  18. package/dist/index.cjs.js +136 -136
  19. package/dist/index.es.js +29978 -27215
  20. package/dist/stories/Button.stories.d.ts +1 -1
  21. package/dist/stories/Header.stories.d.ts +1 -1
  22. package/dist/stories/Page.stories.d.ts +1 -1
  23. package/dist/useDataTableImport-COVnvslz.js +9 -0
  24. package/dist/useDataTableImport-DAlxBY8w.mjs +237 -0
  25. package/dist/utils/index.d.ts +1 -0
  26. package/dist/utils/logger.d.ts +9 -0
  27. package/package.json +6 -5
  28. package/src/blocks/antivirus-dashboard/AntivirusDashboard.stories.tsx +291 -0
  29. package/src/blocks/antivirus-dashboard/index.tsx +525 -0
  30. package/src/blocks/clamav-service-status/ClamAVServiceStatus.stories.tsx +195 -0
  31. package/src/blocks/clamav-service-status/index.tsx +370 -0
  32. package/src/blocks/file-scan-uploader/FileScanUploader.stories.tsx +257 -0
  33. package/src/blocks/file-scan-uploader/index.tsx +311 -0
  34. package/src/blocks/index.ts +163 -11
  35. package/src/blocks/quarantine-manager/QuarantineManager.stories.tsx +209 -0
  36. package/src/blocks/quarantine-manager/index.tsx +435 -0
  37. package/src/blocks/scan-history-log/ScanHistoryLog.stories.tsx +231 -0
  38. package/src/blocks/scan-history-log/index.tsx +406 -0
  39. package/src/blocks/scan-policy-editor/ScanPolicyEditor.stories.tsx +106 -0
  40. package/src/blocks/scan-policy-editor/index.tsx +418 -0
  41. package/src/blocks/scan-report-generator/ScanReportGenerator.stories.tsx +232 -0
  42. package/src/blocks/scan-report-generator/index.tsx +612 -0
  43. package/src/blocks/sidebar/index.tsx +2 -1
  44. package/src/blocks/signature-database-manager/SignatureDatabaseManager.stories.tsx +279 -0
  45. package/src/blocks/signature-database-manager/index.tsx +470 -0
  46. package/src/blocks/theme-creator-block/index.tsx +16 -2
  47. package/src/blocks/threat-alert-banner/ThreatAlertBanner.stories.tsx +152 -0
  48. package/src/blocks/threat-alert-banner/index.tsx +320 -0
  49. package/src/components/DataTable/DataTable.stories.tsx +203 -0
  50. package/src/components/DataTable/hooks/useDataTableExport.ts +38 -31
  51. package/src/components/DataTable/hooks/useDataTableImport.ts +31 -20
  52. package/src/components/error-boundary/ErrorBoundary.stories.tsx +125 -0
  53. package/src/components/index.ts +45 -4
  54. package/src/components/language-selector/LanguageSelector.stories.tsx +112 -0
  55. package/src/components/theme-selector/ThemeSelector.stories.tsx +77 -0
  56. package/src/components/toaster/Toaster.stories.tsx +67 -0
  57. package/src/components/waka-activity-feed/WakaActivityFeed.stories.tsx +116 -0
  58. package/src/components/waka-ad-banner/WakaAdBanner.stories.tsx +102 -0
  59. package/src/components/waka-ad-fallback/WakaAdFallback.stories.tsx +117 -0
  60. package/src/components/waka-ad-inline/WakaAdInline.stories.tsx +105 -0
  61. package/src/components/waka-ad-interstitial/WakaAdInterstitial.stories.tsx +92 -0
  62. package/src/components/waka-ad-placeholder/WakaAdPlaceholder.stories.tsx +89 -0
  63. package/src/components/waka-ad-provider/WakaAdProvider.stories.tsx +110 -0
  64. package/src/components/waka-ad-sidebar/WakaAdSidebar.stories.tsx +89 -0
  65. package/src/components/waka-ad-sidebar/index.tsx +3 -2
  66. package/src/components/waka-ad-sticky-footer/WakaAdStickyFooter.stories.tsx +88 -0
  67. package/src/components/waka-address-autocomplete/WakaAddressAutocomplete.stories.tsx +46 -0
  68. package/src/components/waka-admincrumb/WakaAdmincrumb.stories.tsx +166 -0
  69. package/src/components/waka-alert-panel/WakaAlertPanel.stories.tsx +45 -0
  70. package/src/components/waka-alert-stack/WakaAlertStack.stories.tsx +62 -0
  71. package/src/components/waka-allocation-matrix/WakaAllocationMatrix.stories.tsx +68 -0
  72. package/src/components/waka-approval-chain/WakaApprovalChain.stories.tsx +63 -0
  73. package/src/components/waka-audit-log/WakaAuditLog.stories.tsx +73 -0
  74. package/src/components/waka-autocomplete/WakaAutocomplete.stories.tsx +132 -172
  75. package/src/components/waka-biometric-prompt/WakaBiometricPrompt.stories.tsx +48 -0
  76. package/src/components/waka-breadcrumb/WakaBreadcrumb.stories.tsx +74 -191
  77. package/src/components/waka-breadcrumb-path/WakaBreadcrumbPath.stories.tsx +40 -0
  78. package/src/components/waka-budget-burn/WakaBudgetBurn.stories.tsx +86 -0
  79. package/src/components/waka-capacity-planner/WakaCapacityPlanner.stories.tsx +273 -0
  80. package/src/components/waka-cart-summary/WakaCartSummary.stories.tsx +176 -0
  81. package/src/components/waka-cart-summary/index.tsx +19 -10
  82. package/src/components/waka-challenge-timer/WakaChallengeTimer.stories.tsx +98 -0
  83. package/src/components/waka-chat-bubble/WakaChatBubble.stories.tsx +118 -0
  84. package/src/components/waka-checklist/WakaChecklist.stories.tsx +71 -0
  85. package/src/components/waka-checkout-stepper/WakaCheckoutStepper.stories.tsx +102 -0
  86. package/src/components/waka-cohort-table/WakaCohortTable.stories.tsx +56 -0
  87. package/src/components/waka-color-picker/WakaColorPicker.stories.tsx +99 -155
  88. package/src/components/waka-combo-counter/WakaComboCounter.stories.tsx +128 -0
  89. package/src/components/waka-command-bar/WakaCommandBar.stories.tsx +45 -0
  90. package/src/components/waka-compare-period/WakaComparePeriod.stories.tsx +76 -0
  91. package/src/components/waka-config-comparator/WakaConfigComparator.stories.tsx +143 -0
  92. package/src/components/waka-connection-matrix/WakaConnectionMatrix.stories.tsx +52 -0
  93. package/src/components/waka-content-recommendation/WakaContentRecommendation.stories.tsx +41 -0
  94. package/src/components/waka-coupon-input/WakaCouponInput.stories.tsx +126 -0
  95. package/src/components/waka-credit-card-input/WakaCreditCardInput.stories.tsx +120 -0
  96. package/src/components/waka-datetime-picker.form-integration/WakaDateTimePickerForm.stories.tsx +79 -0
  97. package/src/components/waka-dependency-tree/WakaDependencyTree.stories.tsx +72 -0
  98. package/src/components/waka-device-trust/WakaDeviceTrust.stories.tsx +109 -0
  99. package/src/components/waka-empty-state/WakaEmptyState.stories.tsx +87 -0
  100. package/src/components/waka-feature-announcement/WakaFeatureAnnouncement.stories.tsx +47 -0
  101. package/src/components/waka-feature-flag-row/WakaFeatureFlagRow.stories.tsx +188 -0
  102. package/src/components/waka-file-upload/WakaFileUpload.stories.tsx +118 -174
  103. package/src/components/waka-floating-nav/WakaFloatingNav.stories.tsx +53 -0
  104. package/src/components/waka-goal-progress/WakaGoalProgress.stories.tsx +137 -0
  105. package/src/components/waka-hotspot/WakaHotspot.stories.tsx +56 -0
  106. package/src/components/waka-invoice-preview/WakaInvoicePreview.stories.tsx +169 -0
  107. package/src/components/waka-kpi-dashboard/WakaKpiDashboard.stories.tsx +46 -0
  108. package/src/components/waka-level-progress/WakaLevelProgress.stories.tsx +94 -75
  109. package/src/components/waka-liquid-button/WakaLiquidButton.stories.tsx +45 -0
  110. package/src/components/waka-magic-link/WakaMagicLink.stories.tsx +61 -0
  111. package/src/components/waka-magnetic-button/WakaMagneticButton.stories.tsx +40 -0
  112. package/src/components/waka-mention-input/WakaMentionInput.stories.tsx +140 -0
  113. package/src/components/waka-milestone-road/WakaMilestoneRoad.stories.tsx +143 -0
  114. package/src/components/waka-orbital-menu/WakaOrbitalMenu.stories.tsx +54 -0
  115. package/src/components/waka-order-tracker/WakaOrderTracker.stories.tsx +163 -0
  116. package/src/components/waka-outstream-video/WakaOutstreamVideo.stories.tsx +94 -0
  117. package/src/components/waka-pagination/WakaPagination.stories.tsx +110 -280
  118. package/src/components/waka-password-strength/WakaPasswordStrength.stories.tsx +132 -268
  119. package/src/components/waka-payment-method-picker/WakaPaymentMethodPicker.stories.tsx +141 -0
  120. package/src/components/waka-permission-matrix/WakaPermissionMatrix.stories.tsx +124 -0
  121. package/src/components/waka-phone-input/WakaPhoneInput.stories.tsx +56 -0
  122. package/src/components/waka-points-popup/WakaPointsPopup.stories.tsx +96 -0
  123. package/src/components/waka-power-up/WakaPowerUp.stories.tsx +121 -0
  124. package/src/components/waka-presence-indicator/WakaPresenceIndicator.stories.tsx +49 -0
  125. package/src/components/waka-pricing-table/WakaPricingTable.stories.tsx +159 -0
  126. package/src/components/waka-product-card/WakaProductCard.stories.tsx +202 -0
  127. package/src/components/waka-progress-onboarding/WakaProgressOnboarding.stories.tsx +57 -0
  128. package/src/components/waka-pull-to-refresh/WakaPullToRefresh.stories.tsx +51 -0
  129. package/src/components/waka-rank-badge/WakaRankBadge.stories.tsx +108 -0
  130. package/src/components/waka-rating-input/WakaRatingInput.stories.tsx +51 -0
  131. package/src/components/waka-reaction-picker/WakaReactionPicker.stories.tsx +52 -0
  132. package/src/components/waka-region-map/WakaRegionMap.stories.tsx +181 -0
  133. package/src/components/waka-resource-pool/WakaResourcePool.stories.tsx +70 -0
  134. package/src/components/waka-rich-text-editor/WakaRichTextEditor.stories.tsx +108 -197
  135. package/src/components/waka-rollback-slider/WakaRollbackSlider.stories.tsx +41 -0
  136. package/src/components/waka-schedule-picker/WakaSchedulePicker.stories.tsx +64 -0
  137. package/src/components/waka-season-pass/WakaSeasonPass.stories.tsx +107 -0
  138. package/src/components/waka-security-scan-result/WakaSecurityScanResult.stories.tsx +146 -0
  139. package/src/components/waka-security-score/WakaSecurityScore.stories.tsx +63 -0
  140. package/src/components/waka-session-manager/WakaSessionManager.stories.tsx +68 -0
  141. package/src/components/waka-signature-pad/WakaSignaturePad.stories.tsx +159 -0
  142. package/src/components/waka-signature-pad/index.tsx +5 -3
  143. package/src/components/waka-sla-tracker/WakaSlaTracker.stories.tsx +65 -0
  144. package/src/components/waka-slider-range/WakaSliderRange.stories.tsx +66 -0
  145. package/src/components/waka-sponsored-badge/WakaSponsoredBadge.stories.tsx +60 -0
  146. package/src/components/waka-sponsored-card/WakaSponsoredCard.stories.tsx +64 -0
  147. package/src/components/waka-sponsored-feed/WakaSponsoredFeed.stories.tsx +58 -0
  148. package/src/components/waka-spotlight/WakaSpotlight.stories.tsx +53 -0
  149. package/src/components/waka-stats-hexagon/WakaStatsHexagon.stories.tsx +161 -0
  150. package/src/components/waka-stepper/WakaStepper.stories.tsx +137 -410
  151. package/src/components/waka-swipe-card/WakaSwipeCard.stories.tsx +51 -0
  152. package/src/components/waka-tag-input/WakaTagInput.stories.tsx +224 -0
  153. package/src/components/waka-team-banner/WakaTeamBanner.stories.tsx +50 -0
  154. package/src/components/waka-theme-creator/WakaThemeCreator.stories.tsx +58 -0
  155. package/src/components/waka-theme-manager/WakaThemeManager.stories.tsx +298 -0
  156. package/src/components/waka-theme-manager/index.tsx +6 -11
  157. package/src/components/waka-thread-view/WakaThreadView.stories.tsx +143 -0
  158. package/src/components/waka-timeline/WakaTimeline.stories.tsx +171 -324
  159. package/src/components/waka-tooltip-tour/WakaTooltipTour.stories.tsx +92 -0
  160. package/src/components/waka-tour-guide/WakaTourGuide.stories.tsx +89 -0
  161. package/src/components/waka-treemap-chart/WakaTreemapChart.stories.tsx +234 -129
  162. package/src/components/waka-treemap-chart/index.tsx +2 -2
  163. package/src/components/waka-two-factor-setup/WakaTwoFactorSetup.stories.tsx +142 -0
  164. package/src/components/waka-typing-indicator/WakaTypingIndicator.stories.tsx +134 -0
  165. package/src/components/waka-video-ad/WakaVideoAd.stories.tsx +138 -0
  166. package/src/components/waka-video-call/WakaVideoCall.stories.tsx +186 -0
  167. package/src/components/waka-video-overlay/WakaVideoOverlay.stories.tsx +100 -0
  168. package/src/components/waka-voice-message/WakaVoiceMessage.stories.tsx +190 -0
  169. package/src/components/waka-welcome-modal/WakaWelcomeModal.stories.tsx +87 -0
  170. package/src/components/waka-xp-bar/WakaXPBar.stories.tsx +29 -29
  171. package/dist/useDataTableImport-D8R2HQl6.mjs +0 -229
  172. package/dist/useDataTableImport-S_hhA5Wo.js +0 -9
  173. package/src/components/DataTable/README.md +0 -446
@@ -0,0 +1,612 @@
1
+ "use client"
2
+
3
+ import { useState } from "react"
4
+ import { Badge } from "../../components/badge"
5
+ import { Button } from "../../components/button"
6
+ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../../components/card"
7
+ import { Input } from "../../components/input"
8
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../components/select"
9
+ import { Progress } from "../../components/progress"
10
+ import { Tabs, TabsContent, TabsList, TabsTrigger } from "../../components/tabs"
11
+ import { Checkbox } from "../../components/checkbox"
12
+ import { Label } from "../../components/label"
13
+ import {
14
+ FileText,
15
+ Download,
16
+ Mail,
17
+ Calendar,
18
+ CheckCircle2,
19
+ AlertTriangle,
20
+ XCircle,
21
+ Shield,
22
+ TrendingUp,
23
+ BarChart3,
24
+ FileSpreadsheet,
25
+ FileJson,
26
+ } from "lucide-react"
27
+ import { cn } from "../../utils/cn"
28
+
29
+ export type ReportFormat = "pdf" | "csv" | "json"
30
+ export type ReportType = "executive_summary" | "detailed" | "iso27001_compliance" | "hds_audit"
31
+
32
+ export interface ReportConfig {
33
+ startDate: Date
34
+ endDate: Date
35
+ format: ReportFormat
36
+ type: ReportType
37
+ includeSections: {
38
+ generalStats: boolean
39
+ threatDetails: boolean
40
+ scannedFiles: boolean
41
+ actionsTaken: boolean
42
+ recommendations: boolean
43
+ }
44
+ recipientEmail?: string
45
+ }
46
+
47
+ export interface ReportPreview {
48
+ totalScans: number
49
+ totalThreats: number
50
+ detectionRate: number
51
+ quarantinedFiles: number
52
+ threatsBySeverity: { severity: string; count: number }[]
53
+ complianceChecks: { name: string; passed: boolean; details: string }[]
54
+ weeklyTrend: { week: string; scans: number; threats: number }[]
55
+ }
56
+
57
+ export interface ScanReportGeneratorProps {
58
+ config?: Partial<ReportConfig>
59
+ preview?: ReportPreview
60
+ isGenerating?: boolean
61
+ generationProgress?: number
62
+ onGenerate?: (config: ReportConfig) => void
63
+ onSchedule?: (config: ReportConfig, frequency: "daily" | "weekly" | "monthly") => void
64
+ onSendEmail?: (config: ReportConfig, email: string) => void
65
+ className?: string
66
+ }
67
+
68
+ const defaultConfig: ReportConfig = {
69
+ startDate: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
70
+ endDate: new Date(),
71
+ format: "pdf",
72
+ type: "executive_summary",
73
+ includeSections: {
74
+ generalStats: true,
75
+ threatDetails: true,
76
+ scannedFiles: true,
77
+ actionsTaken: true,
78
+ recommendations: true,
79
+ },
80
+ }
81
+
82
+ const defaultPreview: ReportPreview = {
83
+ totalScans: 1247,
84
+ totalThreats: 34,
85
+ detectionRate: 98.5,
86
+ quarantinedFiles: 28,
87
+ threatsBySeverity: [
88
+ { severity: "critical", count: 3 },
89
+ { severity: "high", count: 8 },
90
+ { severity: "medium", count: 15 },
91
+ { severity: "low", count: 8 },
92
+ ],
93
+ complianceChecks: [
94
+ { name: "Antivirus actif", passed: true, details: "ClamAV opérationnel" },
95
+ { name: "Scans automatisés", passed: true, details: "Planification quotidienne" },
96
+ { name: "Quarantaine sécurisée", passed: true, details: "Isolation cryptographique" },
97
+ { name: "Audit trail", passed: true, details: "Logs immutables activés" },
98
+ ],
99
+ weeklyTrend: [
100
+ { week: "S1", scans: 280, threats: 7 },
101
+ { week: "S2", scans: 295, threats: 9 },
102
+ { week: "S3", scans: 340, threats: 11 },
103
+ { week: "S4", scans: 332, threats: 7 },
104
+ ],
105
+ }
106
+
107
+ export function ScanReportGenerator({
108
+ config: initialConfig,
109
+ preview: initialPreview,
110
+ isGenerating = false,
111
+ generationProgress = 0,
112
+ onGenerate,
113
+ onSchedule,
114
+ onSendEmail,
115
+ className,
116
+ }: ScanReportGeneratorProps) {
117
+ const [config, setConfig] = useState<ReportConfig>({ ...defaultConfig, ...initialConfig })
118
+ const [preview] = useState<ReportPreview>(initialPreview || defaultPreview)
119
+ const [recipientEmail, setRecipientEmail] = useState("")
120
+ const [activeTab, setActiveTab] = useState("config")
121
+
122
+ const formatIcons: Record<ReportFormat, React.ReactNode> = {
123
+ pdf: <FileText className="h-4 w-4" />,
124
+ csv: <FileSpreadsheet className="h-4 w-4" />,
125
+ json: <FileJson className="h-4 w-4" />,
126
+ }
127
+
128
+ const reportTypeLabels: Record<ReportType, string> = {
129
+ executive_summary: "Résumé exécutif",
130
+ detailed: "Détail complet",
131
+ iso27001_compliance: "Conformité ISO27001",
132
+ hds_audit: "Audit HDS",
133
+ }
134
+
135
+ const severityColors: Record<string, string> = {
136
+ critical: "bg-red-500",
137
+ high: "bg-orange-500",
138
+ medium: "bg-yellow-500",
139
+ low: "bg-blue-500",
140
+ }
141
+
142
+ const updateSection = (section: keyof ReportConfig["includeSections"], value: boolean) => {
143
+ setConfig({
144
+ ...config,
145
+ includeSections: {
146
+ ...config.includeSections,
147
+ [section]: value,
148
+ },
149
+ })
150
+ }
151
+
152
+ const maxThreatCount = Math.max(...preview.threatsBySeverity.map((t) => t.count))
153
+ const maxTrendValue = Math.max(...preview.weeklyTrend.map((t) => Math.max(t.scans, t.threats)))
154
+
155
+ return (
156
+ <div className={cn("space-y-6", className)}>
157
+ {/* Header */}
158
+ <div className="flex items-start justify-between">
159
+ <div>
160
+ <h2 className="text-2xl font-bold">Générateur de rapports</h2>
161
+ <p className="text-sm text-muted-foreground mt-1">
162
+ Créez des rapports de scan personnalisés pour vos audits de sécurité
163
+ </p>
164
+ </div>
165
+ <Badge variant="outline" className="gap-1.5">
166
+ <Shield className="h-3.5 w-3.5" />
167
+ ISO27001 / HDS
168
+ </Badge>
169
+ </div>
170
+
171
+ {/* Main Content */}
172
+ <Tabs value={activeTab} onValueChange={setActiveTab}>
173
+ <TabsList>
174
+ <TabsTrigger value="config">Configuration</TabsTrigger>
175
+ <TabsTrigger value="preview">Aperçu</TabsTrigger>
176
+ </TabsList>
177
+
178
+ {/* Configuration Tab */}
179
+ <TabsContent value="config" className="space-y-6">
180
+ <Card>
181
+ <CardHeader>
182
+ <CardTitle>Période du rapport</CardTitle>
183
+ <CardDescription>Sélectionnez la plage de dates à analyser</CardDescription>
184
+ </CardHeader>
185
+ <CardContent className="grid gap-4 sm:grid-cols-2">
186
+ <div className="space-y-2">
187
+ <Label htmlFor="startDate">Date de début</Label>
188
+ <Input
189
+ id="startDate"
190
+ type="date"
191
+ value={config.startDate.toISOString().split("T")[0]}
192
+ onChange={(e) =>
193
+ setConfig({ ...config, startDate: new Date(e.target.value) })
194
+ }
195
+ />
196
+ </div>
197
+ <div className="space-y-2">
198
+ <Label htmlFor="endDate">Date de fin</Label>
199
+ <Input
200
+ id="endDate"
201
+ type="date"
202
+ value={config.endDate.toISOString().split("T")[0]}
203
+ onChange={(e) => setConfig({ ...config, endDate: new Date(e.target.value) })}
204
+ />
205
+ </div>
206
+ </CardContent>
207
+ </Card>
208
+
209
+ <Card>
210
+ <CardHeader>
211
+ <CardTitle>Type et format</CardTitle>
212
+ <CardDescription>Choisissez le type de rapport et le format de sortie</CardDescription>
213
+ </CardHeader>
214
+ <CardContent className="grid gap-4 sm:grid-cols-2">
215
+ <div className="space-y-2">
216
+ <Label htmlFor="reportType">Type de rapport</Label>
217
+ <Select
218
+ value={config.type}
219
+ onValueChange={(value) => setConfig({ ...config, type: value as ReportType })}
220
+ >
221
+ <SelectTrigger id="reportType">
222
+ <SelectValue />
223
+ </SelectTrigger>
224
+ <SelectContent>
225
+ {Object.entries(reportTypeLabels).map(([value, label]) => (
226
+ <SelectItem key={value} value={value}>
227
+ {label}
228
+ </SelectItem>
229
+ ))}
230
+ </SelectContent>
231
+ </Select>
232
+ </div>
233
+ <div className="space-y-2">
234
+ <Label htmlFor="format">Format de sortie</Label>
235
+ <Select
236
+ value={config.format}
237
+ onValueChange={(value) => setConfig({ ...config, format: value as ReportFormat })}
238
+ >
239
+ <SelectTrigger id="format">
240
+ <SelectValue />
241
+ </SelectTrigger>
242
+ <SelectContent>
243
+ <SelectItem value="pdf">
244
+ <span className="flex items-center gap-2">
245
+ {formatIcons.pdf}
246
+ PDF
247
+ </span>
248
+ </SelectItem>
249
+ <SelectItem value="csv">
250
+ <span className="flex items-center gap-2">
251
+ {formatIcons.csv}
252
+ CSV
253
+ </span>
254
+ </SelectItem>
255
+ <SelectItem value="json">
256
+ <span className="flex items-center gap-2">
257
+ {formatIcons.json}
258
+ JSON
259
+ </span>
260
+ </SelectItem>
261
+ </SelectContent>
262
+ </Select>
263
+ </div>
264
+ </CardContent>
265
+ </Card>
266
+
267
+ <Card>
268
+ <CardHeader>
269
+ <CardTitle>Sections à inclure</CardTitle>
270
+ <CardDescription>Personnalisez le contenu du rapport</CardDescription>
271
+ </CardHeader>
272
+ <CardContent className="space-y-3">
273
+ <div className="flex items-center gap-2">
274
+ <Checkbox
275
+ id="generalStats"
276
+ checked={config.includeSections.generalStats}
277
+ onCheckedChange={(checked) =>
278
+ updateSection("generalStats", checked as boolean)
279
+ }
280
+ />
281
+ <Label htmlFor="generalStats" className="cursor-pointer">
282
+ Statistiques générales
283
+ </Label>
284
+ </div>
285
+ <div className="flex items-center gap-2">
286
+ <Checkbox
287
+ id="threatDetails"
288
+ checked={config.includeSections.threatDetails}
289
+ onCheckedChange={(checked) =>
290
+ updateSection("threatDetails", checked as boolean)
291
+ }
292
+ />
293
+ <Label htmlFor="threatDetails" className="cursor-pointer">
294
+ Détails des menaces détectées
295
+ </Label>
296
+ </div>
297
+ <div className="flex items-center gap-2">
298
+ <Checkbox
299
+ id="scannedFiles"
300
+ checked={config.includeSections.scannedFiles}
301
+ onCheckedChange={(checked) =>
302
+ updateSection("scannedFiles", checked as boolean)
303
+ }
304
+ />
305
+ <Label htmlFor="scannedFiles" className="cursor-pointer">
306
+ Liste des fichiers scannés
307
+ </Label>
308
+ </div>
309
+ <div className="flex items-center gap-2">
310
+ <Checkbox
311
+ id="actionsTaken"
312
+ checked={config.includeSections.actionsTaken}
313
+ onCheckedChange={(checked) =>
314
+ updateSection("actionsTaken", checked as boolean)
315
+ }
316
+ />
317
+ <Label htmlFor="actionsTaken" className="cursor-pointer">
318
+ Actions prises
319
+ </Label>
320
+ </div>
321
+ <div className="flex items-center gap-2">
322
+ <Checkbox
323
+ id="recommendations"
324
+ checked={config.includeSections.recommendations}
325
+ onCheckedChange={(checked) =>
326
+ updateSection("recommendations", checked as boolean)
327
+ }
328
+ />
329
+ <Label htmlFor="recommendations" className="cursor-pointer">
330
+ Recommandations
331
+ </Label>
332
+ </div>
333
+ </CardContent>
334
+ </Card>
335
+
336
+ {/* Actions */}
337
+ <div className="flex flex-col sm:flex-row gap-3">
338
+ <Button
339
+ className="flex-1"
340
+ onClick={() => onGenerate?.(config)}
341
+ disabled={isGenerating}
342
+ >
343
+ <Download className="h-4 w-4 mr-2" />
344
+ Générer le rapport
345
+ </Button>
346
+ <Button
347
+ variant="outline"
348
+ className="flex-1"
349
+ onClick={() => onSchedule?.(config, "weekly")}
350
+ disabled={isGenerating}
351
+ >
352
+ <Calendar className="h-4 w-4 mr-2" />
353
+ Planifier génération
354
+ </Button>
355
+ </div>
356
+
357
+ <Card>
358
+ <CardHeader>
359
+ <CardTitle>Envoi par email</CardTitle>
360
+ <CardDescription>Envoyez le rapport directement par email</CardDescription>
361
+ </CardHeader>
362
+ <CardContent className="flex gap-2">
363
+ <Input
364
+ placeholder="email@example.com"
365
+ type="email"
366
+ value={recipientEmail}
367
+ onChange={(e) => setRecipientEmail(e.target.value)}
368
+ className="flex-1"
369
+ />
370
+ <Button
371
+ variant="outline"
372
+ onClick={() => onSendEmail?.(config, recipientEmail)}
373
+ disabled={!recipientEmail || isGenerating}
374
+ >
375
+ <Mail className="h-4 w-4 mr-2" />
376
+ Envoyer
377
+ </Button>
378
+ </CardContent>
379
+ </Card>
380
+
381
+ {/* Generation Progress */}
382
+ {isGenerating && (
383
+ <Card>
384
+ <CardContent className="pt-6">
385
+ <div className="space-y-2">
386
+ <div className="flex items-center justify-between text-sm">
387
+ <span className="text-muted-foreground">Génération en cours...</span>
388
+ <span className="font-medium">{generationProgress}%</span>
389
+ </div>
390
+ <Progress value={generationProgress} />
391
+ </div>
392
+ </CardContent>
393
+ </Card>
394
+ )}
395
+ </TabsContent>
396
+
397
+ {/* Preview Tab */}
398
+ <TabsContent value="preview" className="space-y-6">
399
+ {/* Header Preview */}
400
+ <Card>
401
+ <CardContent className="pt-6">
402
+ <div className="space-y-4">
403
+ <div className="flex items-start justify-between">
404
+ <div>
405
+ <div className="h-12 w-12 rounded-lg bg-gradient-to-br from-blue-500 to-purple-600 flex items-center justify-center mb-3">
406
+ <Shield className="h-6 w-6 text-white" />
407
+ </div>
408
+ <h3 className="text-xl font-bold">Rapport de scan de sécurité</h3>
409
+ <p className="text-sm text-muted-foreground mt-1">
410
+ {reportTypeLabels[config.type]}
411
+ </p>
412
+ </div>
413
+ <Badge variant="secondary">
414
+ {config.startDate.toLocaleDateString()} -{" "}
415
+ {config.endDate.toLocaleDateString()}
416
+ </Badge>
417
+ </div>
418
+ <div className="text-xs text-muted-foreground">
419
+ Généré le {new Date().toLocaleString()}
420
+ </div>
421
+ </div>
422
+ </CardContent>
423
+ </Card>
424
+
425
+ {/* Summary Stats */}
426
+ {config.includeSections.generalStats && (
427
+ <div className="grid gap-4 sm:grid-cols-2 lg:grid-cols-4">
428
+ <Card>
429
+ <CardContent className="pt-6">
430
+ <div className="space-y-2">
431
+ <div className="flex items-center gap-2 text-sm text-muted-foreground">
432
+ <BarChart3 className="h-4 w-4" />
433
+ Total scans
434
+ </div>
435
+ <div className="text-2xl font-bold">{preview.totalScans.toLocaleString()}</div>
436
+ </div>
437
+ </CardContent>
438
+ </Card>
439
+ <Card>
440
+ <CardContent className="pt-6">
441
+ <div className="space-y-2">
442
+ <div className="flex items-center gap-2 text-sm text-muted-foreground">
443
+ <AlertTriangle className="h-4 w-4" />
444
+ Menaces détectées
445
+ </div>
446
+ <div className="text-2xl font-bold">{preview.totalThreats}</div>
447
+ </div>
448
+ </CardContent>
449
+ </Card>
450
+ <Card>
451
+ <CardContent className="pt-6">
452
+ <div className="space-y-2">
453
+ <div className="flex items-center gap-2 text-sm text-muted-foreground">
454
+ <TrendingUp className="h-4 w-4" />
455
+ Taux de détection
456
+ </div>
457
+ <div className="text-2xl font-bold">{preview.detectionRate}%</div>
458
+ </div>
459
+ </CardContent>
460
+ </Card>
461
+ <Card>
462
+ <CardContent className="pt-6">
463
+ <div className="space-y-2">
464
+ <div className="flex items-center gap-2 text-sm text-muted-foreground">
465
+ <Shield className="h-4 w-4" />
466
+ Fichiers en quarantaine
467
+ </div>
468
+ <div className="text-2xl font-bold">{preview.quarantinedFiles}</div>
469
+ </div>
470
+ </CardContent>
471
+ </Card>
472
+ </div>
473
+ )}
474
+
475
+ {/* Threats by Severity */}
476
+ {config.includeSections.threatDetails && (
477
+ <Card>
478
+ <CardHeader>
479
+ <CardTitle>Menaces par sévérité</CardTitle>
480
+ <CardDescription>Distribution des menaces détectées</CardDescription>
481
+ </CardHeader>
482
+ <CardContent className="space-y-4">
483
+ {preview.threatsBySeverity.map((item) => (
484
+ <div key={item.severity} className="space-y-2">
485
+ <div className="flex items-center justify-between text-sm">
486
+ <span className="capitalize font-medium">{item.severity}</span>
487
+ <span className="text-muted-foreground">{item.count}</span>
488
+ </div>
489
+ <div className="h-2 bg-muted rounded-full overflow-hidden">
490
+ <div
491
+ className={cn("h-full rounded-full", severityColors[item.severity])}
492
+ style={{ width: `${(item.count / maxThreatCount) * 100}%` }}
493
+ />
494
+ </div>
495
+ </div>
496
+ ))}
497
+ </CardContent>
498
+ </Card>
499
+ )}
500
+
501
+ {/* Weekly Trend */}
502
+ {config.includeSections.generalStats && (
503
+ <Card>
504
+ <CardHeader>
505
+ <CardTitle>Tendance hebdomadaire</CardTitle>
506
+ <CardDescription>Évolution des scans et menaces</CardDescription>
507
+ </CardHeader>
508
+ <CardContent>
509
+ <div className="space-y-4">
510
+ <div className="flex items-end gap-4 h-48">
511
+ {preview.weeklyTrend.map((item) => (
512
+ <div key={item.week} className="flex-1 flex flex-col items-center gap-2">
513
+ <div className="flex-1 w-full flex items-end gap-1">
514
+ <div
515
+ className="flex-1 bg-blue-500 rounded-t"
516
+ style={{ height: `${(item.scans / maxTrendValue) * 100}%` }}
517
+ title={`Scans: ${item.scans}`}
518
+ />
519
+ <div
520
+ className="flex-1 bg-orange-500 rounded-t"
521
+ style={{ height: `${(item.threats / maxTrendValue) * 100}%` }}
522
+ title={`Menaces: ${item.threats}`}
523
+ />
524
+ </div>
525
+ <span className="text-xs text-muted-foreground">{item.week}</span>
526
+ </div>
527
+ ))}
528
+ </div>
529
+ <div className="flex items-center justify-center gap-6 text-xs">
530
+ <div className="flex items-center gap-2">
531
+ <div className="h-3 w-3 rounded bg-blue-500" />
532
+ <span className="text-muted-foreground">Scans</span>
533
+ </div>
534
+ <div className="flex items-center gap-2">
535
+ <div className="h-3 w-3 rounded bg-orange-500" />
536
+ <span className="text-muted-foreground">Menaces</span>
537
+ </div>
538
+ </div>
539
+ </div>
540
+ </CardContent>
541
+ </Card>
542
+ )}
543
+
544
+ {/* Compliance Checks */}
545
+ {(config.type === "iso27001_compliance" || config.type === "hds_audit") && (
546
+ <Card>
547
+ <CardHeader>
548
+ <CardTitle>Vérifications de conformité</CardTitle>
549
+ <CardDescription>
550
+ {config.type === "iso27001_compliance"
551
+ ? "Conformité ISO27001"
552
+ : "Audit HDS"}
553
+ </CardDescription>
554
+ </CardHeader>
555
+ <CardContent className="space-y-3">
556
+ {preview.complianceChecks.map((check, index) => (
557
+ <div
558
+ key={index}
559
+ className="flex items-start gap-3 p-3 rounded-lg border bg-card"
560
+ >
561
+ {check.passed ? (
562
+ <CheckCircle2 className="h-5 w-5 text-green-500 mt-0.5" />
563
+ ) : (
564
+ <XCircle className="h-5 w-5 text-red-500 mt-0.5" />
565
+ )}
566
+ <div className="flex-1 space-y-1">
567
+ <div className="font-medium">{check.name}</div>
568
+ <div className="text-sm text-muted-foreground">{check.details}</div>
569
+ </div>
570
+ <Badge variant={check.passed ? "default" : "destructive"} className={check.passed ? "bg-green-500/10 text-green-600 border-green-500/20" : ""}>
571
+ {check.passed ? "Conforme" : "Non conforme"}
572
+ </Badge>
573
+ </div>
574
+ ))}
575
+ </CardContent>
576
+ </Card>
577
+ )}
578
+
579
+ {/* Recommendations */}
580
+ {config.includeSections.recommendations && (
581
+ <Card>
582
+ <CardHeader>
583
+ <CardTitle>Recommandations</CardTitle>
584
+ <CardDescription>Actions suggérées pour améliorer la sécurité</CardDescription>
585
+ </CardHeader>
586
+ <CardContent>
587
+ <ul className="space-y-2 text-sm">
588
+ <li className="flex items-start gap-2">
589
+ <span className="text-muted-foreground mt-1">•</span>
590
+ <span>Augmenter la fréquence des scans pour les répertoires critiques</span>
591
+ </li>
592
+ <li className="flex items-start gap-2">
593
+ <span className="text-muted-foreground mt-1">•</span>
594
+ <span>Mettre à jour les signatures de virus (dernière mise à jour: il y a 2h)</span>
595
+ </li>
596
+ <li className="flex items-start gap-2">
597
+ <span className="text-muted-foreground mt-1">•</span>
598
+ <span>Configurer des alertes en temps réel pour les menaces critiques</span>
599
+ </li>
600
+ <li className="flex items-start gap-2">
601
+ <span className="text-muted-foreground mt-1">•</span>
602
+ <span>Réviser la politique de quarantaine automatique</span>
603
+ </li>
604
+ </ul>
605
+ </CardContent>
606
+ </Card>
607
+ )}
608
+ </TabsContent>
609
+ </Tabs>
610
+ </div>
611
+ )
612
+ }
@@ -596,7 +596,8 @@ export function WakaSidebar({
596
596
  "bg-[var(--sidebar-bg)] text-[var(--sidebar-text)]",
597
597
  "[&_.bg-sidebar-active]:bg-[var(--sidebar-active)]",
598
598
  "[&_.text-sidebar-active-foreground]:text-[var(--sidebar-active-foreground)]",
599
- "[&_.text-sidebar-foreground\\/70]:text-[var(--sidebar-text)]/70",
599
+ "[&_.text-sidebar-foreground\\/70]:text-[var(--sidebar-text)]",
600
+ "[&_.text-sidebar-foreground\\/70]:opacity-70",
600
601
  "[&_.border-sidebar-active]:border-[var(--sidebar-active)]",
601
602
  contentClassName
602
603
  )