sozsoft-platform/ui/src/views/intranet/widgets/Documents.tsx

99 lines
4.2 KiB
TypeScript

import React from 'react'
import { FaFileAlt, FaDownload } from 'react-icons/fa'
import dayjs from 'dayjs'
import { DocumentDto } from '@/proxy/intranet/models'
import { useLocalization } from '@/utils/hooks/useLocalization'
import { getFileIcon, getFileType } from '@/proxy/intranet/utils'
import { FILE_URL } from '@/constants/app.constant'
import Button from '@/components/ui/Button'
import type { DashboardWidgetDefinition } from '../dashboardWidget'
import { baseNameOf, formatFileSize } from '../documents/documentUtils'
const Documents: React.FC<{ documents: DocumentDto[] }> = ({ documents }) => {
const { translate } = useLocalization()
return (
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 border-b border-gray-200 dark:border-gray-700">
<div className="flex items-center justify-between">
<h2 className="text-base font-semibold text-gray-900 dark:text-white flex items-center gap-2">
<FaFileAlt className="w-5 h-5" />
{translate('::App.Intranet.Document')}
</h2>
</div>
</div>
<div className="divide-y divide-gray-200 dark:divide-gray-700">
{documents.length > 0 ? (
documents.slice(0, 3).map((doc) => (
<div
key={doc.id}
className="p-4 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors"
>
<div className="flex items-start gap-3">
<div className="p-2 bg-blue-100 dark:bg-blue-900/30 rounded-lg">
{getFileIcon(doc.extension)}
</div>
<div className="flex-1 min-w-0">
<h4
className="text-sm font-medium text-gray-900 dark:text-white truncate"
title={doc.name}
>
{baseNameOf(doc.name)}
</h4>
<p className="text-xs text-gray-600 dark:text-gray-400 mt-1">
{getFileType(doc.extension)}
<span className="mx-1">•</span>
{formatFileSize(doc.size)}
</p>
<div className="text-xs text-gray-500 dark:text-gray-400 mt-1 flex items-center gap-2">
<span>{dayjs(doc.modifiedAt).fromNow()}</span>
{doc.isReadOnly && (
<>
<span>•</span>
<span className="text-orange-500">
🔒 {translate('::App.Platform.ReadOnly')}
</span>
</>
)}
</div>
</div>
<Button
onClick={(e) => {
e.stopPropagation()
const url = FILE_URL(doc.path, doc.tenantId)
const link = document.createElement('a')
link.href = url
link.download = doc.name
link.target = '_blank'
link.rel = 'noopener noreferrer'
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
}}
size="sm"
variant="plain"
shape="none"
icon={
<FaDownload className="h-5 w-5 text-gray-600 transition-colors group-hover:text-blue-600 dark:text-gray-400 dark:group-hover:text-blue-400" />
}
className="group !h-9 !w-9 !rounded-lg !px-0 transition-colors hover:!bg-blue-100 dark:hover:!bg-blue-900/30"
title={translate('::App.Listform.ListformField.Download')}
/>
</div>
</div>
))
) : (
<div className="p-4 text-center text-sm text-gray-500 dark:text-gray-400">
{translate('::App.RecentDocuments.NoDocuments')}
</div>
)}
</div>
</div>
)
}
export const dashboardWidget: DashboardWidgetDefinition = {
id: 'documents',
render: ({ dashboard }) => <Documents documents={dashboard?.documents || []} />,
}
export default Documents