Skip to content

Commit

Permalink
Merge pull request #8 from Kevin-Umali/feature/TL-DYS-23
Browse files Browse the repository at this point in the history
[TL-DYS-23] [TL-DYS-35] Implemented generated idea counter
  • Loading branch information
poorsyaaa authored Sep 24, 2023
2 parents fb96d65 + 81b174f commit 6cfc64e
Show file tree
Hide file tree
Showing 15 changed files with 189 additions and 1,481 deletions.
1,324 changes: 0 additions & 1,324 deletions README.md

Large diffs are not rendered by default.

57 changes: 57 additions & 0 deletions client/src/api/backend-api.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { ProjectLocationState, RelatedImages } from "../types";

const API_URL = process.env.NODE_ENV === "development" ? "http://localhost:3000/api" : import.meta.env.VITE_OPEN_AI_API_URL;

const fetchApi = async (endpoint: string, method: string = "GET", body?: object) => {
const options = {
method,
headers: {
"Content-Type": "application/json",
},
body: body ? JSON.stringify(body) : undefined,
};

const response = await fetch(`${API_URL}${endpoint}`, options);

if (!response.ok) {
throw new Error("Network response was not ok");
}

return await response.json();
};

export const generateProjectIdeas = async (materials: string[], onlySpecified: boolean, difficulty: string, category: string, tools: string[], time: number, budget: number, endPurpose: string) => {
return fetchApi("/v1/generate/idea", "POST", { materials, onlySpecified, difficulty, category, tools, time, budget, endPurpose });
};

export const generateProjectExplanations = async (title: string, materials: string[], tools: string[], time: string, budget: string, description: string) => {
return fetchApi("/v1/generate/explain", "POST", { title, materials, tools, time, budget, description });
};

export const searchImages = async (query: string) => {
return fetchApi(`/v1/image/search?query=${encodeURIComponent(query)}`);
};

export const getGuideByPath = async (path: string) => {
return fetchApi(`/v1/guide/${path}`);
};

export const getAllGuides = async () => {
return fetchApi("/v1/guide");
};

export const saveShareLinkData = async (projectDetails: ProjectLocationState | null, projectImage: RelatedImages | null, explanation: string | null) => {
return fetchApi("/v1/share", "POST", { projectDetails, projectImage, explanation });
};

export const getShareLinkData = async (id: string) => {
return fetchApi(`/v1/share/${id}`);
};

export const getTotalCountOfGeneratedIdea = async () => {
return fetchApi("/v1/counter");
};

export const incrementCounterOfGeneratedIdea = async () => {
return fetchApi("/v1/counter", "POST");
};
149 changes: 0 additions & 149 deletions client/src/api/open-ai-api.ts

This file was deleted.

39 changes: 38 additions & 1 deletion client/src/pages/Home.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ import {
Icon,
useBreakpointValue,
Container,
useSafeLayoutEffect,
} from "@chakra-ui/react";
import { FaRegLightbulb, FaInfoCircle } from "react-icons/fa";

import { generateProjectIdeas } from "../api/open-ai-api";
import { generateProjectIdeas, getTotalCountOfGeneratedIdea, incrementCounterOfGeneratedIdea } from "../api/backend-api";
import { categories, steps } from "../constants";
import {
BudgetFilter,
Expand Down Expand Up @@ -59,13 +60,38 @@ const Home = () => {

const [projects, setProjects] = useState([]);

const [totalCount, setTotalCount] = useState<number>(0);

const orientation: Orientation | undefined = useBreakpointValue({
base: "vertical",
md: "horizontal",
}) as Orientation | undefined;

const toast = useToast();

const fetchTotalCount = async () => {
try {
const response = await getTotalCountOfGeneratedIdea();
if (response?.data?.totalCount) {
setTotalCount(response.data.totalCount);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
toast({
title: "An error occurred.",
description: error.message,
status: "error",
duration: 5000,
isClosable: true,
position: "top-right",
});
}
};

useSafeLayoutEffect(() => {
fetchTotalCount();
}, []);

const handleSubmit = useCallback(async () => {
try {
if (!safetyConfirmed) throw new Error("Please check the safety checkbox");
Expand All @@ -78,6 +104,9 @@ const Home = () => {
setProjects(response.data.ideas);

goToNext();

await incrementCounterOfGeneratedIdea();
setTotalCount((count) => count + 1);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
Expand Down Expand Up @@ -135,6 +164,14 @@ const Home = () => {
</Text>
</Box>
</Box>
{totalCount}
{totalCount !== null && (
<Box p={4} borderRadius="lg" mb={2}>
<Text fontSize={["md", "lg"]} textAlign="center" fontWeight="bold">
🎉 Total generated ideas so far: {totalCount} 🎉
</Text>
</Box>
)}
<Stepper index={activeStep} width="100%" orientation={orientation}>
{steps.map((step, index) => (
<Step key={step.title}>
Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/HowToGuideDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useEffect, useState } from "react";
import { Box, Container, Heading, useToast } from "@chakra-ui/react";
import CustomMarkdown from "../components/CustomMarkdown";
import { useParams, useNavigate } from "react-router-dom";
import { getGuideByPath } from "../api/open-ai-api";
import { getGuideByPath } from "../api/backend-api";
import { HowToGuide } from "../types";
import { trimLeadingWhitespace } from "../utils";
import MetaTag from "../components/MetaTag";
Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/HowToGuideList.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useEffect, useState } from "react";
import { Box, Container, Heading, Text, LinkBox, LinkOverlay, VStack, useToast } from "@chakra-ui/react";
import { Link as RouterLink } from "react-router-dom";
import { getAllGuides } from "../api/open-ai-api";
import { getAllGuides } from "../api/backend-api";
import MetaTag from "../components/MetaTag";

type Guide = {
Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/ProjectDetail.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect } from "react";
import { Container, SimpleGrid, Divider, useToast, useDisclosure, Box, Button, Text } from "@chakra-ui/react";
import { useLocation, useNavigate } from "react-router-dom";
import { generateProjectExplanations, saveShareLinkData, searchImages } from "../api/open-ai-api";
import { generateProjectExplanations, saveShareLinkData, searchImages } from "../api/backend-api";
import { ProjectImage, ProjectInfo, ProjectSteps, ShareModal } from "../components/project-details";
import { RelatedImages, ProjectLocationState } from "../types";

Expand Down
2 changes: 1 addition & 1 deletion client/src/pages/ProjectDetailById.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useState, useEffect } from "react";
import { Container, SimpleGrid, Divider, useToast, useDisclosure, Box, Button, Text } from "@chakra-ui/react";
import { useParams, useNavigate } from "react-router-dom";
import { getShareLinkData } from "../api/open-ai-api";
import { getShareLinkData } from "../api/backend-api";
import { ProjectImage, ProjectInfo, ProjectSteps, ShareModal } from "../components/project-details";
import { RelatedImages, ProjectLocationState } from "../types";

Expand Down
7 changes: 7 additions & 0 deletions server/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,10 @@ model ProjectShareLink {
projectImage Json
explanation String?
}

model IdeaGenerationCounter {
id Int @id @default(autoincrement())
count Int @default(0)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
61 changes: 61 additions & 0 deletions server/src/controllers/counter.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Request, Response, NextFunction } from "express";
import { sendSuccess } from "../utils/response-template";
import { PrismaClient } from "@prisma/client";
import { getStartOfDay } from "../utils";

export const getTotalCountOfGeneratedIdea = async (req: Request, res: Response, next: NextFunction) => {
try {
const prisma = req.app.get("prisma") as PrismaClient;

const totalCount = await prisma.ideaGenerationCounter.aggregate({
_sum: {
count: true,
},
});

return sendSuccess(res, { totalCount: totalCount._sum.count ?? 0 });
} catch (error) {
next(error);
}
};

export const incrementCounterOfGeneratedIdea = async (req: Request, res: Response, next: NextFunction) => {
try {
const prisma = req.app.get("prisma") as PrismaClient;

const today = getStartOfDay(new Date());

const counter = await prisma.ideaGenerationCounter.findFirst({
where: {
createdAt: {
gte: today,
lt: new Date(today.getTime() + 24 * 60 * 60 * 1000),
},
},
});

if (counter) {
await prisma.ideaGenerationCounter.update({
where: {
id: counter.id,
},
data: {
count: {
increment: 1,
},
},
});
} else {
await prisma.ideaGenerationCounter.create({
data: {
count: 1,
createdAt: today,
},
});
}

return sendSuccess(res, {}, 201);
} catch (error) {
next(error);
}
};
Loading

0 comments on commit 6cfc64e

Please sign in to comment.