feat: Integrate shadcn/ui design system
- Install shadcn/ui dependencies (CVA, clsx, tailwind-merge, lucide-react) - Install Radix UI primitives (slot, label) - Create utility helper (lib/utils.ts with cn function) - Update Tailwind config for shadcn/ui theme support - Add CSS variables for theming in globals.css (Tailwind v4 syntax) - Add shadcn/ui components: Button, Card, Input, Label - Update JourneyForm with shadcn/ui components and icons - Update DataPreview with shadcn/ui components and icons - Improve UI consistency and accessibility 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,9 @@
|
||||
|
||||
import { useState } from 'react'
|
||||
import API_URL from '@/lib/api'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Upload, BarChart3, Loader2, FileText, CheckCircle2, AlertCircle } from 'lucide-react'
|
||||
|
||||
interface DataPreviewProps {
|
||||
data: any
|
||||
@@ -53,63 +56,54 @@ export default function DataPreview({ data, loading, formData }: DataPreviewProp
|
||||
}
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="bg-white/98 backdrop-blur-lg rounded-3xl shadow-2xl border border-white/30 overflow-hidden">
|
||||
<div className="flex flex-col items-center justify-center h-96 p-8">
|
||||
<div className="relative">
|
||||
<div className="animate-spin rounded-full h-20 w-20 border-4 border-blue-200"></div>
|
||||
<div className="animate-spin rounded-full h-20 w-20 border-t-4 border-blue-600 absolute top-0"></div>
|
||||
</div>
|
||||
<Card className="bg-white/98 backdrop-blur-lg border-white/30">
|
||||
<CardContent className="flex flex-col items-center justify-center h-96 p-8">
|
||||
<Loader2 className="h-20 w-20 text-blue-600 animate-spin" />
|
||||
<p className="mt-6 text-gray-700 font-semibold text-lg">Načítání dat...</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
if (!data) {
|
||||
return (
|
||||
<div className="bg-white/98 backdrop-blur-lg rounded-3xl shadow-2xl border border-white/30 overflow-hidden">
|
||||
<div className="bg-gradient-to-r from-purple-50 to-purple-100 px-8 py-6 border-b border-purple-200">
|
||||
<div className="flex items-center gap-4">
|
||||
<Card className="bg-white/98 backdrop-blur-lg border-white/30">
|
||||
<CardHeader className="bg-gradient-to-r from-purple-50 to-purple-100 border-b border-purple-200">
|
||||
<CardTitle className="text-3xl font-bold text-gray-800 flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-gradient-to-br from-purple-500 to-purple-600 rounded-xl flex items-center justify-center shadow-lg">
|
||||
<svg className="w-7 h-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
<BarChart3 className="w-7 h-7 text-white" />
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-gray-800">Náhled dat</h2>
|
||||
<span>Náhled dat</span>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="p-8">
|
||||
<div className="flex flex-col items-center justify-center py-16 text-center">
|
||||
<div className="w-20 h-20 bg-gray-100 rounded-full flex items-center justify-center mb-4">
|
||||
<FileText className="w-10 h-10 text-gray-400" />
|
||||
</div>
|
||||
<p className="text-gray-500 font-medium">
|
||||
Vyplňte formulář a klikněte na "Vypočítat"
|
||||
</p>
|
||||
<p className="text-gray-400 text-sm mt-1">
|
||||
Data se zobrazí zde
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-8">
|
||||
<div className="flex flex-col items-center justify-center py-16 text-center">
|
||||
<div className="w-20 h-20 bg-gray-100 rounded-full flex items-center justify-center mb-4">
|
||||
<svg className="w-10 h-10 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 21h10a2 2 0 002-2V9.414a1 1 0 00-.293-.707l-5.414-5.414A1 1 0 0012.586 3H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<p className="text-gray-500 font-medium">
|
||||
Vyplňte formulář a klikněte na "Vypočítat"
|
||||
</p>
|
||||
<p className="text-gray-400 text-sm mt-1">
|
||||
Data se zobrazí zde
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white/98 backdrop-blur-lg rounded-3xl shadow-2xl border border-white/30 overflow-hidden">
|
||||
<div className="bg-gradient-to-r from-purple-50 to-purple-100 px-8 py-6 border-b border-purple-200">
|
||||
<div className="flex items-center gap-4">
|
||||
<Card className="bg-white/98 backdrop-blur-lg border-white/30">
|
||||
<CardHeader className="bg-gradient-to-r from-purple-50 to-purple-100 border-b border-purple-200">
|
||||
<CardTitle className="text-3xl font-bold text-gray-800 flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-gradient-to-br from-purple-500 to-purple-600 rounded-xl flex items-center justify-center shadow-lg">
|
||||
<svg className="w-7 h-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
|
||||
</svg>
|
||||
<BarChart3 className="w-7 h-7 text-white" />
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-gray-800">Náhled dat</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-8">
|
||||
<span>Náhled dat</span>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="p-8">
|
||||
|
||||
<div className="mb-6 grid grid-cols-2 gap-3 bg-gradient-to-br from-blue-50 to-indigo-50 p-5 rounded-xl border border-blue-100">
|
||||
<div>
|
||||
@@ -165,23 +159,39 @@ export default function DataPreview({ data, loading, formData }: DataPreviewProp
|
||||
|
||||
{formData && formData.startDate === '2025-01-01' && (
|
||||
<div className="mt-6">
|
||||
<button
|
||||
<Button
|
||||
onClick={handleFillToWebsite}
|
||||
disabled={filling}
|
||||
className="w-full bg-gradient-to-r from-orange-600 to-orange-700 hover:from-orange-700 hover:to-orange-800 text-white font-bold py-4 px-6 rounded-xl shadow-lg hover:shadow-2xl transform hover:-translate-y-1 transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed"
|
||||
size="lg"
|
||||
className="w-full bg-gradient-to-r from-orange-600 to-orange-700 hover:from-orange-700 hover:to-orange-800 text-lg h-12"
|
||||
>
|
||||
<span className="flex items-center justify-center gap-3">
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-8l-4-4m0 0L8 8m4-4v12" />
|
||||
</svg>
|
||||
<span className="text-lg">{filling ? 'Vyplňování...' : 'Vyplnit na web'}</span>
|
||||
</span>
|
||||
</button>
|
||||
{filling ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-5 w-5 animate-spin" />
|
||||
Vyplňování...
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Upload className="mr-2 h-5 w-5" />
|
||||
Vyplnit na web
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
{fillResult && (
|
||||
<div className={`mt-4 ${fillResult.dry_run ? 'bg-blue-50 border-blue-200' : 'bg-green-50 border-green-200'} border rounded-xl p-4`}>
|
||||
<h3 className={`font-bold ${fillResult.dry_run ? 'text-blue-900' : 'text-green-900'} mb-2`}>
|
||||
{fillResult.dry_run ? 'Výsledek DRY RUN:' : 'Výsledek vyplňování:'}
|
||||
<h3 className={`font-bold ${fillResult.dry_run ? 'text-blue-900' : 'text-green-900'} mb-2 flex items-center gap-2`}>
|
||||
{fillResult.dry_run ? (
|
||||
<>
|
||||
<AlertCircle className="h-5 w-5" />
|
||||
Výsledek DRY RUN:
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CheckCircle2 className="h-5 w-5" />
|
||||
Výsledek vyplňování:
|
||||
</>
|
||||
)}
|
||||
</h3>
|
||||
<div className={`text-sm ${fillResult.dry_run ? 'text-blue-800' : 'text-green-800'}`}>
|
||||
<p>Měsíc: {fillResult.month}</p>
|
||||
@@ -205,18 +215,23 @@ export default function DataPreview({ data, loading, formData }: DataPreviewProp
|
||||
</>
|
||||
)}
|
||||
{fillResult.dry_run && (
|
||||
<p className="mt-2 font-semibold text-orange-700">
|
||||
⚠️ DRY RUN MODE - Data nebyla odeslána na web
|
||||
<p className="mt-2 font-semibold text-orange-700 flex items-center gap-2">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
DRY RUN MODE - Data nebyla odeslána na web
|
||||
</p>
|
||||
)}
|
||||
{!fillResult.dry_run && fillResult.updates_successful > 0 && (
|
||||
<p className="mt-2 font-semibold text-green-700">
|
||||
✅ Data byla úspěšně vyplněna. Nyní zkontrolujte na webu a klikněte "Uzavřít měsíc" ručně.
|
||||
<p className="mt-2 font-semibold text-green-700 flex items-center gap-2">
|
||||
<CheckCircle2 className="h-4 w-4" />
|
||||
Data byla úspěšně vyplněna. Nyní zkontrolujte na webu a klikněte "Uzavřít měsíc" ručně.
|
||||
</p>
|
||||
)}
|
||||
{!fillResult.dry_run && fillResult.errors && fillResult.errors.length > 0 && (
|
||||
<div className="mt-2 p-2 bg-red-100 border border-red-300 rounded">
|
||||
<p className="font-semibold text-red-900">Chyby:</p>
|
||||
<p className="font-semibold text-red-900 flex items-center gap-2">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
Chyby:
|
||||
</p>
|
||||
{fillResult.errors.map((err: any, idx: number) => (
|
||||
<p key={idx} className="text-xs text-red-800">• {err.type} řádek {err.row}: {err.error}</p>
|
||||
))}
|
||||
@@ -227,7 +242,7 @@ export default function DataPreview({ data, loading, formData }: DataPreviewProp
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
import { useState } from 'react'
|
||||
import API_URL from '@/lib/api'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Calculator, Download } from 'lucide-react'
|
||||
|
||||
interface JourneyFormProps {
|
||||
onDataCalculated: (data: any) => void
|
||||
@@ -99,130 +104,114 @@ export default function JourneyForm({ onDataCalculated, setLoading, onFormDataCh
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-white/98 backdrop-blur-lg rounded-3xl shadow-2xl overflow-hidden border border-white/30">
|
||||
<div className="bg-gradient-to-r from-blue-50 to-blue-100 px-8 py-6 border-b border-blue-200">
|
||||
<div className="flex items-center gap-4">
|
||||
<Card className="bg-white/98 backdrop-blur-lg border-white/30">
|
||||
<CardHeader className="bg-gradient-to-r from-blue-50 to-blue-100 border-b border-blue-200">
|
||||
<CardTitle className="text-3xl font-bold text-gray-800 flex items-center gap-4">
|
||||
<div className="w-12 h-12 bg-gradient-to-br from-blue-500 to-blue-600 rounded-xl flex items-center justify-center shadow-lg">
|
||||
<svg className="w-7 h-7 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z" />
|
||||
</svg>
|
||||
</div>
|
||||
<h2 className="text-3xl font-bold text-gray-800">Vstupní údaje</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div className="p-8">
|
||||
<span>Vstupní údaje</span>
|
||||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="p-8">
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-5">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Uživatelské jméno
|
||||
</label>
|
||||
<input
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="username">Uživatelské jméno</Label>
|
||||
<Input
|
||||
id="username"
|
||||
type="text"
|
||||
required
|
||||
value={formData.username}
|
||||
onChange={(e) => setFormData({ ...formData, username: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
placeholder="Zadejte uživatelské jméno"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Heslo
|
||||
</label>
|
||||
<input
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="password">Heslo</Label>
|
||||
<Input
|
||||
id="password"
|
||||
type="password"
|
||||
required
|
||||
value={formData.password}
|
||||
onChange={(e) => setFormData({ ...formData, password: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
placeholder="Zadejte heslo"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Datum od
|
||||
</label>
|
||||
<input
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="startDate">Datum od</Label>
|
||||
<Input
|
||||
id="startDate"
|
||||
type="date"
|
||||
required
|
||||
value={formData.startDate}
|
||||
onChange={(e) => setFormData({ ...formData, startDate: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Datum do
|
||||
</label>
|
||||
<input
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="endDate">Datum do</Label>
|
||||
<Input
|
||||
id="endDate"
|
||||
type="date"
|
||||
required
|
||||
value={formData.endDate}
|
||||
onChange={(e) => setFormData({ ...formData, endDate: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Počáteční stav [km]
|
||||
</label>
|
||||
<input
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="startKm">Počáteční stav [km]</Label>
|
||||
<Input
|
||||
id="startKm"
|
||||
type="number"
|
||||
required
|
||||
value={formData.startKm}
|
||||
onChange={(e) => setFormData({ ...formData, startKm: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Koncový stav [km]
|
||||
</label>
|
||||
<input
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="endKm">Koncový stav [km]</Label>
|
||||
<Input
|
||||
id="endKm"
|
||||
type="number"
|
||||
required
|
||||
value={formData.endKm}
|
||||
onChange={(e) => setFormData({ ...formData, endKm: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
SPZ vozidla
|
||||
</label>
|
||||
<input
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="vehicleRegistration">SPZ vozidla</Label>
|
||||
<Input
|
||||
id="vehicleRegistration"
|
||||
type="text"
|
||||
value={formData.vehicleRegistration}
|
||||
onChange={(e) => setFormData({ ...formData, vehicleRegistration: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label className="block text-sm font-medium text-gray-700 mb-1">
|
||||
Variance (0-1)
|
||||
</label>
|
||||
<input
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="variance">Variance (0-1)</Label>
|
||||
<Input
|
||||
id="variance"
|
||||
type="number"
|
||||
step="0.01"
|
||||
min="0"
|
||||
max="1"
|
||||
value={formData.variance}
|
||||
onChange={(e) => setFormData({ ...formData, variance: e.target.value })}
|
||||
className="w-full px-4 py-3 bg-gray-50 border border-gray-200 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
|
||||
/>
|
||||
<p className="text-xs text-gray-500 mt-1">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Náhodná variace rozdělení kilometrů (doporučeno 0.1 = 10%)
|
||||
</p>
|
||||
</div>
|
||||
@@ -237,33 +226,27 @@ export default function JourneyForm({ onDataCalculated, setLoading, onFormDataCh
|
||||
)}
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4 pt-6">
|
||||
<button
|
||||
<Button
|
||||
type="submit"
|
||||
className="flex-1 bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 text-white font-bold py-4 px-6 rounded-xl shadow-lg hover:shadow-2xl transform hover:-translate-y-1 transition-all duration-200"
|
||||
size="lg"
|
||||
className="flex-1 bg-gradient-to-r from-blue-600 to-blue-700 hover:from-blue-700 hover:to-blue-800 text-lg h-12"
|
||||
>
|
||||
<span className="flex items-center justify-center gap-3">
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 7h6m0 10v-3m-3 3h.01M9 17h.01M9 14h.01M12 14h.01M15 11h.01M12 11h.01M9 11h.01M7 21h10a2 2 0 002-2V5a2 2 0 00-2-2H7a2 2 0 00-2 2v14a2 2 0 002 2z" />
|
||||
</svg>
|
||||
<span className="text-lg">Vypočítat</span>
|
||||
</span>
|
||||
</button>
|
||||
<Calculator className="mr-2 h-5 w-5" />
|
||||
Vypočítat
|
||||
</Button>
|
||||
|
||||
<button
|
||||
<Button
|
||||
type="button"
|
||||
onClick={handleExport}
|
||||
className="flex-1 bg-gradient-to-r from-green-600 to-green-700 hover:from-green-700 hover:to-green-800 text-white font-bold py-4 px-6 rounded-xl shadow-lg hover:shadow-2xl transform hover:-translate-y-1 transition-all duration-200"
|
||||
size="lg"
|
||||
className="flex-1 bg-gradient-to-r from-green-600 to-green-700 hover:from-green-700 hover:to-green-800 text-lg h-12"
|
||||
>
|
||||
<span className="flex items-center justify-center gap-3">
|
||||
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 10v6m0 0l-3-3m3 3l3-3m2 8H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
|
||||
</svg>
|
||||
<span className="text-lg">Export Excel</span>
|
||||
</span>
|
||||
</button>
|
||||
<Download className="mr-2 h-5 w-5" />
|
||||
Export Excel
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user