|
1 | 1 | 'use client'; |
2 | 2 |
|
| 3 | +import { useApi } from '@/hooks/use-api'; |
3 | 4 | import { useCommentActions } from '@/hooks/use-comments-api'; |
4 | 5 | import { Avatar, AvatarFallback, AvatarImage } from '@comp/ui/avatar'; |
5 | 6 | import { Button } from '@comp/ui/button'; |
@@ -56,6 +57,7 @@ export function CommentItem({ comment, refreshComments }: CommentItemProps) { |
56 | 57 |
|
57 | 58 | // Use API hooks instead of server actions |
58 | 59 | const { updateComment, deleteComment } = useCommentActions(); |
| 60 | + const { get: apiGet } = useApi(); |
59 | 61 |
|
60 | 62 | const handleEditToggle = () => { |
61 | 63 | if (!isEditing) { |
@@ -105,6 +107,33 @@ export function CommentItem({ comment, refreshComments }: CommentItemProps) { |
105 | 107 | } |
106 | 108 | }; |
107 | 109 |
|
| 110 | + const handleAttachmentClick = async (attachmentId: string, fileName: string) => { |
| 111 | + try { |
| 112 | + // Generate fresh download URL on-demand using the useApi hook (with org context) |
| 113 | + const response = await apiGet<{ downloadUrl: string; expiresIn: number }>( |
| 114 | + `/v1/attachments/${attachmentId}/download`, |
| 115 | + ); |
| 116 | + |
| 117 | + if (response.error || !response.data?.downloadUrl) { |
| 118 | + console.error('API Error Details:', { |
| 119 | + status: response.status, |
| 120 | + error: response.error, |
| 121 | + data: response.data, |
| 122 | + }); |
| 123 | + throw new Error(response.error || 'API response missing downloadUrl'); |
| 124 | + } |
| 125 | + |
| 126 | + // Open the fresh URL in a new tab |
| 127 | + window.open(response.data.downloadUrl, '_blank', 'noopener,noreferrer'); |
| 128 | + } catch (error) { |
| 129 | + console.error('Error downloading attachment:', error); |
| 130 | + |
| 131 | + // Since we no longer pre-generate URLs, show user error when API fails |
| 132 | + console.error('No fallback available - URLs are only generated on-demand'); |
| 133 | + toast.error(`Failed to download ${fileName}`); |
| 134 | + } |
| 135 | + }; |
| 136 | + |
108 | 137 | return ( |
109 | 138 | <Card className="bg-foreground/5 rounded-lg"> |
110 | 139 | <CardContent className="text-foreground flex items-start gap-3 p-4"> |
@@ -175,9 +204,12 @@ export function CommentItem({ comment, refreshComments }: CommentItemProps) { |
175 | 204 | {comment.attachments.map((att) => ( |
176 | 205 | <div key={att.id} className="flex items-center gap-2 text-xs"> |
177 | 206 | <span>📎</span> |
178 | | - <span className="text-blue-600 hover:underline cursor-pointer"> |
| 207 | + <button |
| 208 | + onClick={() => handleAttachmentClick(att.id, att.name)} |
| 209 | + className="text-blue-600 hover:underline cursor-pointer text-left" |
| 210 | + > |
179 | 211 | {att.name} |
180 | | - </span> |
| 212 | + </button> |
181 | 213 | </div> |
182 | 214 | ))} |
183 | 215 | </div> |
|
0 commit comments