refactor: Update response handling for comments and uploads to access nested data structure

This commit is contained in:
Yusuf İpek
2026-02-07 18:17:46 +03:00
parent f6044f3c24
commit 42839d4d69
3 changed files with 29 additions and 18 deletions
@@ -583,7 +583,8 @@ export default function VideoPage() {
}); });
if (res.ok) { if (res.ok) {
const newComment = await res.json(); const response = await res.json();
const newComment = response.data;
// Replace temp comment with real one // Replace temp comment with real one
setVideo((prev) => { setVideo((prev) => {
if (!prev) return prev; if (!prev) return prev;
@@ -704,7 +705,8 @@ export default function VideoPage() {
throw new Error('Failed to upload audio'); throw new Error('Failed to upload audio');
} }
const { url } = await uploadRes.json(); const uploadData = await uploadRes.json();
const { url } = uploadData.data;
// Submit comment with voice URL // Submit comment with voice URL
await handleAddComment({ url, duration: recordingTime }); await handleAddComment({ url, duration: recordingTime });
@@ -947,7 +949,8 @@ export default function VideoPage() {
}); });
if (res.ok) { if (res.ok) {
const newReply = await res.json(); const response = await res.json();
const newReply = response.data;
// Replace temp reply with real one // Replace temp reply with real one
setVideo((prev) => { setVideo((prev) => {
if (!prev) return prev; if (!prev) return prev;
@@ -1073,7 +1076,8 @@ export default function VideoPage() {
formData.append('audio', replyAudioBlob, 'recording.webm'); formData.append('audio', replyAudioBlob, 'recording.webm');
const uploadRes = await fetch('/api/upload/audio', { method: 'POST', body: formData }); const uploadRes = await fetch('/api/upload/audio', { method: 'POST', body: formData });
if (!uploadRes.ok) throw new Error('Failed to upload audio'); if (!uploadRes.ok) throw new Error('Failed to upload audio');
const { url } = await uploadRes.json(); const uploadData = await uploadRes.json();
const { url } = uploadData.data;
await handleReplyComment(parentId, { url, duration: replyRecordingTime }); await handleReplyComment(parentId, { url, duration: replyRecordingTime });
} catch (err) { } catch (err) {
console.error('Failed to submit voice reply:', err); console.error('Failed to submit voice reply:', err);
@@ -1647,17 +1651,17 @@ export default function VideoPage() {
)} )}
> >
<div className="flex items-start justify-between gap-2 mb-2"> <div className="flex items-start justify-between gap-2 mb-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2 min-w-0">
<Avatar className="h-6 w-6"> <Avatar className="h-6 w-6 shrink-0">
<AvatarImage src={comment.author?.image ?? undefined} /> <AvatarImage src={comment.author?.image ?? undefined} />
<AvatarFallback className="text-xs"> <AvatarFallback className="text-xs">
{authorName.charAt(0)} {authorName.charAt(0)}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
<span className="text-sm font-medium">{authorName}</span> <span className="text-sm font-medium truncate">{authorName}</span>
{comment.tag && ( {comment.tag && (
<span <span
className="text-[10px] font-medium px-2 py-0.5 rounded-full text-white" className="text-[10px] font-medium px-2 py-0.5 rounded-full text-white shrink-0"
style={{ backgroundColor: comment.tag.color }} style={{ backgroundColor: comment.tag.color }}
> >
{comment.tag.name} {comment.tag.name}
@@ -1665,7 +1669,7 @@ export default function VideoPage() {
)} )}
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1 shrink-0">
<button <button
onClick={() => handleSeekToTimestamp(comment.timestamp)} onClick={() => handleSeekToTimestamp(comment.timestamp)}
className="flex items-center gap-1 text-xs text-primary hover:underline px-1.5 py-0.5 rounded bg-primary/10 hover:bg-primary/20 transition-colors" className="flex items-center gap-1 text-xs text-primary hover:underline px-1.5 py-0.5 rounded bg-primary/10 hover:bg-primary/20 transition-colors"
@@ -1,4 +1,5 @@
import { NextRequest } from 'next/server'; import { NextRequest } from 'next/server';
import { revalidatePath } from 'next/cache';
import { db } from '@/lib/db'; import { db } from '@/lib/db';
import { auth } from '@/lib/auth'; import { auth } from '@/lib/auth';
import { ProjectMemberRole } from '@prisma/client'; import { ProjectMemberRole } from '@prisma/client';
@@ -165,6 +166,8 @@ export async function DELETE(request: NextRequest, { params }: RouteParams) {
await db.video.delete({ where: { id: videoId } }); await db.video.delete({ where: { id: videoId } });
revalidatePath(`/projects/${projectId}`);
const response = successResponse({ message: 'Video deleted' }); const response = successResponse({ message: 'Video deleted' });
return withCacheControl(response, 'private, no-store'); return withCacheControl(response, 'private, no-store');
} catch (error) { } catch (error) {
+13 -9
View File
@@ -539,7 +539,8 @@ export default function WatchPage() {
}); });
if (res.ok) { if (res.ok) {
const newComment = await res.json(); const response = await res.json();
const newComment = response.data;
// Replace temp comment with real one // Replace temp comment with real one
setVideo((prev) => { setVideo((prev) => {
if (!prev) return prev; if (!prev) return prev;
@@ -659,7 +660,8 @@ export default function WatchPage() {
throw new Error('Failed to upload audio'); throw new Error('Failed to upload audio');
} }
const { url } = await uploadRes.json(); const uploadData = await uploadRes.json();
const { url } = uploadData.data;
await handleAddComment({ url, duration: recordingTime }); await handleAddComment({ url, duration: recordingTime });
setAudioBlob(null); setAudioBlob(null);
setRecordingTime(0); setRecordingTime(0);
@@ -900,7 +902,8 @@ export default function WatchPage() {
}); });
if (res.ok) { if (res.ok) {
const newReply = await res.json(); const response = await res.json();
const newReply = response.data;
// Replace temp reply with real one // Replace temp reply with real one
setVideo((prev) => { setVideo((prev) => {
if (!prev) return prev; if (!prev) return prev;
@@ -1026,7 +1029,8 @@ export default function WatchPage() {
formData.append('audio', replyAudioBlob, 'recording.webm'); formData.append('audio', replyAudioBlob, 'recording.webm');
const uploadRes = await fetch('/api/upload/audio', { method: 'POST', body: formData }); const uploadRes = await fetch('/api/upload/audio', { method: 'POST', body: formData });
if (!uploadRes.ok) throw new Error('Failed to upload audio'); if (!uploadRes.ok) throw new Error('Failed to upload audio');
const { url } = await uploadRes.json(); const uploadData = await uploadRes.json();
const { url } = uploadData.data;
await handleReplyComment(parentId, { url, duration: replyRecordingTime }); await handleReplyComment(parentId, { url, duration: replyRecordingTime });
} catch (err) { } catch (err) {
console.error('Failed to submit voice reply:', err); console.error('Failed to submit voice reply:', err);
@@ -1484,17 +1488,17 @@ export default function WatchPage() {
)} )}
> >
<div className="flex items-start justify-between gap-2 mb-2"> <div className="flex items-start justify-between gap-2 mb-2">
<div className="flex items-center gap-2"> <div className="flex items-center gap-2 min-w-0">
<Avatar className="h-6 w-6"> <Avatar className="h-6 w-6 shrink-0">
<AvatarImage src={comment.author?.image ?? undefined} /> <AvatarImage src={comment.author?.image ?? undefined} />
<AvatarFallback className="text-xs"> <AvatarFallback className="text-xs">
{authorName.charAt(0)} {authorName.charAt(0)}
</AvatarFallback> </AvatarFallback>
</Avatar> </Avatar>
<span className="text-sm font-medium">{authorName}</span> <span className="text-sm font-medium truncate">{authorName}</span>
{comment.tag && ( {comment.tag && (
<span <span
className="text-[10px] font-medium px-1.5 py-0.5 rounded-full text-white" className="text-[10px] font-medium px-1.5 py-0.5 rounded-full text-white shrink-0"
style={{ backgroundColor: comment.tag.color }} style={{ backgroundColor: comment.tag.color }}
> >
{comment.tag.name} {comment.tag.name}
@@ -1502,7 +1506,7 @@ export default function WatchPage() {
)} )}
</div> </div>
<div className="flex items-center gap-1"> <div className="flex items-center gap-1 shrink-0">
<button <button
onClick={() => handleSeekToTimestamp(comment.timestamp)} onClick={() => handleSeekToTimestamp(comment.timestamp)}
className="flex items-center gap-1 text-xs text-primary hover:underline px-1.5 py-0.5 rounded bg-primary/10 hover:bg-primary/20 transition-colors" className="flex items-center gap-1 text-xs text-primary hover:underline px-1.5 py-0.5 rounded bg-primary/10 hover:bg-primary/20 transition-colors"