mirror of
https://github.com/Crosstalk-Solutions/project-nomad.git
synced 2026-03-28 03:29:25 +01:00
- Add i18next, react-i18next, i18next-browser-languagedetector packages - Configure i18n initialization with language detector in lib/i18n.ts - Created en/de translation files and moved most hard-coded strings into the files and translated them - Uses locale-aware date formatting where applicable - Added language-specific Wikipedia content files (wikipedia.en.json, wikipedia.de.json) and updated download URLs - Added NOMAD_REPO_URL env variable for fork-friendly URL resolution (easier testing and rollout independent of Crosstalk repo)
61 lines
2.2 KiB
TypeScript
61 lines
2.2 KiB
TypeScript
import { formatBytes } from '~/lib/util'
|
|
import { useTranslation } from 'react-i18next'
|
|
import DynamicIcon, { DynamicIconName } from './DynamicIcon'
|
|
import type { CollectionWithStatus } from '../../types/collections'
|
|
import classNames from 'classnames'
|
|
import { IconCircleCheck } from '@tabler/icons-react'
|
|
|
|
export interface CuratedCollectionCardProps {
|
|
collection: CollectionWithStatus
|
|
onClick?: (collection: CollectionWithStatus) => void;
|
|
size?: 'small' | 'large'
|
|
}
|
|
|
|
const CuratedCollectionCard: React.FC<CuratedCollectionCardProps> = ({ collection, onClick, size = 'small' }) => {
|
|
const { t } = useTranslation()
|
|
const totalSizeBytes = collection.resources?.reduce(
|
|
(acc, resource) => acc + resource.size_mb * 1024 * 1024,
|
|
0
|
|
)
|
|
return (
|
|
<div
|
|
className={classNames(
|
|
'flex flex-col bg-desert-green rounded-lg p-6 text-white border border-b-desert-green shadow-sm hover:shadow-lg transition-shadow cursor-pointer',
|
|
{ 'opacity-65 cursor-not-allowed !hover:shadow-sm': collection.all_installed },
|
|
{ 'h-56': size === 'small', 'h-80': size === 'large' }
|
|
)}
|
|
onClick={() => {
|
|
if (collection.all_installed) {
|
|
return
|
|
}
|
|
if (onClick) {
|
|
onClick(collection)
|
|
}
|
|
}}
|
|
>
|
|
<div className="flex items-center mb-4">
|
|
<div className="flex justify-between w-full items-center">
|
|
<div className="flex">
|
|
<DynamicIcon icon={collection.icon as DynamicIconName} className="w-6 h-6 mr-2" />
|
|
<h3 className="text-lg font-semibold">{collection.name}</h3>
|
|
</div>
|
|
{collection.all_installed && (
|
|
<div className="flex items-center">
|
|
<IconCircleCheck
|
|
className="w-5 h-5 text-lime-400 ml-2"
|
|
title={t('common.allItemsDownloaded')}
|
|
/>
|
|
<p className="text-lime-400 text-sm ml-1">{t('common.allItemsDownloaded')}</p>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
<p className="text-gray-200 grow">{collection.description}</p>
|
|
<p className="text-gray-200 text-xs mt-2">
|
|
{t('common.items', { count: collection.resources?.length, size: formatBytes(totalSizeBytes, 0) })}
|
|
</p>
|
|
</div>
|
|
)
|
|
}
|
|
export default CuratedCollectionCard
|