diff --git a/.env.development b/.env.development index 7bd2639..bd6f17f 100644 --- a/.env.development +++ b/.env.development @@ -1,5 +1,6 @@ NEXTAUTH_SECRET= sadsada -NEXTAPI_URL= http://localhost:3000 +NEXT_PUBLIC_BACKEND_URL = https://yoyo.dev.flamapp.com/ +# NEXT_PUBLIC_BACKEND_URL = http:/192.168.1.172:3000/ NEXT_PUBLIC_BACKEND_URL = https://yoyo.dev.flamapp.com/ NEXT_PUBLIC_ENV = development NEXT_PUBLIC_AVATURN_KEY= 1KpN2kSPr-2An7Vxi66yePiLv2NYTXRmS1AuDQqkEPf5_qUI6IHxb8KyOAdjHv_Ikf1tTsdWGsYZEJtvnTqu1Q \ No newline at end of file diff --git a/app/(protected)/avatars/loading.tsx b/app/(protected)/avatars/loading.tsx new file mode 100644 index 0000000..a388b3d --- /dev/null +++ b/app/(protected)/avatars/loading.tsx @@ -0,0 +1,12 @@ +import Spinner from "@/components/Spinner"; +import React from "react"; + +const Loading = () => { + return ( +
+ +
+ ); +}; + +export default Loading; diff --git a/app/(protected)/avatars/page-client.tsx b/app/(protected)/avatars/page-client.tsx index 2e6a5e6..6458acc 100644 --- a/app/(protected)/avatars/page-client.tsx +++ b/app/(protected)/avatars/page-client.tsx @@ -1,42 +1,26 @@ "use client"; +import Icon from "@/components/icons"; import CreateAvatarButton from "@/components/ui/avatars/create-avatar-button"; -import Content from "@/components/ui/dashboard/Content"; -import NoAvatars from "@/components/ui/home/No-avatars"; -import { getAvatars } from "@/lib/api/http"; +import Content from "@/components/ui/avatars/Content"; +import NoAvatars from "@/components/ui/avatars/No-avatars"; +import Link from "next/link"; -import React, { useEffect, useState } from "react"; +import React from "react"; const AvatarSelectClient = () => { - const [avatars, setAvatars] = useState([]); - const [show, setShow] = useState(true); - - useEffect(() => { - setTimeout(() => { - setShow(false); - }, 5000); - }, []); - - useEffect(() => { - const api = async () => { - const res = await getAvatars(); - console.log("res", res); - setAvatars(res); - return res; - }; - api(); - }, []); - return (
-
-

My Avatars

- {avatars.length !== 0 && } - {avatars.length === 0 && ( - - )} + {/*
*/} +
+ + + + My Avatars +
+ -
+ {/*
*/}
); }; diff --git a/app/(protected)/avatars/use-avatars.tsx b/app/(protected)/avatars/use-avatars.tsx new file mode 100644 index 0000000..0c5cb33 --- /dev/null +++ b/app/(protected)/avatars/use-avatars.tsx @@ -0,0 +1,15 @@ +import { getAvatars } from '@/lib/api/http'; +import useSwr from 'swr'; + +const useAvatars = () => { + const { data, mutate, isLoading, error } = useSwr('/avatars', getAvatars); + + return { + data: data as any, + mutate, + loading: isLoading, + error, + } +} + +export default useAvatars \ No newline at end of file diff --git a/app/(protected)/home/create/page-client.tsx b/app/(protected)/home/create/page-client.tsx new file mode 100644 index 0000000..72b67dc --- /dev/null +++ b/app/(protected)/home/create/page-client.tsx @@ -0,0 +1,41 @@ +"use client"; + +import React, { useEffect, useState } from "react"; +import { Button } from "@/components/ui/button"; +import Link from "next/link"; +import cookies from "js-cookie"; + +const img = + "https://s3-alpha-sig.figma.com/img/2192/9ade/96e419a040fe1b637d4964ddf4f4689f?Expires=1707696000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=Wzh9aCE5Oi5lAk9DFPMKEe~JiXKlDhmQ8jql01oqCftocD2aDjJxsn1ZZmeDtdSN5LauU64X6TpbAiFSZU-QY7wTvIXjvX-7GyZvX~9dxHPGuamFF04caDGZpgEgHphmax2YzFkK-Ee4lXtjAi2VDePRoUpb3HOg5WPju5jkYEJGEOlAWr5sccyPaZzW8X2A18Mvm5DM-HB1pyhphL~eEqu5h2HIcB9paL69eZ4Zr~75DfbaI6PXwMIPzTvcZ0~T9m~ooTFbpc8iUF5sQZ8MJ6qA2Mp6K0EA5lNR1pM~b3d0VJ6aGF2CWNTFY-XFY9bGpOQjXgJaJDxCTkfLyQk9Kg__"; + +const PageClient = () => { + const [avatarData, setAvatarData] = useState(null); + + useEffect(() => { + const data = cookies.get("__avatar") || null; + const aData = JSON.parse(data as any); + setAvatarData(aData); + }, []) + + return ( +
+ {"hello"} + + {" "} + Creating your video
It will be available in 5-10 minutes... +
+ + + +
+ ); +}; + +export default PageClient; diff --git a/app/(protected)/home/create/page.tsx b/app/(protected)/home/create/page.tsx index 74b7e8d..7b58982 100644 --- a/app/(protected)/home/create/page.tsx +++ b/app/(protected)/home/create/page.tsx @@ -1,35 +1,9 @@ -/* eslint-disable @next/next/no-img-element */ -import { Button } from "@/components/ui/button"; -import Image from "next/image"; -import Link from "next/link"; import React from "react"; - -const img = - "https://s3-alpha-sig.figma.com/img/2192/9ade/96e419a040fe1b637d4964ddf4f4689f?Expires=1707696000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=Wzh9aCE5Oi5lAk9DFPMKEe~JiXKlDhmQ8jql01oqCftocD2aDjJxsn1ZZmeDtdSN5LauU64X6TpbAiFSZU-QY7wTvIXjvX-7GyZvX~9dxHPGuamFF04caDGZpgEgHphmax2YzFkK-Ee4lXtjAi2VDePRoUpb3HOg5WPju5jkYEJGEOlAWr5sccyPaZzW8X2A18Mvm5DM-HB1pyhphL~eEqu5h2HIcB9paL69eZ4Zr~75DfbaI6PXwMIPzTvcZ0~T9m~ooTFbpc8iUF5sQZ8MJ6qA2Mp6K0EA5lNR1pM~b3d0VJ6aGF2CWNTFY-XFY9bGpOQjXgJaJDxCTkfLyQk9Kg__"; +import PageClient from "./page-client"; const Page = () => { return ( -
-
- {"hello"} -
- - {" "} - Creating your video
It will be available in 5-10 minutes... -
- - - -
+ ); }; diff --git a/app/(protected)/home/page-client.tsx b/app/(protected)/home/page-client.tsx index 70c64a2..bd65fb1 100644 --- a/app/(protected)/home/page-client.tsx +++ b/app/(protected)/home/page-client.tsx @@ -7,22 +7,40 @@ import Link from "next/link"; import React, { useState } from "react"; import { Button } from "@/components/ui/button"; import { useRouter } from "next/navigation"; +import cookies from "js-cookie"; +import { toast } from "sonner"; const HomeClient = ({ templates }: any) => { const item = templates[0]; - const [play, setPlay] = useState(false); - const [loading, setLoading] = useState(false) + const [loading, setLoading] = useState(false); + const [muted, setMuted] = useState(true); const router = useRouter(); - + const handleCreatevideo = async () => { - setLoading(true) - await createUserVideo(item?._id) - .then((res: any) => setLoading(false)) - .catch((err: any) => console.log(err)) + setLoading(true); + + const cookieData: any = cookies.get("__avatar") || null; + + const avatarData = JSON.parse(cookieData); + + if (!avatarData) { + toast.error("Select a Avatar first"); + setLoading(false); + router.replace("/avatars"); + return; + } - router.push('/home/create'); - } + await createUserVideo(item?._id, avatarData?.id) + .then((res: any) => { + router.replace("/home/create"); + setLoading(false); + }) + .catch((err: any) => { + toast.error("Error creating video"); + console.log(err); + }); + }; return (
@@ -39,43 +57,34 @@ const HomeClient = ({ templates }: any) => { > -
- {"hello"} -
- {play && ( - - )} +
- +
{item?.display_name} setPlay(!play)} + className="h-max bg-primary rounded-full text-black cursor-pointer p-1" + onClick={() => { + setMuted(!muted); + }} > - {play ? ( - + {muted ? ( + ) : ( - + )} - - {/* - - {item?.display_name} theme song - */} +
{/* Scroll to see next diff --git a/app/(protected)/home/page.tsx b/app/(protected)/home/page.tsx index 3741f4b..450a4b5 100644 --- a/app/(protected)/home/page.tsx +++ b/app/(protected)/home/page.tsx @@ -6,7 +6,7 @@ import { notFound } from "next/navigation"; export default async function Page() { const templates = await getTemplates(); - if(templates.length === 0 || !templates) { + if(templates?.length === 0 || !templates) { notFound(); } diff --git a/app/(protected)/layout.tsx b/app/(protected)/layout.tsx index 97b15fd..c830435 100644 --- a/app/(protected)/layout.tsx +++ b/app/(protected)/layout.tsx @@ -1,16 +1,13 @@ import { ReactNode } from "react"; -import AuthProvider from "@/lib/providers/AuthProvider"; import { Background } from "@/components/ui/background"; -export const dynamic = "force-static"; +// export const dynamic = "force-static"; export default function Layout({ children }: { children: ReactNode }) { return ( - -
- - {children} -
-
+
+ + {children} +
); } diff --git a/app/(protected)/videos/loading.tsx b/app/(protected)/videos/loading.tsx new file mode 100644 index 0000000..a388b3d --- /dev/null +++ b/app/(protected)/videos/loading.tsx @@ -0,0 +1,12 @@ +import Spinner from "@/components/Spinner"; +import React from "react"; + +const Loading = () => { + return ( +
+ +
+ ); +}; + +export default Loading; diff --git a/app/(protected)/videos/page-client.tsx b/app/(protected)/videos/page-client.tsx index ec0263e..0255413 100644 --- a/app/(protected)/videos/page-client.tsx +++ b/app/(protected)/videos/page-client.tsx @@ -1,41 +1,38 @@ "use client"; -import VideoContent from "@/components/ui/dashboard/VideoContent"; -import { getVideos } from "@/lib/api/http"; -import { useSession } from "next-auth/react"; -import React, { useEffect, useState } from "react"; +import Icon from "@/components/icons"; +import VideoContent from "@/components/ui/videos/VideoContent"; +import React from "react"; +import Link from "next/link"; +import { Button } from "@/components/ui/button"; +import useVideos from "./use-videos"; +import Spinner from "@/components/Spinner"; const VideosClient = () => { - const [videos, setVideos] = useState(null); - const [show, setShow] = useState(true); - - const session = useSession(); - - // useEffect(() => { - // setTimeout(() => { - // setShow(false); - // }, 5000); - // }, []); - - useEffect(() => { - const api = async () => { - const res = await getVideos(); - setVideos(res); - return res; - }; - api(); - }, [session]); - - console.log(videos); - + const { loading, mutate } = useVideos(); + return (
-

My Videos

- {/* Render Videos */} - - {/* */} -
+ + + + + {" "} + My Videos + + + + +
); }; diff --git a/app/(protected)/videos/use-videos.tsx b/app/(protected)/videos/use-videos.tsx new file mode 100644 index 0000000..e4f8968 --- /dev/null +++ b/app/(protected)/videos/use-videos.tsx @@ -0,0 +1,15 @@ +import { getVideos } from '@/lib/api/http'; +import { fetcher } from '@/lib/functions'; +import useSwr from 'swr'; + +const useVideos = () => { + const { data, error, mutate, isValidating } = useSwr('/videos', getVideos); + + return { + data: data as any, + mutate, + loading: (!data && !error || isValidating) ? true : false, + } +} + +export default useVideos \ No newline at end of file diff --git a/app/layout.tsx b/app/layout.tsx index bb1174e..8553782 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -4,6 +4,9 @@ import "./globals.css"; import { cn } from "@/lib/functions"; import { Toaster } from "@/components/ui/sonner"; import type { Viewport } from "next"; +import AuthProvider from "@/lib/providers/AuthProvider"; +import { Background } from "@/components/ui/background"; +import SWRProvider from "@/lib/providers/SwrProvider"; const maprope = Manrope({ subsets: ["latin"] }); @@ -28,8 +31,14 @@ export default function RootLayout({ }>) { return ( - - {children} + + + + + {children} + + + ); } diff --git a/components/Skeleton.tsx b/components/Skeleton.tsx index b7206d6..57e3900 100644 --- a/components/Skeleton.tsx +++ b/components/Skeleton.tsx @@ -8,7 +8,7 @@ function Skeleton({ return (
+ + {/* Loading... */} +
+ ); +} diff --git a/components/icons.tsx b/components/icons.tsx index 786407a..a6b5491 100644 --- a/components/icons.tsx +++ b/components/icons.tsx @@ -13,10 +13,13 @@ import { UserRound, Video, ChevronsUp, - PlayCircle, - PauseCircle, Home, + ArrowLeft, + VolumeX, + Volume2, + RotateCcw, } from "lucide-react"; +import { FaPause, FaPlay } from "react-icons/fa"; import { cn } from "@/lib/functions"; @@ -35,9 +38,13 @@ export const icons: IIcon = { avatar: UserRound, video: Video, doubleUp: ChevronsUp, - play: PlayCircle, - pause: PauseCircle, + play: FaPlay, + pause: FaPause, home: Home, + back: ArrowLeft, + muted: VolumeX, + unmute: Volume2, + refresh: RotateCcw }; const Icon = ({ diff --git a/components/ui/dashboard/Card.tsx b/components/ui/avatars/Card.tsx similarity index 69% rename from components/ui/dashboard/Card.tsx rename to components/ui/avatars/Card.tsx index 0a28c9d..e84a54d 100644 --- a/components/ui/dashboard/Card.tsx +++ b/components/ui/avatars/Card.tsx @@ -1,12 +1,19 @@ 'use client'; import { cn } from "@/lib/utils"; -import React from "react"; +import React, { useEffect, useState } from "react"; import Image from "next/image"; import cookies from 'js-cookie'; import Link from "next/link"; import { toast } from "sonner"; +const colours = [ + 'bg-[#C5FF1F]', + 'bg-[#ff66cc]', + 'bg-[#c3cdc7]', + 'bg-red-300' +] + const Card = ({ avatarData }: any) => { const handleCardSelect = () => { cookies.set( @@ -15,17 +22,26 @@ const Card = ({ avatarData }: any) => { id: avatarData?._id, gender: avatarData?.avatar_meta?.gender, url: avatarData?.avatar_url, - display_url: avatarData?.avatar_url, + display_url: avatarData?.profile_picture?.webp, }) ); toast.success("Avatar Selected !!"); } + const [id, setId] = useState(null); + + useEffect(() => { + const data = cookies.get("__avatar") || null; + const aData = JSON.parse(data as any); + setId(aData?.id); + }, []); + return ( @@ -37,12 +53,13 @@ const Card = ({ avatarData }: any) => { : "bg-yellow-500 opacity-30 animate-pulse" )} /> */} -
+
{avatarData?.profile_picture?.webp ? ( {"loading..."} { + const { data: avatars, loading, error } = useAvatars(); + + if (loading) { + return ( +
+ {Array.from({ length: 6 }).map((_item, index) => { + return + })} +
+ ); + } + + if(error) { + return ; + } + + if (!avatars || avatars.length === 0) { + return ; + } + + return ( +
+ {avatars.map((avatarData: any, index: number) => ( + + ))} +
+ ); +}; + +export default Content; diff --git a/components/ui/home/No-avatars.tsx b/components/ui/avatars/No-avatars.tsx similarity index 85% rename from components/ui/home/No-avatars.tsx rename to components/ui/avatars/No-avatars.tsx index 0d2c8bf..369b999 100644 --- a/components/ui/home/No-avatars.tsx +++ b/components/ui/avatars/No-avatars.tsx @@ -7,7 +7,7 @@ import React from "react"; const img = "https://s3-alpha-sig.figma.com/img/2192/9ade/96e419a040fe1b637d4964ddf4f4689f?Expires=1707696000&Key-Pair-Id=APKAQ4GOSFWCVNEHN3O4&Signature=Wzh9aCE5Oi5lAk9DFPMKEe~JiXKlDhmQ8jql01oqCftocD2aDjJxsn1ZZmeDtdSN5LauU64X6TpbAiFSZU-QY7wTvIXjvX-7GyZvX~9dxHPGuamFF04caDGZpgEgHphmax2YzFkK-Ee4lXtjAi2VDePRoUpb3HOg5WPju5jkYEJGEOlAWr5sccyPaZzW8X2A18Mvm5DM-HB1pyhphL~eEqu5h2HIcB9paL69eZ4Zr~75DfbaI6PXwMIPzTvcZ0~T9m~ooTFbpc8iUF5sQZ8MJ6qA2Mp6K0EA5lNR1pM~b3d0VJ6aGF2CWNTFY-XFY9bGpOQjXgJaJDxCTkfLyQk9Kg__"; -const NoAvatars = () => { +const NoAvatars = ({ error = false }: { error?: boolean}) => { return (
@@ -18,14 +18,14 @@ const NoAvatars = () => { alt={"hello"} />
-

No Avatars Available

- {error ? "Error Fetching Avatars" : "No Avatars Available"}

+ {!error && Create - + }
); }; diff --git a/components/ui/dashboard/Content.tsx b/components/ui/dashboard/Content.tsx deleted file mode 100644 index 9833cb0..0000000 --- a/components/ui/dashboard/Content.tsx +++ /dev/null @@ -1,14 +0,0 @@ -import React from "react"; -import Card from "./Card"; - -const Content = ({ avatars }: any) => { - return ( -
- {avatars.map((avatarData: any, index: number) => ( - - ))} -
- ); -}; - -export default Content; diff --git a/components/ui/dashboard/VideoCard.tsx b/components/ui/dashboard/VideoCard.tsx deleted file mode 100644 index 8541275..0000000 --- a/components/ui/dashboard/VideoCard.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { cn } from "@/lib/utils"; -import React, { useRef, useState } from "react"; -import { FaPause, FaPlay } from "react-icons/fa"; -import { MdPause, MdPlayArrow } from "react-icons/md"; - -const VideoCard = ({ videoData }: { videoData: any }) => { - const videoRef = useRef(null); - - const [isPlaying, setIsPlaying] = useState(false); - const handlePlayPause = () => { - if (videoRef?.current?.paused) { - videoRef.current.play(); - setIsPlaying(true); - } else { - videoRef.current.pause(); - setIsPlaying(false); - } - }; - - return ( -
- {videoData.status === "PROCESSED" ? ( -
-
- {isPlaying ? : } -
-
- ) : ( -
- Generating Video... -
- )} -
- ); -}; - -export default VideoCard; diff --git a/components/ui/dashboard/VideoContent.tsx b/components/ui/dashboard/VideoContent.tsx deleted file mode 100644 index 8e7b101..0000000 --- a/components/ui/dashboard/VideoContent.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import NoVideos from "./NoVideos"; -import VideoCard from "./VideoCard"; - -const VideoContent = ({ videos }: { videos: any }) => { - if (!videos || videos.length === 0) { - return ( -
- -
- ); - } - - return ( -
- {videos.map((videoData: any, index: number) => ( - - ))} -
- ); -}; - -export default VideoContent; diff --git a/components/ui/dialog.tsx b/components/ui/dialog.tsx new file mode 100644 index 0000000..95b0d38 --- /dev/null +++ b/components/ui/dialog.tsx @@ -0,0 +1,122 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { Cross2Icon } from "@radix-ui/react-icons" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/components/ui/form.tsx b/components/ui/form.tsx new file mode 100644 index 0000000..67927c9 --- /dev/null +++ b/components/ui/form.tsx @@ -0,0 +1,182 @@ +import * as React from "react"; +import * as LabelPrimitive from "@radix-ui/react-label"; +import { Slot } from "@radix-ui/react-slot"; +import { + Controller, + ControllerProps, + FieldPath, + FieldValues, + FormProvider, + useFormContext, +} from "react-hook-form"; + +import { cn } from "@/lib/utils"; +import { Label } from "@/components/ui/label"; +import { MdOutlineError } from "react-icons/md"; + +const Form = FormProvider; + +type FormFieldContextValue< + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +> = { + name: TName; +}; + +const FormFieldContext = React.createContext( + {} as FormFieldContextValue +); + +const FormField = < + TFieldValues extends FieldValues = FieldValues, + TName extends FieldPath = FieldPath +>({ + ...props +}: ControllerProps) => { + return ( + + + + ); +}; + +const useFormField = () => { + const fieldContext = React.useContext(FormFieldContext); + const itemContext = React.useContext(FormItemContext); + const { getFieldState, formState } = useFormContext(); + + const fieldState = getFieldState(fieldContext.name, formState); + + if (!fieldContext) { + throw new Error("useFormField should be used within "); + } + + const { id } = itemContext; + + return { + id, + name: fieldContext.name, + formItemId: `${id}-form-item`, + formDescriptionId: `${id}-form-item-description`, + formMessageId: `${id}-form-item-message`, + ...fieldState, + }; +}; + +type FormItemContextValue = { + id: string; +}; + +const FormItemContext = React.createContext( + {} as FormItemContextValue +); + +const FormItem = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes +>(({ className, ...props }, ref) => { + const id = React.useId(); + + return ( + +
+ + ); +}); +FormItem.displayName = "FormItem"; + +const FormLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + const { error, formItemId } = useFormField(); + + return ( +