diff --git a/__tests__/api/feedback.test.ts b/__tests__/api/feedback.test.ts index 94f17de..e6f0f15 100644 --- a/__tests__/api/feedback.test.ts +++ b/__tests__/api/feedback.test.ts @@ -85,7 +85,6 @@ describe("Feedback API Endpoint", () => { color_3_reason: "Reason 3", color_4_reason: "Reason 4", prompt: "Prompt", - isDark: false, feedback: "Feedback", }; @@ -109,7 +108,6 @@ describe("Feedback API Endpoint", () => { color_3_reason: "Reason 3", color_4_reason: "Reason 4", prompt: "Prompt", - isDark: false, feedback: "Feedback", }; diff --git a/__tests__/api/generate.test.ts b/__tests__/api/generate.test.ts index 516e7b3..f65c17e 100644 --- a/__tests__/api/generate.test.ts +++ b/__tests__/api/generate.test.ts @@ -75,7 +75,7 @@ describe("Generate API Endpoint", () => { it("should return 400 if details are missing", async () => { req.body = { details: null, - isDark: false, + mode: "Dark", }; await handler(req, res); @@ -89,7 +89,7 @@ describe("Generate API Endpoint", () => { it("should return 404 if user is not found", async () => { req.body = { details: "test details", - isDark: false, + mode: "Dark", }; (db.query.users.findFirst as jest.Mock).mockResolvedValue(null); @@ -104,7 +104,7 @@ describe("Generate API Endpoint", () => { it("should return 400 if pupa is insufficient", async () => { req.body = { details: "test details", - isDark: false, + mode: "Dark", }; (db.query.users.findFirst as jest.Mock).mockResolvedValue({ pupa: 0, @@ -122,7 +122,7 @@ describe("Generate API Endpoint", () => { it("should return 400 if content is flagged by OpenAI", async () => { req.body = { details: "test details", - isDark: false, + mode: "Dark", }; (db.query.users.findFirst as jest.Mock).mockResolvedValue({ pupa: 1, @@ -142,7 +142,7 @@ describe("Generate API Endpoint", () => { it("should return 500 for GPT response error", async () => { req.body = { details: "test details", - isDark: false, + mode: "Dark", }; (db.query.users.findFirst as jest.Mock).mockResolvedValue({ pupa: 1, @@ -171,7 +171,7 @@ describe("Generate API Endpoint", () => { it("should return 500 for json parse error", async () => { req.body = { details: "test details", - isDark: false, + mode: "Dark", }; (db.query.users.findFirst as jest.Mock).mockResolvedValue({ pupa: 1, @@ -200,7 +200,7 @@ describe("Generate API Endpoint", () => { it("should return 500 for server error", async () => { req.body = { details: "test details", - isDark: false, + mode: "Dark", }; (db.query.users.findFirst as jest.Mock).mockResolvedValue({ pupa: 1, @@ -233,7 +233,7 @@ describe("Generate API Endpoint", () => { }; req.body = { details: "test details", - isDark: false, + mode: "Dark", }; (db.query.users.findFirst as jest.Mock).mockResolvedValue({ pupa: 1, diff --git a/__tests__/api/theme/inappropriate.test.ts b/__tests__/api/theme/inappropriate.test.ts index 2c99a3a..c49350b 100644 --- a/__tests__/api/theme/inappropriate.test.ts +++ b/__tests__/api/theme/inappropriate.test.ts @@ -94,7 +94,6 @@ describe("Theme Inappropriate API Endpoint", () => { await handler(req, res); - console.log(res.json); expect(db.insert).toHaveBeenCalled(); expect(res.status).toHaveBeenCalledWith(500); expect(res.json).toHaveBeenCalledWith({ diff --git a/src/components/generate-theme-dialog.tsx b/src/components/generate-theme-dialog.tsx index 175ed1f..db3f558 100644 --- a/src/components/generate-theme-dialog.tsx +++ b/src/components/generate-theme-dialog.tsx @@ -11,7 +11,6 @@ import { } from "./ui/dialog"; import { Label } from "./ui/label"; import { useEffect, useState } from "react"; -import { Switch } from "./ui/switch"; import axios from "axios"; import { Cross2Icon, ReloadIcon } from "@radix-ui/react-icons"; import { Textarea } from "./ui/textarea"; @@ -20,13 +19,16 @@ import { cn } from "@/lib/utils"; import { useRouter } from "next/router"; import { useHelpers } from "@/hooks/useHelpers"; import { useSession } from "next-auth/react"; -import { - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from "./ui/tooltip"; +import { Tooltip, TooltipContent, TooltipTrigger } from "./ui/tooltip"; import { INPUT_LIMIT } from "@/constants/website"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "./ui/select"; +import { GeneratedThemeProps } from "@/interfaces/theme"; interface GenerateThemeDialogProps { open: boolean; @@ -35,7 +37,7 @@ interface GenerateThemeDialogProps { interface FormDataProps { prompt: string; - isDark: boolean; + mode: GeneratedThemeProps["mode"]; } export const GenerateThemeDialog: React.FC = ({ @@ -55,7 +57,7 @@ export const GenerateThemeDialog: React.FC = ({ const [isPromptError, setIsPromptError] = useState(false); const [data, setData] = useState({ prompt: "", - isDark: false, + mode: "Default", }); const isAuthenticatedIsActived = @@ -66,13 +68,13 @@ export const GenerateThemeDialog: React.FC = ({ e.preventDefault(); axios .post("/api/generate", { - isDark: data.isDark, + mode: data.mode, details: data.prompt, }) .then((res) => { setGeneratedTheme({ ...res.data, - isDark: data.isDark, + mode: data.mode, prompt: data.prompt, }); setOpen(false); @@ -80,7 +82,7 @@ export const GenerateThemeDialog: React.FC = ({ setIsPromptError(false); router.push("/themes/generated"); setLoading(false); - setData({ prompt: "", isDark: false }); + setData({ prompt: "", mode: "Default" }); }) .catch((error) => { addToast({ @@ -99,7 +101,7 @@ export const GenerateThemeDialog: React.FC = ({ if (generateDialogDefaultValues) { setData(generateDialogDefaultValues); } else { - setData({ prompt: "", isDark: false }); + setData({ prompt: "", mode: "Default" }); setIsPromptError(false); } }, [generateDialogDefaultValues]); @@ -171,26 +173,33 @@ export const GenerateThemeDialog: React.FC = ({ } }} /> -
- - setData((prev) => ({ - ...prev, - isDark: !data.isDark, - })) - } - /> - -
+ +
diff --git a/src/components/profile-purchases.tsx b/src/components/profile-purchases.tsx index f859918..f9a56f6 100644 --- a/src/components/profile-purchases.tsx +++ b/src/components/profile-purchases.tsx @@ -75,7 +75,7 @@ export default function ProfilePurchases() { {e.pupa} - promts was made on + credits was made on {moment().format("MMMM Do YYYY, h:mm a")} diff --git a/src/components/profile-themes.tsx b/src/components/profile-themes.tsx index 01ef849..fcb4378 100644 --- a/src/components/profile-themes.tsx +++ b/src/components/profile-themes.tsx @@ -190,7 +190,7 @@ export default function ProfileThemes() { -
+
{tabs.find((tab) => tab.id === selectedTab)?.getThemes()}
@@ -352,7 +352,7 @@ const CreatedTheme: React.FC = ({ : sortedThemes; return isLoadingCreatedThemes ? ( -
+
{new Array(6).fill(0).map((_, index) => ( ))} @@ -538,7 +538,7 @@ const LikedTheme: React.FC = ({ }); return isLoadingLikedThemes ? ( -
+
{new Array(6).fill(0).map((_, index) => ( ))} @@ -723,7 +723,7 @@ const SavedTheme: React.FC = ({ }); return isLoadingSavedThemes ? ( -
+
{new Array(6).fill(0).map((_, index) => ( ))} diff --git a/src/components/save-generated-theme-dialog.tsx b/src/components/save-generated-theme-dialog.tsx index b360039..b888713 100644 --- a/src/components/save-generated-theme-dialog.tsx +++ b/src/components/save-generated-theme-dialog.tsx @@ -45,7 +45,6 @@ interface RegisterDialogProps { primary: string; secondary: string; prompt: string; - isDark: boolean; }; } diff --git a/src/components/save-theme-dialog.tsx b/src/components/save-theme-dialog.tsx index 1c68a1d..366d466 100644 --- a/src/components/save-theme-dialog.tsx +++ b/src/components/save-theme-dialog.tsx @@ -39,7 +39,6 @@ interface RegisterDialogProps { color_2_reason: string; color_3_reason: string; color_4_reason: string; - isDark: boolean; prompt: string; }; isDirty: boolean; diff --git a/src/components/tag-picker.tsx b/src/components/tag-picker.tsx index cd2894e..96fada1 100644 --- a/src/components/tag-picker.tsx +++ b/src/components/tag-picker.tsx @@ -56,15 +56,10 @@ export default function TagPicker({ }, []); useEffect(() => { - axios - .get("/api/tags") - .then((res) => { - setTags(res.data); - setFilteredTags(res.data); - }) - .catch((err) => { - console.log(err); - }); + axios.get("/api/tags").then((res) => { + setTags(res.data); + setFilteredTags(res.data); + }); }, []); useEffect(() => { diff --git a/src/components/theme-view.tsx b/src/components/theme-view.tsx index dd131a3..1d54587 100644 --- a/src/components/theme-view.tsx +++ b/src/components/theme-view.tsx @@ -4,7 +4,12 @@ import { ExportThemeDialog } from "@/components/export-theme-dialog"; import { Button } from "@/components/ui/button"; import Typography from "@/components/ui/typography"; import { FontProps, GOOGLE_FONTS } from "@/constants/fonts"; -import { ColorsProps, FontObjProps, ShadesProps } from "@/interfaces/theme"; +import { + ColorsProps, + FontObjProps, + GeneratedThemeProps, + ShadesProps, +} from "@/interfaces/theme"; import { cn, generateAllShades, getLuminance } from "@/lib/utils"; import { ArrowLeftIcon, @@ -75,14 +80,14 @@ export interface ThemeVeiwProps { }; type?: "view" | "generated"; prompt?: string; - isDark?: boolean; + mode?: GeneratedThemeProps["mode"]; } export const ThemeView: React.FC = ({ theme, type = "view", prompt = "", - isDark = false, + mode = "Default", }) => { const router = useRouter(); const { addToast } = useToast(); @@ -299,7 +304,7 @@ export const ThemeView: React.FC = ({ onClick={() => { setGenerateDialogDefaultValues({ prompt, - isDark, + mode, }); setGenerateThemeDialog(true); }} @@ -511,7 +516,6 @@ export const ThemeView: React.FC = ({ color_2_reason: theme.color_2_reason, color_3_reason: theme.color_3_reason, color_4_reason: theme.color_4_reason, - isDark: isDark, prompt: prompt, }} /> diff --git a/src/constants/openai.ts b/src/constants/openai.ts index 59f408b..6c10a89 100644 --- a/src/constants/openai.ts +++ b/src/constants/openai.ts @@ -1,16 +1,23 @@ +import { GeneratedThemeProps } from "@/interfaces/theme"; + export const getPrompt = ({ - isDark, + mode, description, }: { - isDark: boolean; + mode: GeneratedThemeProps["mode"]; description: string; }) => `Design a color scheme for a website based on the provided description. The color choices must be justified based on relevance to the website's content and the cultural context of the color. Adhere to the following guidelines: - Follow the 60-30-10 rule for color distribution. - Ensure color combinations comply with WCAG 2 Level AAA standards for contrast. -- Design for ${isDark ? "Dark" : "Light"} theme mode. +${ + mode === "Default" + ? `- Represent colors in HEX code format (ex. #FFFFFF). +- Reason should at least 20 words and not have more than 30 words.` + : `- Design for ${mode === "Dark" ? "Dark" : "Light"} theme mode. - Represent colors in HEX code format (ex. #FFFFFF). -- Reason should at least 20 words and not have more than 30 words. +- Reason should at least 20 words and not have more than 30 words.` +} Description: ${description} diff --git a/src/hooks/useHelpers.tsx b/src/hooks/useHelpers.tsx index 0259a17..9bdb6d7 100644 --- a/src/hooks/useHelpers.tsx +++ b/src/hooks/useHelpers.tsx @@ -42,10 +42,12 @@ type Context = { setIsAIOnly: Dispatch>; generateDialogDefaultValues?: { prompt: string; - isDark: boolean; + mode: GeneratedThemeProps["mode"]; }; setGenerateDialogDefaultValues: Dispatch< - SetStateAction<{ prompt: string; isDark: boolean } | undefined> + SetStateAction< + { prompt: string; mode: GeneratedThemeProps["mode"] } | undefined + > >; template: TemplateType; setTemplate: Dispatch>; @@ -87,7 +89,7 @@ const HelpersContext = createContext({ setIsAIOnly: () => {}, generateDialogDefaultValues: { prompt: "", - isDark: false, + mode: "Default", }, setGenerateDialogDefaultValues: () => {}, template: "Learning", diff --git a/src/interfaces/theme.ts b/src/interfaces/theme.ts index 41d82a9..3703919 100644 --- a/src/interfaces/theme.ts +++ b/src/interfaces/theme.ts @@ -101,5 +101,5 @@ export interface GeneratedThemeProps { color_4: string; color_4_reason: string; prompt: string; - isDark: boolean; + mode: "Light" | "Dark" | "Default"; } diff --git a/src/pages/api/feedback.ts b/src/pages/api/feedback.ts index b905fa8..94fa296 100644 --- a/src/pages/api/feedback.ts +++ b/src/pages/api/feedback.ts @@ -24,7 +24,7 @@ export default async function handler( color_4, color_4_reason, prompt, - isDark, + isDark = false, feedback, } = req.body; if ( diff --git a/src/pages/api/generate.ts b/src/pages/api/generate.ts index f80dfb2..401e2a9 100644 --- a/src/pages/api/generate.ts +++ b/src/pages/api/generate.ts @@ -17,7 +17,7 @@ export default async function handler( if (!session) { return res.status(401).json({ error: "Unauthorized" }); } - const { details, isDark } = req.body; + const { details, mode } = req.body; if (!details) { return res.status(400).json({ error: "Missing required fields" }); } @@ -62,12 +62,12 @@ export default async function handler( { role: "user", content: getPrompt({ - isDark, + mode, description: details, }), }, ], - temperature: 1, + temperature: 0.8, response_format: { type: "json_object" }, }); if (!gptResponse.choices[0].message.content) { diff --git a/src/pages/api/themes.ts b/src/pages/api/themes.ts index 7f7802d..17f5078 100644 --- a/src/pages/api/themes.ts +++ b/src/pages/api/themes.ts @@ -157,7 +157,6 @@ export default async function handler( } return res.status(404).json({ error: "Theme not found" }); } catch (error) { - console.log(error); return res.status(500).json({ error: "Failed to fetch theme" }); } } else { @@ -316,7 +315,11 @@ export default async function handler( LEFT JOIN tag ON tag.id = themes_to_tags."tagId" WHERE - users_to_liked_themes."userId" = ${userId} + theme.id IN ( + SELECT DISTINCT "themeId" + FROM users_to_liked_themes + WHERE users_to_liked_themes."userId" = ${userId} AND users_to_liked_themes.status <> 'N' + ) GROUP BY theme.id, "user".id ORDER BY @@ -422,7 +425,6 @@ export default async function handler( })) ); } catch (error) { - console.log(error); return res.status(500).json({ error: "Failed to fetch themes" }); } } @@ -538,7 +540,6 @@ export default async function handler( return; } catch (error) { - console.log(error); return res.status(500).json({ error: "Failed to create theme" }); } } else { diff --git a/src/pages/api/user.ts b/src/pages/api/user.ts index 61771e3..ab9e484 100644 --- a/src/pages/api/user.ts +++ b/src/pages/api/user.ts @@ -245,7 +245,6 @@ export default async function handler( columns: { id: true, name: true, - email: true, image: true, experience: true, level: true, @@ -294,7 +293,6 @@ export default async function handler( columns: { id: true, name: true, - email: true, image: true, experience: true, avatar: true, diff --git a/src/pages/themes/create.tsx b/src/pages/themes/create.tsx index 86337e1..99c246f 100644 --- a/src/pages/themes/create.tsx +++ b/src/pages/themes/create.tsx @@ -370,7 +370,6 @@ const CreateTheme = () => { color_2_reason: generatedTheme?.color_2_reason, color_3_reason: generatedTheme?.color_3_reason, color_4_reason: generatedTheme?.color_4_reason, - isDark: generatedTheme?.isDark, prompt: generatedTheme?.prompt, } : undefined diff --git a/src/pages/themes/generated.tsx b/src/pages/themes/generated.tsx index 412e3ab..c9864db 100644 --- a/src/pages/themes/generated.tsx +++ b/src/pages/themes/generated.tsx @@ -38,7 +38,7 @@ export default function GeneratedTheme() { ...{ likedBy: [], savedBy: [], views: [], tags: [] }, }} prompt={generatedTheme.prompt} - isDark={generatedTheme.isDark} + mode={generatedTheme.mode} type="generated" />