Skip to content

Commit

Permalink
Merge pull request #2 from Eyevinn/setup-front-and-backend
Browse files Browse the repository at this point in the history
feat: add functionality to backend and build frontend
  • Loading branch information
JoeldelPilar authored Dec 11, 2024
2 parents 18a4341 + ff1aaf0 commit 60061ae
Show file tree
Hide file tree
Showing 25 changed files with 753 additions and 114 deletions.
309 changes: 220 additions & 89 deletions package-lock.json

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@
"fastify": "4.23.2",
"ioredis": "^5.4.1",
"next": "^14.2.15",
"nodemon": "^2.0.20",
"nodemon": "^3.1.7",
"openai": "^4.75.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"tailwind-merge": "^2.5.4",
Expand All @@ -42,7 +43,7 @@
"@commitlint/cli": "^17.4.2",
"@commitlint/config-conventional": "^17.4.2",
"@types/jest": "^29.4.0",
"@types/node": "^18.11.18",
"@types/node": "^18.19.67",
"@types/react": "^18.2.37",
"@types/react-dom": "^18.2.15",
"@typescript-eslint/eslint-plugin": "^5.51.0",
Expand All @@ -54,7 +55,7 @@
"jest": "^29.5.0",
"postcss": "^8",
"prettier": "^2.8.4",
"tailwindcss": "^3.4.1",
"tailwindcss": "^3.4.16",
"ts-jest": "^29.0.5",
"typescript": "^4.9.5"
}
Expand Down
Binary file not shown.
Binary file added public/fonts/Inter/Inter-Black.ttf
Binary file not shown.
Binary file added public/fonts/Inter/Inter-Bold.ttf
Binary file not shown.
Binary file added public/fonts/Inter/Inter-ExtraBold.ttf
Binary file not shown.
Binary file added public/fonts/Inter/Inter-ExtraLight.ttf
Binary file not shown.
Binary file added public/fonts/Inter/Inter-Light.ttf
Binary file not shown.
Binary file added public/fonts/Inter/Inter-Medium.ttf
Binary file not shown.
Binary file added public/fonts/Inter/Inter-Regular.ttf
Binary file not shown.
Binary file added public/fonts/Inter/Inter-SemiBold.ttf
Binary file not shown.
Binary file added public/fonts/Inter/Inter-Thin.ttf
Binary file not shown.
Binary file not shown.
Binary file added public/fonts/Level/LevelOne.otf
Binary file not shown.
2 changes: 1 addition & 1 deletion src/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ describe('api', () => {
const server = api({ title: 'my awesome service' });
const response = await server.inject({
method: 'GET',
url: '/'
url: '/api'
});
expect(response.statusCode).toBe(200);
expect(response.body).toBe('Hello, world! I am my awesome service');
Expand Down
63 changes: 59 additions & 4 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import swaggerUI from '@fastify/swagger-ui';
import { TypeBoxTypeProvider } from '@fastify/type-provider-typebox';
import { Static, Type } from '@sinclair/typebox';
import fastify, { FastifyPluginCallback } from 'fastify';
import { ErrorResponse } from './api/errors';
import { ReviewResponse, ReviewSchema } from './service/models';
import { generateReview } from './service/models/openai';

const HelloWorld = Type.String({
description: 'The magical words!'
Expand All @@ -12,7 +15,6 @@ const HelloWorld = Type.String({
export interface HealthcheckOptions {
title: string;
}

const healthcheck: FastifyPluginCallback<HealthcheckOptions> = (
fastify,
opts,
Expand All @@ -35,6 +37,59 @@ const healthcheck: FastifyPluginCallback<HealthcheckOptions> = (
next();
};

const ReviewRequestSchema = Type.Object({
githubUrl: Type.String({
format: 'url',
description: 'The GitHub repo URL to analyze'
})
});
type ReviewRequestBody = Static<typeof ReviewRequestSchema>;

export interface ReviewOptions {
title: string;
}

const createReview: FastifyPluginCallback<ReviewOptions> = (
fastify,
opts,
next
) => {
fastify.post<{
Body: ReviewRequestBody;
Reply: ReviewResponse | ErrorResponse;
}>(
'/review',
{
schema: {
description:
'Generate a review from a given GitHub repository URL using OpenAI',
body: ReviewRequestSchema,
response: {
200: ReviewSchema,
400: ErrorResponse,
500: ErrorResponse
}
}
},
async (request, reply) => {
const { githubUrl } = request.body;
try {
const review = await generateReview(githubUrl);
reply.send({ review });
} catch (error) {
if (error instanceof Error) {
reply
.status(500)
.send({ reason: `An error occurred: ${error.message}` });
} else {
reply.status(500).send({ reason: 'An unknown error occurred' });
}
}
}
);
next();
};

export interface ApiOptions {
title: string;
}
Expand All @@ -58,11 +113,11 @@ export default (opts: ApiOptions) => {
}
});
api.register(swaggerUI, {
routePrefix: '/docs'
routePrefix: '/api/docs'
});

api.register(healthcheck, { title: opts.title });
// register other API routes here
api.register(healthcheck, { prefix: '/api', title: opts.title });
api.register(createReview, { prefix: '/api/v1', title: opts.title });

return api;
};
164 changes: 164 additions & 0 deletions src/app/_components/Review.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
import { ReviewResponse } from '@/service/models';
import { Card, CardBody, CardHeader } from '@nextui-org/react';

type ReviewProps = {
review: ReviewResponse | undefined;
error: string;
};

export default function Review({ review, error }: ReviewProps) {
return (
<section>
{!error ? (
<Card className="max-w-[45rem] grow bg-stone-800 my-4 p-4 border border-zinc-600">
<CardHeader className="flex flex-col justify-start items-start">
<h2 className="text-2xl">Review of the Repository</h2>
<p className="text-sm italic">
NOTE! Some of the numbers do not match the actual values - this
because of limitations of the AI
</p>
</CardHeader>
<CardBody>
{review && (
<div>
<h3 className="text-xl mb-2">Repository Metadata</h3>
<ul>
<li>Title: {review.review.metadata.repository_name}</li>
<li>Creator: {review.review.metadata.creator}</li>
<li>
Last Commit Date: {review.review.metadata.last_commit_date}
</li>
<li>
Stars:{' '}
<span className="text-sky-500">
{review.review.metadata.stars}
</span>
</li>
<li>
Forks:{' '}
<span className="text-sky-500">
{review.review.metadata.forks}
</span>
</li>
<li>
Contributors:{' '}
<span className="text-sky-500">
{review.review.metadata.contributors}
</span>
</li>
</ul>
<h3 className="text-xl my-2">Scoring Criteria</h3>
<ul>
<li>
Code Quality:{' '}
<span className="text-sky-500">
{review.review.scoring_criteria.code_quality.score}
</span>
</li>
<li>
Security:{' '}
<span className="text-sky-500">
{review.review.scoring_criteria.security.score}
</span>
</li>
<li>
Documentation:{' '}
<span className="text-sky-500">
{review.review.scoring_criteria.documentation.score}
</span>
</li>
<li>
Project Structure and Testing:{' '}
<span className="text-sky-500">
{
review.review.scoring_criteria
.project_structure_and_testing.score
}
</span>
</li>
<li>
Version Control and Git Practices:{' '}
<span className="text-sky-500">
{
review.review.scoring_criteria
.version_control_and_git_practices.score
}
</span>
</li>
<li>
Overall Score:{' '}
<span className="text-sky-500">
{review.review.scoring_criteria.overall_score}
</span>
/100
</li>
</ul>
<h3 className="text-xl my-2">Feedback</h3>
<h4 className="text-lg my-2">Code Quality</h4>
<p className="text-sm">
{review.review.scoring_criteria.code_quality.feedback}
</p>
<h4 className="text-lg my-2">Security</h4>
<p className="text-sm">
{review.review.scoring_criteria.security.feedback}
</p>
<ul className="flex flex-col gap-2">
{review.review.scoring_criteria.security.vulnerabilities.map(
(v) => (
<li className="text-sm list-inside list-disc">
{v.dependency} - {v.version} - {v.issue}
</li>
)
)}
</ul>
<h4 className="text-lg my-2">Documentation</h4>
<p className="text-sm">
{review.review.scoring_criteria.documentation.feedback}
</p>
<h4 className="text-lg my-2">Project Structure and Testing</h4>
<p className="text-sm">
{
review.review.scoring_criteria.project_structure_and_testing
.feedback
}
</p>
<h4 className="text-lg my-2">
Version Control and Git Practices
</h4>
<p className="text-sm">
{
review.review.scoring_criteria
.version_control_and_git_practices.feedback
}
</p>

<h3 className="text-xl my-2">Suggestions for Improvement</h3>
<ul>
{review.review.suggestions_for_improvement.map(
(suggestion, index) => (
<li
className="text-sm list-disc list-inside list-item"
key={index}
>
{suggestion}
</li>
)
)}
</ul>
</div>
)}
</CardBody>
</Card>
) : (
<Card className="max-w-[45rem] grow bg-stone-800 my-4 p-4 border border-zinc-600">
<CardHeader>
<h2 className="text-2xl">Wopsie, something whent wrong!</h2>
</CardHeader>
<CardBody>
<p className="text-red-500 italic">{error}</p>
</CardBody>
</Card>
)}
</section>
);
}
Loading

0 comments on commit 60061ae

Please sign in to comment.