diff --git a/prisma/migrations/20240830204152_/migration.sql b/prisma/migrations/20240830204152_/migration.sql new file mode 100644 index 000000000..8293c1666 --- /dev/null +++ b/prisma/migrations/20240830204152_/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "VideoMetadata" ADD COLUMN "original_mp4_url" TEXT, +ADD COLUMN "transcoded" BOOLEAN NOT NULL DEFAULT false; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 2ee969079..e614cf77e 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -122,6 +122,8 @@ model VideoMetadata { migrated_video_1080p_mp4_1 String? migrated_video_360p_mp4_1 String? migrated_video_720p_mp4_1 String? + original_mp4_url String? + transcoded Boolean @default(false) @@unique([contentId]) } diff --git a/src/app/api/github/callback/route.ts b/src/app/api/github/callback/route.ts index e75c1dc1b..f2f9563fd 100644 --- a/src/app/api/github/callback/route.ts +++ b/src/app/api/github/callback/route.ts @@ -1,71 +1,82 @@ -import prisma from "@/db"; -import { authOptions } from "@/lib/auth"; -import { getServerSession } from "next-auth"; -import { NextRequest, NextResponse } from "next/server"; +import prisma from '@/db'; +import { authOptions } from '@/lib/auth'; +import { getServerSession } from 'next-auth'; +import { NextRequest, NextResponse } from 'next/server'; export async function GET(req: NextRequest) { - const code = req.nextUrl.searchParams.get('code'); + const code = req.nextUrl.searchParams.get('code'); - const session = await getServerSession(authOptions); + const session = await getServerSession(authOptions); - if (!session?.user?.id || !code) { - return NextResponse.redirect(new URL('/payout-methods?error=invalid_session', req.url)); - } - - try { - // Exchange code for access token - const tokenResponse = await fetch('https://github.com/login/oauth/access_token', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - body: JSON.stringify({ - client_id: process.env.GITHUB_ID, - client_secret: process.env.GITHUB_SECRET, - code, - }), - }); + if (!session?.user?.id || !code) { + return NextResponse.redirect( + new URL('/payout-methods?error=invalid_session', req.url), + ); + } - const tokenData = await tokenResponse.json(); - console.log('Token data:', tokenData); + try { + // Exchange code for access token + const tokenResponse = await fetch( + 'https://github.com/login/oauth/access_token', + { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Accept: 'application/json', + }, + body: JSON.stringify({ + client_id: process.env.GITHUB_ID, + client_secret: process.env.GITHUB_SECRET, + code, + }), + }, + ); - if (tokenData.error) { - throw new Error(tokenData.error_description); - } + const tokenData = await tokenResponse.json(); + console.log('Token data:', tokenData); - // Get user info from GitHub - const userResponse = await fetch('https://api.github.com/user', { - headers: { - Authorization: `token ${tokenData.access_token}`, - }, - }); + if (tokenData.error) { + throw new Error(tokenData.error_description); + } - const userData = await userResponse.json(); - console.log('User data:', userData); + // Get user info from GitHub + const userResponse = await fetch('https://api.github.com/user', { + headers: { + Authorization: `token ${tokenData.access_token}`, + }, + }); - const existingLink = await prisma.gitHubLink.findUnique({ - where: { userId: session.user.id }, - }); + const userData = await userResponse.json(); + console.log('User data:', userData); - if (!existingLink) { - await prisma.gitHubLink.create({ - data: { - userId: session.user.id, - githubId: userData.id.toString(), - username: userData.login, - access_token: tokenData.access_token, - avatarUrl: userData.avatar_url, - profileUrl: userData.html_url, - }, - }); - } else { - return NextResponse.redirect(new URL('/payout-methods?github_linked=true', req.url)); - } + const existingLink = await prisma.gitHubLink.findUnique({ + where: { userId: session.user.id }, + }); - return NextResponse.redirect(new URL('/payout-methods?github_linked=true', req.url)); - } catch (error) { - console.error('Error linking GitHub:', error); - return NextResponse.redirect(new URL('/payout-methods?error=github_link_failed', req.url)); + if (!existingLink) { + await prisma.gitHubLink.create({ + data: { + userId: session.user.id, + githubId: userData.id.toString(), + username: userData.login, + access_token: tokenData.access_token, + avatarUrl: userData.avatar_url, + profileUrl: userData.html_url, + }, + }); + } else { + return NextResponse.redirect( + new URL('/payout-methods?github_linked=true', req.url), + ); } -} \ No newline at end of file + + return NextResponse.redirect( + new URL('/payout-methods?github_linked=true', req.url), + ); + } catch (error) { + console.error('Error linking GitHub:', error); + return NextResponse.redirect( + new URL('/payout-methods?error=github_link_failed', req.url), + ); + } +} diff --git a/src/app/api/github/details/route.ts b/src/app/api/github/details/route.ts index 80b89e1e3..5e94ca569 100644 --- a/src/app/api/github/details/route.ts +++ b/src/app/api/github/details/route.ts @@ -1,48 +1,68 @@ -import prisma from "@/db"; -import { authOptions } from "@/lib/auth"; -import { getServerSession } from "next-auth"; -import { NextResponse } from "next/server"; +import prisma from '@/db'; +import { authOptions } from '@/lib/auth'; +import { getServerSession } from 'next-auth'; +import { NextResponse } from 'next/server'; export async function GET() { - const session = await getServerSession(authOptions); - - if (!session) { - return NextResponse.json({ message: 'Unauthorised', success: 'false' }, { status: 401 }); - } - - const githubData = await prisma.gitHubLink.findMany({ - where: { - userId: session?.user?.id - }, - select: { - avatarUrl: true, - username: true, - profileUrl: true, - } - }); + const session = await getServerSession(authOptions); + + if (!session) { + return NextResponse.json( + { message: 'Unauthorised', success: 'false' }, + { status: 401 }, + ); + } - if (!githubData) { - return NextResponse.json({ message: "Couldn't find any Linked github", success: 'false' }); - } + const githubData = await prisma.gitHubLink.findMany({ + where: { + userId: session?.user?.id, + }, + select: { + avatarUrl: true, + username: true, + profileUrl: true, + }, + }); - return NextResponse.json({ message: "found data successsfully", data: githubData, success: 'true' }); + if (!githubData) { + return NextResponse.json({ + message: "Couldn't find any Linked github", + success: 'false', + }); + } + + return NextResponse.json({ + message: 'found data successsfully', + data: githubData, + success: 'true', + }); } export async function DELETE() { - const session = await getServerSession(authOptions); - - if (!session) { - return NextResponse.json({ message: 'Unauthorised', success: 'false' }, { status: 401 }); - } - - try { - await prisma.gitHubLink.delete({ - where: { - userId: session?.user?.id - }, - }); - return NextResponse.json({ message: "Github unlinked succeessfully", success: 'true' }); - } catch (error) { - return NextResponse.json({ message: "Something went wrong", error: error, success: 'false' }); - } -} \ No newline at end of file + const session = await getServerSession(authOptions); + + if (!session) { + return NextResponse.json( + { message: 'Unauthorised', success: 'false' }, + { status: 401 }, + ); + } + + try { + await prisma.gitHubLink.delete({ + where: { + userId: session?.user?.id, + }, + }); + return NextResponse.json({ + message: 'Github unlinked succeessfully', + success: 'true', + }); + } catch (error) { + return NextResponse.json({ + message: 'Something went wrong', + error, + success: 'false', + }); + } +} diff --git a/src/app/api/github/link/route.ts b/src/app/api/github/link/route.ts index e634dd2f9..34702a81b 100644 --- a/src/app/api/github/link/route.ts +++ b/src/app/api/github/link/route.ts @@ -1,11 +1,11 @@ -import { NextResponse } from "next/server"; +import { NextResponse } from 'next/server'; export async function GET() { - const clientId = process.env.GITHUB_ID; - const redirectUri = `${process.env.NEXTAUTH_URL}/api/github/callback`; - const scope = 'read:user user:email'; + const clientId = process.env.GITHUB_ID; + const redirectUri = `${process.env.NEXTAUTH_URL}/api/github/callback`; + const scope = 'read:user user:email'; - const githubAuthUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`; + const githubAuthUrl = `https://github.com/login/oauth/authorize?client_id=${clientId}&redirect_uri=${redirectUri}&scope=${scope}`; - return NextResponse.redirect(githubAuthUrl); -} \ No newline at end of file + return NextResponse.redirect(githubAuthUrl); +} diff --git a/src/app/payout-methods/page.tsx b/src/app/payout-methods/page.tsx index b4bfb05c8..c1ce928e2 100644 --- a/src/app/payout-methods/page.tsx +++ b/src/app/payout-methods/page.tsx @@ -2,15 +2,21 @@ import { useEffect, useState } from 'react'; import NewPayoutDialog from '@/components/NewPayoutDialog'; import { GitHubLinkButton } from '@/components/GitHubLinkButton'; -import SOL from "../../../public/platform/sol.svg" -import UPI from "../../../public/platform/upi.svg" +import SOL from '../../../public/platform/sol.svg'; +import UPI from '../../../public/platform/upi.svg'; import { PayoutMethodCard } from '@/components/PaymentMethodCard'; import { usePayoutMethods } from '@/hooks/usePayoutMethod'; export default function Page() { const [isDialogBoxOpen, setIsDialogBoxOpen] = useState(false); const [btnClicked, setBtnClicked] = useState(''); - const { upiAddresses, solanaAddresses, handleUpiDelete, handleSolanaDelete, fetchPayoutMethods } = usePayoutMethods(); + const { + upiAddresses, + solanaAddresses, + handleUpiDelete, + handleSolanaDelete, + fetchPayoutMethods, + } = usePayoutMethods(); const openDialog = (method: string) => { setIsDialogBoxOpen(true); @@ -19,18 +25,20 @@ export default function Page() { useEffect(() => { fetchPayoutMethods(); - }, [isDialogBoxOpen]) + }, [isDialogBoxOpen]); const closeDialog = () => setIsDialogBoxOpen(false); return (
-
-

Payout Methods

+
+

+ Payout Methods +

-
+
-
-

Apps

-
+
+

Apps

+
-
-
); diff --git a/src/components/GitHubLinkButton.tsx b/src/components/GitHubLinkButton.tsx index 79ae33253..7d31de35f 100644 --- a/src/components/GitHubLinkButton.tsx +++ b/src/components/GitHubLinkButton.tsx @@ -2,15 +2,14 @@ import { useRouter, useSearchParams } from 'next/navigation'; import { useEffect, useState } from 'react'; import { toast } from 'sonner'; -import { Dialog, DialogTrigger, DialogContent } from "@/components/ui/dialog" -import { Button } from "@/components/ui/button" -import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar" +import { Dialog, DialogTrigger, DialogContent } from '@/components/ui/dialog'; +import { Button } from '@/components/ui/button'; +import { Avatar, AvatarImage, AvatarFallback } from '@/components/ui/avatar'; import Image from 'next/image'; -import GITHUB from "../../public/platform/github.svg"; +import GITHUB from '../../public/platform/github.svg'; import Link from 'next/link'; import { GitHubLink } from '@prisma/client'; - export const GitHubLinkButton = () => { const [isProcessing, setIsProcessing] = useState(false); const [githubData, setGithubData] = useState(null); @@ -19,43 +18,39 @@ export const GitHubLinkButton = () => { useEffect(() => { if (searchParams.get('github_linked') === 'true') { - router.push('/payout-methods') - toast.success('Github account linked successfully') + router.push('/payout-methods'); + toast.success('Github account linked successfully'); } else if (searchParams.get('error') === 'github_link_failed') { - toast.error("Couldn't link with your github , Try again after sometime") + toast.error("Couldn't link with your github , Try again after sometime"); } }, [searchParams]); const getGithubData = async () => { const response = await fetch('/api/github/details'); - const resp = await response.json() + const resp = await response.json(); setGithubData(resp.data[0]); - } - + }; const handleUnlinkAccount = async () => { setIsProcessing(true); const response = await fetch('/api/github/details', { - method: 'DELETE' + method: 'DELETE', }); setIsProcessing(false); - const resp = await response.json() + const resp = await response.json(); console.log(resp); if (resp.success) { toast.success(resp.message); - getGithubData() - } - else { + getGithubData(); + } else { toast.error(resp.message); } - } - - + }; useEffect(() => { - // fetch the saved github linked data - getGithubData() - }, [searchParams]) + // fetch the saved github linked data + getGithubData(); + }, [searchParams]); const handleLinkGitHub = async () => { setIsProcessing(true); @@ -64,67 +59,92 @@ export const GitHubLinkButton = () => { return ( <> -
+

Github

-

Link your Github account

+

+ Link your Github account +

-
+
{githubData ? ( -
+
{/* {githubData?.avatarUrl} */} - -
- + CN
-

@{githubData?.username}

- {githubData?.profileUrl} +

+ @{githubData?.username} +

+ + {githubData?.profileUrl} + {/*

@oliviadavis

*/}
-
-
) : ( - )}
-
+
Landscape
diff --git a/src/components/NewPayoutDialog.tsx b/src/components/NewPayoutDialog.tsx index 2cde1edde..8509446f5 100644 --- a/src/components/NewPayoutDialog.tsx +++ b/src/components/NewPayoutDialog.tsx @@ -15,7 +15,6 @@ import { DialogContent, DialogHeader, DialogTitle, - DialogTrigger, } from '@/components/ui/dialog'; interface DialogProps { @@ -105,22 +104,20 @@ export default function NewPayoutDialog({ {errors[fieldName] && ( -

- {errors[fieldName]?.message} -

- )} +

+ {errors[fieldName]?.message} +

+ )}
- - ); } diff --git a/src/components/PaymentMethodCard.tsx b/src/components/PaymentMethodCard.tsx index 01f30a438..50bc00d90 100644 --- a/src/components/PaymentMethodCard.tsx +++ b/src/components/PaymentMethodCard.tsx @@ -1,66 +1,79 @@ import React from 'react'; import Image from 'next/image'; import { Button } from '@/components/ui/button'; -import { Dialog, DialogTrigger } from "@/components/ui/dialog"; +import { Dialog, DialogTrigger } from '@/components/ui/dialog'; import { ViewAllDialog } from './ViewAllDialog'; interface PayoutMethodCardProps { - title: string; - description: string; - imageSrc: string; - addresses: | Array<{ + title: string; + description: string; + imageSrc: string; + addresses: + | Array<{ id: number; value: string; userId: string; - }> + }> | undefined; - onAdd: (method: string) => void; - id: string; - onDelete: (id: number) => void; + onAdd: (method: string) => void; + id: string; + onDelete: (id: number) => void; } export const PayoutMethodCard: React.FC = ({ - title, - description, - imageSrc, - addresses, - onAdd, - id, - onDelete + title, + description, + imageSrc, + addresses, + onAdd, + id, + onDelete, }) => { - return ( -
-
-

{title}

-

{description}

-
+ return ( +
+
+

{title}

+

{description}

+
-
- +
+ - {addresses?.length !== 0 && ( - - - - - - - )} -
+ {addresses?.length !== 0 && ( + + + + + + + )} +
-
- {title} -
-
- ); -}; \ No newline at end of file +
+ {title} +
+
+ ); +}; diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index 2fc6b68fa..b5accb49b 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -155,7 +155,7 @@ export function Sidebar({ <> {sidebarOpen && (
-
+

Course Content

{ diff --git a/src/components/ViewAllDialog.tsx b/src/components/ViewAllDialog.tsx index 2c1463fb0..52f7f8ed9 100644 --- a/src/components/ViewAllDialog.tsx +++ b/src/components/ViewAllDialog.tsx @@ -1,28 +1,35 @@ import React from 'react'; import { Button } from '@/components/ui/button'; -import { DialogContent, DialogHeader } from "@/components/ui/dialog"; +import { DialogContent, DialogHeader } from '@/components/ui/dialog'; import { TrashIcon } from 'lucide-react'; import { toast } from 'sonner'; interface ViewAllDialogProps { title: string; - addresses: | Array<{ - id: number; - value: string; - userId: string; - }> - | undefined; + addresses: + | Array<{ + id: number; + value: string; + userId: string; + }> + | undefined; onDelete: (id: number) => void; } -export const ViewAllDialog: React.FC = ({ title, addresses, onDelete }) => { +export const ViewAllDialog: React.FC = ({ + title, + addresses, + onDelete, +}) => { return ( - +

{title}

- Click on address to copy + + Click on address to copy +
@@ -30,13 +37,22 @@ export const ViewAllDialog: React.FC = ({ title, addresses, {addresses?.length !== 0 ? ( addresses?.map((address, index) => (
-
{ - navigator.clipboard.writeText(address.value); - toast.success('Copied to clipboard') - }}> -

{address.value.slice(0, 20)}...

+
{ + navigator.clipboard.writeText(address.value); + toast.success('Copied to clipboard'); + }} + > +

+ {address.value.slice(0, 20)}... +

- @@ -50,4 +66,4 @@ export const ViewAllDialog: React.FC = ({ title, addresses,
); -}; \ No newline at end of file +}; diff --git a/src/hooks/usePayoutMethod.ts b/src/hooks/usePayoutMethod.ts index fde3aefcc..73421d26a 100644 --- a/src/hooks/usePayoutMethod.ts +++ b/src/hooks/usePayoutMethod.ts @@ -1,55 +1,57 @@ -"use client"; +'use client'; import { useState, useEffect } from 'react'; import { useAction } from '@/hooks/useAction'; import { toast } from 'sonner'; import { - deleteSolanaAddress, - deleteUpiId, - getPayoutMethods, + deleteSolanaAddress, + deleteUpiId, + getPayoutMethods, } from '@/actions/payoutMethods'; import { SolanaAddress, UpiId } from '@prisma/client'; export const usePayoutMethods = () => { - const [upiAddresses, setUpiAddresses] = useState([]); - const [solanaAddresses, setSolanaAddresses] = useState([]); + const [upiAddresses, setUpiAddresses] = useState([]); + const [solanaAddresses, setSolanaAddresses] = useState< + SolanaAddress[] | undefined + >([]); - const fetchPayoutMethods = async () => { - const result = await getPayoutMethods(); - if (result) { - setUpiAddresses(result.upiIds); - setSolanaAddresses(result.solanaAddresses); - } - }; + const fetchPayoutMethods = async () => { + const result = await getPayoutMethods(); + if (result) { + setUpiAddresses(result.upiIds); + setSolanaAddresses(result.solanaAddresses); + } + }; - const { execute: executeDeleteUPI } = useAction(deleteUpiId, { - onSuccess: () => { - toast.success('UPI Address deleted successfully'); - fetchPayoutMethods(); - }, - onError: () => { - toast.error('Failed to delete UPI id'); - }, - }); + const { execute: executeDeleteUPI } = useAction(deleteUpiId, { + onSuccess: () => { + toast.success('UPI Address deleted successfully'); + fetchPayoutMethods(); + }, + onError: () => { + toast.error('Failed to delete UPI id'); + }, + }); - const { execute: executeDeleteSolana } = useAction(deleteSolanaAddress, { - onSuccess: () => { - toast.success('Solana Address deleted successfully'); - fetchPayoutMethods(); - }, - onError: () => { - toast.error('Failed to delete Solana address'); - }, - }); + const { execute: executeDeleteSolana } = useAction(deleteSolanaAddress, { + onSuccess: () => { + toast.success('Solana Address deleted successfully'); + fetchPayoutMethods(); + }, + onError: () => { + toast.error('Failed to delete Solana address'); + }, + }); - useEffect(() => { - fetchPayoutMethods(); - }, []); + useEffect(() => { + fetchPayoutMethods(); + }, []); - return { - upiAddresses, - solanaAddresses, - fetchPayoutMethods, - handleUpiDelete: (id: number) => executeDeleteUPI({ id }), - handleSolanaDelete: (id: number) => executeDeleteSolana({ id }), - }; -}; \ No newline at end of file + return { + upiAddresses, + solanaAddresses, + fetchPayoutMethods, + handleUpiDelete: (id: number) => executeDeleteUPI({ id }), + handleSolanaDelete: (id: number) => executeDeleteSolana({ id }), + }; +}; diff --git a/tsconfig.json b/tsconfig.json index cec286f06..1f308869a 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,14 +16,14 @@ "incremental": true, "plugins": [ { - "name": "next", - }, + "name": "next" + } ], "paths": { "@/*": ["./src/*"], - "@public/*": ["./public/*"], - }, + "@public/*": ["./public/*"] + } }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"], + "exclude": ["node_modules"] }