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 { useState } from 'react';
|
||||||
|
import { Button } from '@/components/ui/button';
|
||||||
import {
|
import {
|
||||||
Dialog,
|
Dialog,
|
||||||
DialogContent,
|
DialogContent,
|
||||||
DialogHeader,
|
DialogHeader,
|
||||||
DialogTitle,
|
DialogTitle,
|
||||||
} from '@/components/ui/dialog';
|
} from '@/components/ui/dialog';
|
||||||
|
import {
|
||||||
|
Tooltip,
|
||||||
|
TooltipContent,
|
||||||
|
TooltipTrigger,
|
||||||
|
} from '@/components/ui/tooltip';
|
||||||
import { cn } from '@/lib/utils';
|
import { cn } from '@/lib/utils';
|
||||||
|
|
||||||
const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
const IMAGE_EXTENSIONS = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
||||||
@ -19,12 +25,14 @@ type AttachmentPreviewDialogProps = {
|
|||||||
fileUrl: string;
|
fileUrl: string;
|
||||||
fileName: string;
|
fileName: string;
|
||||||
className?: string;
|
className?: string;
|
||||||
|
variant?: 'link' | 'icon';
|
||||||
};
|
};
|
||||||
|
|
||||||
export function AttachmentPreviewDialog({
|
export function AttachmentPreviewDialog({
|
||||||
fileUrl,
|
fileUrl,
|
||||||
fileName,
|
fileName,
|
||||||
className,
|
className,
|
||||||
|
variant = 'link',
|
||||||
}: AttachmentPreviewDialogProps) {
|
}: AttachmentPreviewDialogProps) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const extension = fileExtension(fileName);
|
const extension = fileExtension(fileName);
|
||||||
@ -34,17 +42,34 @@ export function AttachmentPreviewDialog({
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<button
|
{variant === 'icon' ? (
|
||||||
type="button"
|
<Tooltip>
|
||||||
onClick={() => setOpen(true)}
|
<TooltipTrigger asChild>
|
||||||
className={cn(
|
<Button
|
||||||
'inline-flex items-center gap-1 text-primary underline underline-offset-4 hover:text-primary/80',
|
type="button"
|
||||||
className,
|
variant="ghost"
|
||||||
)}
|
size="icon"
|
||||||
>
|
className={className}
|
||||||
<Paperclip className="h-3.5 w-3.5 shrink-0" />
|
onClick={() => setOpen(true)}
|
||||||
<span className="truncate">{fileName}</span>
|
>
|
||||||
</button>
|
<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}>
|
<Dialog open={open} onOpenChange={setOpen}>
|
||||||
<DialogContent
|
<DialogContent
|
||||||
|
|||||||
@ -27,7 +27,14 @@ export function createMaterialCard(params: CreateCardParams) {
|
|||||||
</Badge>
|
</Badge>
|
||||||
)}
|
)}
|
||||||
</div>
|
</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
|
<RowActions
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
@ -46,7 +53,7 @@ export function createMaterialCard(params: CreateCardParams) {
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
)}
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
@ -63,18 +70,6 @@ export function createMaterialCard(params: CreateCardParams) {
|
|||||||
? `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`
|
? `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`
|
||||||
: '-'}
|
: '-'}
|
||||||
</p>
|
</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>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -64,38 +64,27 @@ export function createMaterialColumns(
|
|||||||
return `${courseClass.course?.code ?? ''} ${courseClass.course?.name ?? ''}`;
|
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({
|
||||||
columns.push({
|
id: 'actions',
|
||||||
id: 'actions',
|
header: () => <span className="block text-center">Aksi</span>,
|
||||||
header: () => <span className="block text-center">Aksi</span>,
|
meta: {
|
||||||
meta: {
|
className: 'w-[130px] text-center',
|
||||||
className: 'w-[100px] text-center',
|
headerClassName: 'w-[130px] text-center',
|
||||||
headerClassName: 'w-[100px] text-center',
|
},
|
||||||
},
|
cell: ({ row }) => {
|
||||||
cell: ({ row }) => {
|
const material = row.original;
|
||||||
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
|
<RowActions
|
||||||
actions={[
|
actions={[
|
||||||
{
|
{
|
||||||
@ -114,10 +103,10 @@ export function createMaterialColumns(
|
|||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
/>
|
/>
|
||||||
);
|
</div>
|
||||||
},
|
);
|
||||||
});
|
},
|
||||||
}
|
});
|
||||||
|
|
||||||
return columns;
|
return columns;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user