mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 09:36:08 +00:00
refactor: Update response handling for comments and uploads to access nested data structure
This commit is contained in:
@@ -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) {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user