feat: enhance AttachmentPreviewDialog integration; add icon variant and improve file display in material cards
This commit is contained in:
parent
19397d3b5b
commit
facf7ab177
@ -1,11 +1,17 @@
|
||||
import { Paperclip } from 'lucide-react';
|
||||
import { Eye, Paperclip } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from '@/components/ui/dialog';
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui/tooltip';
|
||||
import { cn } from '@/lib/utils';
|
||||
|
||||
const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||
@ -19,12 +25,14 @@ type AttachmentPreviewDialogProps = {
|
||||
fileUrl: string;
|
||||
fileName: string;
|
||||
className?: string;
|
||||
variant?: 'link' | 'icon';
|
||||
};
|
||||
|
||||
export function AttachmentPreviewDialog({
|
||||
fileUrl,
|
||||
fileName,
|
||||
className,
|
||||
variant = 'link',
|
||||
}: AttachmentPreviewDialogProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
const extension = fileExtension(fileName);
|
||||
@ -34,17 +42,34 @@ export function AttachmentPreviewDialog({
|
||||
|
||||
return (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen(true)}
|
||||
className={cn(
|
||||
'inline-flex items-center gap-1 text-primary underline underline-offset-4 hover:text-primary/80',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<Paperclip className="h-3.5 w-3.5 shrink-0" />
|
||||
<span className="truncate">{fileName}</span>
|
||||
</button>
|
||||
{variant === 'icon' ? (
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="icon"
|
||||
className={className}
|
||||
onClick={() => setOpen(true)}
|
||||
>
|
||||
<Eye className="h-4 w-4" />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top">Lihat</TooltipContent>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setOpen(true)}
|
||||
className={cn(
|
||||
'inline-flex items-center gap-1 text-primary underline underline-offset-4 hover:text-primary/80',
|
||||
className,
|
||||
)}
|
||||
>
|
||||
<Paperclip className="h-3.5 w-3.5 shrink-0" />
|
||||
<span className="truncate">{fileName}</span>
|
||||
</button>
|
||||
)}
|
||||
|
||||
<Dialog open={open} onOpenChange={setOpen}>
|
||||
<DialogContent
|
||||
|
||||
@ -27,7 +27,14 @@ export function createMaterialCard(params: CreateCardParams) {
|
||||
</Badge>
|
||||
)}
|
||||
</div>
|
||||
{(canUpdate || canDelete) && (
|
||||
<div className="flex items-center">
|
||||
{material.file_url && material.file_name && (
|
||||
<AttachmentPreviewDialog
|
||||
fileUrl={material.file_url}
|
||||
fileName={material.file_name}
|
||||
variant="icon"
|
||||
/>
|
||||
)}
|
||||
<RowActions
|
||||
actions={[
|
||||
{
|
||||
@ -46,7 +53,7 @@ export function createMaterialCard(params: CreateCardParams) {
|
||||
},
|
||||
]}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
@ -63,18 +70,6 @@ export function createMaterialCard(params: CreateCardParams) {
|
||||
? `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`
|
||||
: '-'}
|
||||
</p>
|
||||
|
||||
{material.files.length > 0 && (
|
||||
<div className="flex flex-col gap-1">
|
||||
{material.files.map((file) => (
|
||||
<AttachmentPreviewDialog
|
||||
key={file.id}
|
||||
fileUrl={file.url}
|
||||
fileName={file.name}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@ -64,38 +64,27 @@ export function createMaterialColumns(
|
||||
return `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'file_name',
|
||||
header: () => <span>File</span>,
|
||||
cell: ({ row }) => {
|
||||
const material = row.original;
|
||||
|
||||
if (!material.file_url || !material.file_name) {
|
||||
return <span className="text-muted-foreground">-</span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<AttachmentPreviewDialog
|
||||
fileUrl={material.file_url}
|
||||
fileName={material.file_name}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
if (canUpdate || canDelete) {
|
||||
columns.push({
|
||||
id: 'actions',
|
||||
header: () => <span className="block text-center">Aksi</span>,
|
||||
meta: {
|
||||
className: 'w-[100px] text-center',
|
||||
headerClassName: 'w-[100px] text-center',
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
const material = row.original;
|
||||
columns.push({
|
||||
id: 'actions',
|
||||
header: () => <span className="block text-center">Aksi</span>,
|
||||
meta: {
|
||||
className: 'w-[130px] text-center',
|
||||
headerClassName: 'w-[130px] text-center',
|
||||
},
|
||||
cell: ({ row }) => {
|
||||
const material = row.original;
|
||||
|
||||
return (
|
||||
return (
|
||||
<div className="flex items-center justify-center">
|
||||
{material.file_url && material.file_name && (
|
||||
<AttachmentPreviewDialog
|
||||
fileUrl={material.file_url}
|
||||
fileName={material.file_name}
|
||||
variant="icon"
|
||||
/>
|
||||
)}
|
||||
<RowActions
|
||||
actions={[
|
||||
{
|
||||
@ -114,10 +103,10 @@ export function createMaterialColumns(
|
||||
},
|
||||
]}
|
||||
/>
|
||||
);
|
||||
},
|
||||
});
|
||||
}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return columns;
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user