From 3a14660c6d015f1ba5cba7207e42195302833ed1 Mon Sep 17 00:00:00 2001 From: Jessica Rekcah Date: Sat, 6 Dec 2025 10:05:58 +0700 Subject: [PATCH] update --- api_speed_test_results.txt | 29 +++ app/[locale]/(app)/dashboard/videos/page.tsx | 240 ++---------------- app/[locale]/auth/signup/page.tsx | 28 +- app/[locale]/page.tsx | 21 -- app/api/comments/[id]/toggle-privacy/route.ts | 110 ++++++++ app/api/comments/route.ts | 117 ++++++++- app/api/forums/[id]/route.ts | 19 +- bun.lock | 157 ++++++------ components/CommentComponent.tsx | 206 +++++++++++++++ components/CommentForm.tsx | 30 ++- components/VideoActions.tsx | 79 ++++++ components/VideoCard.tsx | 91 +++++++ components/VideoThumbnail.tsx | 125 +++++++++ components/index.ts | 12 +- messages/en.json | 6 +- messages/id.json | 8 +- package.json | 17 +- prisma/schema.prisma | 4 + 18 files changed, 940 insertions(+), 359 deletions(-) create mode 100644 api_speed_test_results.txt create mode 100644 app/api/comments/[id]/toggle-privacy/route.ts create mode 100644 components/CommentComponent.tsx create mode 100644 components/VideoActions.tsx create mode 100644 components/VideoCard.tsx create mode 100644 components/VideoThumbnail.tsx diff --git a/api_speed_test_results.txt b/api_speed_test_results.txt new file mode 100644 index 0000000..59ab186 --- /dev/null +++ b/api_speed_test_results.txt @@ -0,0 +1,29 @@ +API Speed Testing for z.ai coding plan +===================================== +Test started at: Fri Dec 5 11:29:04 PM WIB 2025 + +Running 10 tests... + +Test 1: Status: 200, Time: 1661.878000ms, Size: 50 bytes +Test 2: Status: 200, Time: 769.543000ms, Size: 50 bytes +Test 3: Status: 200, Time: 845.274000ms, Size: 50 bytes +Test 4: Status: 200, Time: 910.513000ms, Size: 50 bytes +Test 5: Status: 200, Time: 773.187000ms, Size: 50 bytes +Test 6: Status: 200, Time: 1002.836000ms, Size: 50 bytes +Test 7: Status: 200, Time: 752.075000ms, Size: 50 bytes +Test 8: Status: 200, Time: 739.803000ms, Size: 50 bytes +Test 9: Status: 200, Time: 1191.639000ms, Size: 50 bytes +Test 10: Status: 200, Time: 780.362000ms, Size: 50 bytes + +Statistics: +---------- +Average response time: 942.71ms +Minimum response time: 739.803000ms +Maximum response time: 1661.878000ms +Total tests: 10 +Test completed at: Fri Dec 5 11:29:23 PM WIB 2025 + +Performance Analysis: +------------------- +⚠️ Fair: Average response time under 1 second + diff --git a/app/[locale]/(app)/dashboard/videos/page.tsx b/app/[locale]/(app)/dashboard/videos/page.tsx index 6597973..f6ffe84 100644 --- a/app/[locale]/(app)/dashboard/videos/page.tsx +++ b/app/[locale]/(app)/dashboard/videos/page.tsx @@ -10,11 +10,11 @@ import { Link } from '@/i18n/routing'; import ActionButton from '@/components/ActionButton'; +import VideoCard from '@/components/VideoCard'; import { useFetch } from '@/hooks/useFetch'; import { useTranslations } from 'next-intl'; +import { Video } from 'lucide-react'; import { useState, useEffect } from 'react'; -import { generateYoutubeEmbedUrl } from '@/lib/youtube'; -import { PlayIcon } from 'lucide-react'; import { canUploadVideos } from '@/lib/admin'; interface VideoData extends Record { @@ -22,6 +22,7 @@ interface VideoData extends Record { title: string; description: string; videoType: 'YOUTUBE' | 'LOCAL'; + videoUrl: string; viewCount: number; createdAt: string; isPublic: boolean; @@ -35,9 +36,10 @@ interface VideoData extends Record { export default function VideosPage() { const t = useTranslations('Videos'); - const { data: videos, loading } = useFetch('/api/videos'); + const { data: videos, loading, refetch } = useFetch('/api/videos'); const [userProfile, setUserProfile] = useState(null); + useEffect(() => { // Fetch user profile to check permissions const fetchProfile = async () => { @@ -58,7 +60,7 @@ export default function VideosPage() { }, []); const handleDelete = async (videoId: string) => { - if (!confirm('Apakah Anda yakin ingin menghapus video ini?')) { + if (!confirm(t('confirmDelete'))) { return; } @@ -69,71 +71,20 @@ export default function VideosPage() { }); if (response.ok) { - // Refresh the videos list - window.location.reload(); + // Refresh videos list using refetch instead of window.reload + await refetch(); } else { - alert('Gagal menghapus video'); + alert(t('errorOccurred')); } } catch (error) { console.error('Error deleting video:', error); - alert('Gagal menghapus video'); + alert(t('errorOccurred')); } }; - const renderVideoActions = (video: any, userProfile: any, handleDelete: Function, t: Function) => { - const canEdit = userProfile && ( - userProfile.role?.name === 'ADMIN' || - userProfile.role?.name === 'PENDIDIK' || - video.uploaderId === userProfile.id - ); - - const canDelete = userProfile && ( - userProfile.role?.name === 'ADMIN' || - video.uploaderId === userProfile.id - ); - - return ( -
- - - - - {t('actionView')} - - - {canEdit && ( - - - - - {t('actionEdit')} - - )} - - {canDelete && ( - - )} -
- ); - }; - return (
+ {/* Header */}

{t('title')}

@@ -148,176 +99,29 @@ export default function VideosPage() { )}
+ {/* Loading State */} {loading ? (

{t('loading')}

) : videos && videos.length > 0 ? ( -
+ /* Video Grid */ +
{videos.map((video) => ( -
- {/* Video Thumbnail */} -
- {video.videoType === 'YOUTUBE' ? ( -