diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6301f87..0a96281 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -38,3 +38,6 @@ jobs: - name: Build run: pnpm build + env: + NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }} + NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY: ${{ secrets.NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY }} diff --git a/apps/client/package.json b/apps/client/package.json index 18504ec..c6a7674 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -1,5 +1,5 @@ { - "name": "core", + "name": "client", "version": "0.1.0", "private": true, "scripts": { @@ -30,6 +30,7 @@ "posthog-js": "^1.217.4", "react": "^19.0.0", "react-dom": "^19.0.0", + "sonner": "^1.7.4", "tailwind-merge": "^3.0.1", "tailwindcss-animate": "^1.0.7" }, @@ -43,4 +44,4 @@ "tailwindcss": "^3.4.17", "typescript": "^5" } -} \ No newline at end of file +} diff --git a/apps/client/src/app/globals.css b/apps/client/src/app/globals.css index 6167036..33cb461 100644 --- a/apps/client/src/app/globals.css +++ b/apps/client/src/app/globals.css @@ -108,5 +108,8 @@ body { --sidebar-accent-foreground: 240 4.8% 95.9%; --sidebar-border: 240 3.7% 15.9%; --sidebar-ring: 217.2 91.2% 59.8%; + .cl-userButtonOuterIdentifier{ + color: white; + } } } diff --git a/apps/client/src/app/contributers/page.tsx b/apps/client/src/app/home/contributers/page.tsx similarity index 100% rename from apps/client/src/app/contributers/page.tsx rename to apps/client/src/app/home/contributers/page.tsx diff --git a/apps/client/src/app/fun/fan.tsx b/apps/client/src/app/home/fun/fan.tsx similarity index 100% rename from apps/client/src/app/fun/fan.tsx rename to apps/client/src/app/home/fun/fan.tsx diff --git a/apps/client/src/app/fun/layout.tsx b/apps/client/src/app/home/fun/layout.tsx similarity index 100% rename from apps/client/src/app/fun/layout.tsx rename to apps/client/src/app/home/fun/layout.tsx diff --git a/apps/client/src/app/fun/page.tsx b/apps/client/src/app/home/fun/page.tsx similarity index 100% rename from apps/client/src/app/fun/page.tsx rename to apps/client/src/app/home/fun/page.tsx diff --git a/apps/client/src/app/home/gallery/page.tsx b/apps/client/src/app/home/gallery/page.tsx new file mode 100644 index 0000000..4d165eb --- /dev/null +++ b/apps/client/src/app/home/gallery/page.tsx @@ -0,0 +1,61 @@ +"use client"; +import React from "react"; +import { FileVideo } from "lucide-react"; +import GalleryCard, { Video } from "@/components/home/videoCard"; +import { fetchUserObjects } from "@/utils"; + +const EmptyState = () => ( +
+ +

No videos yet

+

+ Upload your videos to see them displayed here +

+
+); + +export default function Page() { + const [data, setData] = React.useState([]); + const [loading, setLoading] = React.useState(true); + + React.useEffect(() => { + const loadData = async () => { + try { + const result = await fetchUserObjects(); + setData(result); + } catch (error) { + console.error("Failed to fetch videos:", error); + } finally { + setLoading(false); + } + }; + + loadData(); + }, []); + + if (loading) { + return ( +
+
Loading...
+
+ ); + } + + return ( +
+
+
+
+ {data && data.length > 0 ? ( + data.map((video, index) => ( + + )) + ) : ( + + )} +
+
+
+
+ ); +} diff --git a/apps/client/src/app/home/layout.tsx b/apps/client/src/app/home/layout.tsx index a1ec9ce..2503a61 100644 --- a/apps/client/src/app/home/layout.tsx +++ b/apps/client/src/app/home/layout.tsx @@ -1,5 +1,3 @@ -// TODO: Fix Dark and Light Mode - "use client"; import { AppSidebar } from "@/components/app-sidebar"; import { ReactNode, useEffect, useState } from "react"; @@ -9,41 +7,37 @@ import { SidebarProvider, SidebarTrigger, } from "@/components/ui/sidebar"; +import { ClerkProvider, SignedOut, SignIn } from "@clerk/nextjs"; +import { Toaster } from "@/components/ui/sonner"; +import TanstackProvider from "@/components/TanStackQuery/provider"; export default function Layout({ children }: { children: ReactNode }) { - // const { theme } = useTheme(); - const [mounted, setMounted] = useState(false); - - // Prevent hydration mismatch by mounting after first render - useEffect(() => { - setMounted(true); - }, []); - - // Default color while loading - const borderColor = ["#A07C", "#FE85", "#FBB"]; - - // const borderColor = mounted - // ? theme === "dark" - // ? "white" - // : "black" - // : "white"; - return ( - // - //
{children}
- - - -
-
- - + + {/* // ! Temp Show the page */} + +
+
-
-
{children}
-
-
- - //
+ + + + {/* */} + + + +
+
+ + +
+
+
{children}
+ +
+
+ {/*
*/} +
+ ); } diff --git a/apps/client/src/app/home/upload/page.tsx b/apps/client/src/app/home/upload/page.tsx index 175ac68..cb587f0 100644 --- a/apps/client/src/app/home/upload/page.tsx +++ b/apps/client/src/app/home/upload/page.tsx @@ -1,88 +1,9 @@ -'use client' -import { Router } from 'lucide-react' -import { useRouter } from 'next/navigation' -import React from 'react' - -const Admin = () => { - const [file, setFile] = React.useState() - const Router = useRouter(); - - const handleFileChange = (event: React.ChangeEvent) => { - if (event.target.files) { - const currentFile = event.target.files[0] - setFile(currentFile) - } - } - - const handleUpload = async () => { - if (!file) return; - const formData = new FormData(); - formData.append("files", file); - // Request signed URL from the server - const response = await fetch(`${process.env.NEXT_PUBLIC_SERVER_LINK}/api/fileupload`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: formData, - mode:"no-cors" - }) - } - - - return ( -
-
-

- Admin Panel -

-

- Upload the latest version of the video file. -

- -
-
- -
-
-
- -
-

- {file?.name ? file.name : 'Video files up to 1GB'} -

-
-
-
-
-
- -
-
-
- ) +import { UploadForm } from "@/components/upload/upload-form"; + +export default function UploadPage() { + return ( +
+ +
+ ); } - -export default Admin; \ No newline at end of file diff --git a/apps/client/src/app/home/video/page.tsx b/apps/client/src/app/home/video/page.tsx deleted file mode 100644 index c4280ac..0000000 --- a/apps/client/src/app/home/video/page.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import VideoGallery from '@/components/home/videoCard' -import { Button } from '@/components/ui/button'; -import Link from 'next/link'; -import React from 'react' - -function page() { - return ( -
- - -
- ) -} - -export default page \ No newline at end of file diff --git a/apps/client/src/app/layout.tsx b/apps/client/src/app/layout.tsx index 9e284d4..138d62f 100644 --- a/apps/client/src/app/layout.tsx +++ b/apps/client/src/app/layout.tsx @@ -6,7 +6,6 @@ import { Geist, Geist_Mono } from "next/font/google"; import "./globals.css"; import { Theme } from "@/components/theme"; import { PostHogProvider } from "@/components/posthog/providers"; -import TanstackProvider from "@/components/TanStackQuery/provider"; const geistSans = Geist({ variable: "--font-geist-sans", @@ -37,14 +36,12 @@ export default function RootLayout({ > - {children} - diff --git a/apps/client/src/app/page.tsx b/apps/client/src/app/page.tsx index b22012e..0ceae68 100644 --- a/apps/client/src/app/page.tsx +++ b/apps/client/src/app/page.tsx @@ -1,4 +1,5 @@ "use client"; +// ! Home Page import { Home as Main } from "@/components/home/index"; export default function Home() { return ( diff --git a/apps/client/src/components/TanStackQuery/provider.tsx b/apps/client/src/components/TanStackQuery/provider.tsx index f5848be..d560add 100644 --- a/apps/client/src/components/TanStackQuery/provider.tsx +++ b/apps/client/src/components/TanStackQuery/provider.tsx @@ -1,14 +1,11 @@ -"use client"; -import React from 'react' -import { QueryClient, QueryClientProvider } from '@tanstack/react-query' +import React from "react"; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; -function TanstackProvider({children}:{children: React.ReactNode}) { - const queryClient = new QueryClient() +function TanstackProvider({ children }: { children: React.ReactNode }) { + const queryClient = new QueryClient(); return ( - - {children} - - ) + {children} + ); } -export default TanstackProvider; \ No newline at end of file +export default TanstackProvider; diff --git a/apps/client/src/components/app-sidebar.tsx b/apps/client/src/components/app-sidebar.tsx index b66a0df..23598bc 100644 --- a/apps/client/src/components/app-sidebar.tsx +++ b/apps/client/src/components/app-sidebar.tsx @@ -1,20 +1,8 @@ -"use client"; - import * as React from "react"; -import { - AudioWaveform, - Command, - GalleryVerticalEnd, - Map, - PersonStandingIcon, - File, - Settings2, -} from "lucide-react"; +import { Map, PersonStandingIcon, File } from "lucide-react"; -import { NavMain } from "@/components/nav-main"; import { NavProjects } from "@/components/nav-projects"; import { NavUser } from "@/components/nav-user"; -import { TeamSwitcher } from "@/components/team-switcher"; import { Sidebar, SidebarContent, @@ -22,76 +10,80 @@ import { SidebarHeader, SidebarRail, } from "@/components/ui/sidebar"; -import FanIcon from "@/assests/icon/fan"; import { FanHandler } from "./common/FanHandler"; +import { useUser } from "@clerk/nextjs"; -// This is sample data. -const data = { - user: { - name: "Balaji Sriraman", - email: "balaji@mom.io", - avatar: "/avatars/shadcn.jpg", - }, - teams: [ - { - name: "Acme Inc", - logo: GalleryVerticalEnd, - plan: "Enterprise", - }, - { - name: "Acme Corp.", - logo: AudioWaveform, - plan: "Startup", - }, - { - name: "Evil Corp.", - logo: Command, - plan: "Free", - }, - ], - navMain: [ - { - title: "Playground", - url: "/", - icon: Settings2, +export function AppSidebar({ ...props }: React.ComponentProps) { + const { user } = useUser(); - isActive: true, - items: [ - { - title: "History", - url: "#", - }, - { - title: "Starred", - url: "#", - }, - { - title: "Settings", - url: "#", - }, - ], - }, - ], - projects: [ - { - name: "File Upload", - url: "/home/upload", - icon: File, - }, - { - name: "p2p Sharing", - url: "/home", - icon: PersonStandingIcon, - }, - { - name: "Video Streaming", - url: "/home/video", - icon: Map, + const data = { + projects: [ + { + name: "File Upload", + url: "/home/upload", + icon: File, + }, + { + name: "p2p Sharing", + url: "/home", + icon: PersonStandingIcon, + }, + { + name: "Video Streaming", + url: "/home/gallery", + icon: Map, + }, + ], + // TODO: v2 + // teams: [ + // { + // name: "Acme Inc", + // logo: GalleryVerticalEnd, + // plan: "Enterprise", + // }, + // { + // name: "Acme Corp.", + // logo: AudioWaveform, + // plan: "Startup", + // }, + // { + // name: "Evil Corp.", + // logo: Command, + // plan: "Free", + // }, + // ], + + // navMain: [ + // { + // title: "Playground", + // url: "/", + // icon: Settings2, + + // isActive: true, + // items: [ + // { + // title: "History", + // url: "#", + // }, + // { + // title: "Starred", + // url: "#", + // }, + // { + // title: "Settings", + // url: "#", + // }, + // ], + // }, + // ], + user: { + name: user?.fullName ?? "Guest User", + email: user?.primaryEmailAddress?.emailAddress ?? "", + avatar: user?.imageUrl ?? "", + guest: user ? false : true, }, - ], -}; + }; -export function AppSidebar({ ...props }: React.ComponentProps) { return ( diff --git a/apps/client/src/components/home/index.tsx b/apps/client/src/components/home/index.tsx index bc0d6dc..b8c4247 100644 --- a/apps/client/src/components/home/index.tsx +++ b/apps/client/src/components/home/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useState } from "react"; import { BackgroundLines } from "@/components/ui/background-lines"; -import { MagicBorderButton } from "@/components/ui/button/magic-border-button"; +import { MagicBorderButton } from "@/components/ui/button/home-magic-border-button"; import { CoolMode } from "@/components/ui/cool-mode"; import FanIcon from "@/assests/icon/fan"; import { useTheme } from "next-themes"; @@ -57,19 +57,7 @@ export function Home() { }} >
- -

{ - // Perform the action here - setTimeout(() => { - window.location.href = "/home"; - }, 2000); - }} - > - Turn on! -

-
+ Turn on!
diff --git a/apps/client/src/components/home/videoCard.tsx b/apps/client/src/components/home/videoCard.tsx index e8e54f5..4d146d9 100644 --- a/apps/client/src/components/home/videoCard.tsx +++ b/apps/client/src/components/home/videoCard.tsx @@ -1,28 +1,27 @@ "use client"; -import React, { useState, useRef, useEffect } from 'react'; -import { Card, CardContent } from '@/components/ui/card'; -import { FileVideo, Clock, HardDrive, Calendar } from 'lucide-react'; -import { useQuery } from '@tanstack/react-query'; -// Utility function to format file size +import React, { useState, useRef } from "react"; +import { FileVideo, Clock, HardDrive } from "lucide-react"; +import { Card, CardContent } from "../ui/card"; + +// Utility functions const formatFileSize = (bytes: number) => { - if (bytes === 0) return '0 Bytes'; + if (bytes === 0) return "0 Bytes"; const k = 1024; - const sizes = ['Bytes', 'KB', 'MB', 'GB']; + const sizes = ["Bytes", "KB", "MB", "GB"]; const i = Math.floor(Math.log(bytes) / Math.log(k)); return `${parseFloat((bytes / Math.pow(k, i)).toFixed(2))} ${sizes[i]}`; }; -// Utility function to format date const formatDate = (dateString: string) => { - return new Date(dateString).toLocaleDateString('en-US', { - year: 'numeric', - month: 'short', - day: 'numeric' + return new Date(dateString).toLocaleDateString("en-US", { + year: "numeric", + month: "short", + day: "numeric", }); }; -interface Video { +export interface Video { pathname?: string; contentType?: string; size: number; @@ -30,21 +29,21 @@ interface Video { uploadedAt: string; httpMetadata?: { contentType: string }; customMetadata?: {}; - // Added fields for user info - userName?: string; userAvatar?: string; description?: string; } -const VideoCard = ({ video }: { video: Video }) => { +const GalleryCard = ({ video }: { video: Video }) => { const [isHovering, setIsHovering] = useState(false); const videoRef = useRef(null); - const title = video.pathname?.split('.').slice(0, -1).join('.') || 'Untitled'; + const title = video.pathname?.split(".").slice(0, -1).join(".") || "Untitled"; const handleMouseEnter = () => { setIsHovering(true); if (videoRef.current) { - videoRef.current.play().catch(err => console.log('Video play failed:', err)); + videoRef.current + .play() + .catch((err) => console.log("Video play failed:", err)); } }; @@ -58,47 +57,31 @@ const VideoCard = ({ video }: { video: Video }) => { return ( - - {/* User Info Section */} -
-
- {video.userAvatar ? ( - {video.userName} - ) : ( -
- {(video.userName || 'U')[0].toUpperCase()} -
- )} -
-
-

{video.userName || 'Anonymous User'}

-

{formatDate(video.uploadedAt)}

-
-
- + {/* Video Preview Section */}
{isHovering ? ( -