Skip to content

Commit

Permalink
ADDED: Review Page (wip but mostly up to standard); util router; remo…
Browse files Browse the repository at this point in the history
…ved exposed helper in apiHelper; update Account page;
  • Loading branch information
finnc0 committed Dec 17, 2022
1 parent bcf664f commit 62f7354
Show file tree
Hide file tree
Showing 13 changed files with 404 additions and 52 deletions.
18 changes: 13 additions & 5 deletions apps/web/components/AccGameplayItemExtended.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,23 +21,31 @@ interface Id {
id: string;
}
const AccGameplayItemExtended = ({ item, id }) => {
const [meta, setMeta] = useState();
const [meta, setMeta] = useState<String>();
const utils = trpc.useContext();
const deleteGameplayTrpc = trpc.gameplay.deleteGameplay.useMutation({
async onSuccess() {
await utils.gameplay.invalidate();
},
});
const { isLoading, data, refetch } = trpc.util.getYtVidDataFromId.useQuery(
{
videoId: id,
},
{
enabled: false,
},
);
const [componentLoading, setComponentLoading] = useState<boolean>(true);
const toast = useToast();
const getd = async () => {
const data = await getYtVidDataFromId(id);
setMeta(data);
refetch();
setMeta(data?.title);
setComponentLoading(false);
};
useEffect(() => {
getd();
}, [item]);
}, [item, data]);

const deleteGameplay = () => {
try {
Expand Down Expand Up @@ -75,7 +83,7 @@ const AccGameplayItemExtended = ({ item, id }) => {
fontSize={{ base: 0, sm: 0, md: 16, lg: 16 }}
fontWeight={'bold'}
>
{meta && meta.title.substring(0, 15) + '...'}
{meta && meta.substring(0, 15) + '...'}
</Text>
<Text fontSize={{ base: 0, sm: 0, md: 8, lg: 8 }}>
{item && item.youtubeUrl}
Expand Down
3 changes: 1 addition & 2 deletions apps/web/components/AccGameplayItems.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ import {
Image,
} from '@chakra-ui/react';
import { trpc } from '@utils/trpc';
import Loading from './Loading';
import { getYtVidDataFromId } from '@utils/helpers/apiHelper';
import AccGameplayItemExtended from './AccGameplayItemExtended';
interface Gameplay {
id: string;
Expand Down Expand Up @@ -72,6 +70,7 @@ const AccGameplayItems = () => {
mt={2}
boxShadow={'lg'}
borderRadius={14}
key={index}
>
<Center>
<Image
Expand Down
11 changes: 11 additions & 0 deletions apps/web/components/Finish.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';
import { Box, Center, Flex, Text, Button } from '@chakra-ui/react';
const Finish = () => {
return (
<div>
<Box>Congrats you finished</Box>
</div>
);
};

export default Finish;
3 changes: 0 additions & 3 deletions apps/web/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,6 @@ const nextConfig = {
images: {
domains: ['cdn.discordapp.com'],
},
env: {
YOUTUBE_API_KEY: process.env.YOUTUBE_API_KEY,
},
i18n: {
locales: ['en-US'],
defaultLocale: 'en-US',
Expand Down
204 changes: 202 additions & 2 deletions apps/web/pages/submissions/review.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,205 @@
import {
Box,
Center,
Text,
Flex,
Button,
Image,
chakra,
} from '@chakra-ui/react';
import { Session } from 'next-auth';
import { getSession } from 'next-auth/react';
import { useState, useEffect, ReactElement } from 'react';
import { useRouter } from 'next/router';
import Loading from '@components/Loading';
import Layout from '@components/Layout';
import Finish from '@components/Finish';
import { trpc } from '@utils/trpc';
export default function Review() {
const utils = trpc.useContext();
const { isLoading: reviewItemsLoading, data: reviewItemsData } =
trpc.gameplay.getReviewItems.useQuery({
amountToQuery: 20,
});

const reviewGameplay = trpc.gameplay.reviewGameplay.useMutation({
async onSuccess() {
await utils.gameplay.invalidate();
},
});

const [selectedItem, setSelectedItem] = useState<number>(0);
const [userSession, setUserSession] = useState<Session | undefined>();
const [reviewItems, setReviewItems] = useState(reviewItemsData);
const [loading, setLoading] = useState<boolean>(true);
const [finish, setFinish] = useState<boolean>(false);
const router = useRouter();
var videoIdFromUrlRegex =
/^.*(youtu\.be\/|v\/|u\/\w\/|embed\/|watch\?v=|\&v=)([^#\&\?]*).*/;
// format http://img.youtube.com/vi/[video-id]/[thumbnail-number].jpg
var youtubeThumbnailRetrievalUrl = 'http://img.youtube.com/vi/';
const getYtEmbedLink = (url: string) => {
var result = url.match(videoIdFromUrlRegex);
return `https://youtube.com/embed/${result[2]}`;
};

const getCurrentSession = async () => {
const session = await getSession();
if (session === null) {
router.push('/auth/login');
} else {
setUserSession(session);
setLoading(false);
}
};

const getNecessaryData = async () => {
if (!reviewItemsLoading) setReviewItems(reviewItemsData);
};

const doClickLogic = async (action: 'yes' | 'no') => {
setLoading(true);
let upVotes = null;
let downVotes = null;
if (action == 'yes') {
upVotes = 1;
} else {
downVotes = 1;
}
if (upVotes == null) {
await reviewGameplay.mutateAsync({
gameplayId: reviewItems[selectedItem].id,
downVotes: downVotes,
});
} else {
await reviewGameplay.mutateAsync({
gameplayId: reviewItems[selectedItem].id,
upVotes: upVotes,
});
}
if (selectedItem == reviewItems.length - 1) {
setFinish(true);
}
setSelectedItem(selectedItem + 1);
setLoading(false);
};

const handleYesClick = () => {
doClickLogic('yes');
};

const handleNoClick = () => {
doClickLogic('no');
};

useEffect(() => {
getCurrentSession();
getNecessaryData();
}, [reviewItemsData]);
return (
<div>Coming Soon!</div>
)
<div>
<Center h={'100vh'}>
{loading || reviewItemsLoading ? (
<Loading color={'default'} />
) : (
<>
{finish ? (
<Finish />
) : (
<Box bgColor={'white'} p={6} borderRadius={12}>
<Flex direction={'row'}>
{/* User Icon */}
<Box>
<Image
src={userSession?.user?.image}
w={54}
h={54}
borderRadius={28}
/>
</Box>
{/* Top titles */}
{reviewItems && (
<Flex
direction={'column'}
justifyContent={'center'}
fontSize={18}
ml={2}
>
<Text>
Submitted by&nbsp;
<chakra.span fontWeight={'bold'}>
{reviewItems[selectedItem].user?.name}
</chakra.span>
</Text>

<Text fontWeight={'bold'}>
Does this clip match gameplay from{' '}
<chakra.span fontWeight={'normal'}>
{reviewItems[selectedItem].footageType}
</chakra.span>
</Text>
</Flex>
)}
</Flex>
{/* Iframe */}
<Box mt={6}>
{/* we might want to find a alternative to iframe as it doesn't inherit styles from parent w chakra -ceri */}
{reviewItems && (
<iframe
src={getYtEmbedLink(reviewItems[selectedItem].youtubeUrl)}
style={{
borderRadius: 12,
width: '100%',
height: '42vh',
}}
/>
)}
</Box>
{/* Footer */}
<Flex mt={4} alignItems={'center'}>
<Text>
By answering you accept the{' '}
<chakra.span
fontWeight={'semibold'}
textDecoration={'underline'}
>
Terms of Service
</chakra.span>
</Text>
{/* Button */}
<Box ml={'auto'} right={0}>
<Button
color={'white'}
bgColor={'#373737'}
px={4}
_hover={{ bgColor: '#474747' }}
mr={3}
ml={3}
onClick={() => handleYesClick()}
>
Yes
</Button>
<Button
variant="outline"
color={'#373737'}
borderColor={'#373737'}
px={4}
_hover={{ bgColor: 'gray.300' }}
onClick={() => handleNoClick()}
>
No
</Button>
</Box>
</Flex>
</Box>
)}
</>
)}
</Center>
</div>
);
}

Review.getLayout = function getLayout(page: ReactElement) {
return <Layout>{page}</Layout>;
};
2 changes: 2 additions & 0 deletions apps/web/server/trpc/router/_app.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { router } from '../trpc';
import { gameplayRouter } from './gameplay';
import { userRouter } from './user';
import { utilRouter } from './util';

export const appRouter = router({
gameplay: gameplayRouter,
user: userRouter,
util: utilRouter,
});

// export type definition of API
Expand Down
76 changes: 75 additions & 1 deletion apps/web/server/trpc/router/gameplay.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { TRPCError } from '@trpc/server';
import ytdl from 'ytdl-core';
import { GameplaySchema, GameplayTypes } from '@utils/zod/gameplay';
import {
GameplayPlusUserSchema,
GameplaySchema,
GameplayTypes,
} from '@utils/zod/gameplay';
import { z } from 'zod';
import { router, protectedProcedure } from '../trpc';
import { SegmentSchema } from '@utils/zod/segment';
Expand Down Expand Up @@ -225,4 +229,74 @@ export const gameplayRouter = router({
});
}
}),
getReviewItems: protectedProcedure
.meta({ openapi: { method: 'GET', path: '/gameplay/review' } })
.input(
z.object({
amountToQuery: z.number(),
}),
)
.output(z.array(GameplayPlusUserSchema))
.query(async ({ input, ctx }) => {
const reviewItems = await ctx.prisma.footage.findMany({
take: input.amountToQuery,
include: {
user: true,
},
});
if (reviewItems === null)
throw new TRPCError({
code: 'NOT_FOUND',
message: `Could not query ${input.amountToQuery} gameplay documents`,
});

return reviewItems;
}),
reviewGameplay: protectedProcedure
.meta({ openapi: { method: 'PATCH', path: '/gameplay/review' } })
.input(
z.object({
gameplayId: z.string().cuid(),
upVotes: z.number().optional(),
downVotes: z.number().optional(),
}),
)
.output(z.object({ message: z.string() }))
.mutation(async ({ input, ctx }) => {
if (input.upVotes == null) {
const updateDownVotes = await ctx.prisma.footage.update({
where: {
id: input.gameplayId,
},
data: {
downVotes: {
increment: input.downVotes,
},
},
});
if (updateDownVotes === null)
throw new TRPCError({
code: 'NOT_FOUND',
message: `Could not find a gameplay document with id:${input.gameplayId}.`,
});
} else {
const updateUpVotes = await ctx.prisma.footage.update({
where: {
id: input.gameplayId,
},
data: {
upVotes: {
increment: input.upVotes,
},
},
});
if (updateUpVotes === null)
throw new TRPCError({
code: 'NOT_FOUND',
message: `Could not find a gameplay document with id:${input.gameplayId}.`,
});
}

return { message: 'Updated the gameplay document successfully.' };
}),
});
Loading

0 comments on commit 62f7354

Please sign in to comment.