├── .babelrc.js
├── .env
├── .env.dev
├── .gitignore
├── README.md
├── config-overrides.js
├── package.json
├── public
├── index.html
├── logo.svg
├── logo192.png
├── logo512.png
├── manifest.json
└── robots.txt
├── src
├── App.test.tsx
├── App.tsx
├── assets
│ ├── avatar_01.svg
│ ├── back_genie.png
│ ├── back_graphics.svg
│ ├── back_herograd.svg
│ ├── back_heroicons.svg
│ ├── back_product_1.png
│ ├── back_product_2.png
│ ├── back_product_3.png
│ ├── back_product_4.png
│ ├── back_section2.png
│ ├── back_signin.png
│ ├── back_signup.png
│ ├── back_video.png
│ ├── ico_anycode.svg
│ ├── ico_apidoc.svg
│ ├── ico_bug.svg
│ ├── ico_bugfree.svg
│ ├── ico_calendar.svg
│ ├── ico_copy.svg
│ ├── ico_crown.svg
│ ├── ico_del.svg
│ ├── ico_document.svg
│ ├── ico_downarr.svg
│ ├── ico_export.svg
│ ├── ico_eye.svg
│ ├── ico_facebook.svg
│ ├── ico_github.svg
│ ├── ico_google.svg
│ ├── ico_image.svg
│ ├── ico_leftarrow.svg
│ ├── ico_linkedin.svg
│ ├── ico_monolithic.svg
│ ├── ico_play.svg
│ ├── ico_plus.svg
│ ├── ico_plus_white.svg
│ ├── ico_product.svg
│ ├── ico_refactor.svg
│ ├── ico_review.svg
│ ├── ico_rewrite.svg
│ ├── ico_search.svg
│ ├── ico_smartcon.svg
│ ├── ico_suggest.svg
│ ├── ico_testcase.svg
│ ├── ico_text.svg
│ ├── ico_tool.svg
│ ├── ico_twtter.svg
│ ├── ico_url.svg
│ ├── ico_value.svg
│ ├── ico_wish.svg
│ ├── logo_corning.png
│ ├── logo_hp.png
│ ├── logo_nevada.png
│ ├── logo_oracle.png
│ ├── logo_peoplesoft.png
│ └── logo_white.png
├── components
│ ├── FAQItem.tsx
│ ├── FullScreenLoader.tsx
│ ├── Layout.tsx
│ ├── MagicWand.tsx
│ ├── Prompt.tsx
│ ├── genie
│ │ └── TotalPanel.tsx
│ ├── headers
│ │ ├── AdminHeader.tsx
│ │ ├── Header.tsx
│ │ └── LandingHeader.tsx
│ └── requireUser.tsx
├── index.css
├── index.tsx
├── logo.svg
├── pages
│ ├── admin
│ │ ├── blogcreate.page.tsx
│ │ ├── dashboard.page.tsx
│ │ ├── price.page.tsx
│ │ ├── product.page.tsx
│ │ └── prompt.page.tsx
│ ├── auth
│ │ ├── forgot.page.tsx
│ │ ├── signin.page.tsx
│ │ ├── signup.page.tsx
│ │ ├── terms.page.tsx
│ │ └── verify.page.tsx
│ ├── genie.page.tsx
│ ├── landing.page.tsx
│ ├── pricing.page.tsx
│ └── unauthorized.page.tsx
├── react-app-env.d.ts
├── redux
│ ├── api
│ │ ├── authApi.ts
│ │ ├── customFetchBase.ts
│ │ ├── genieApi.ts
│ │ ├── productApi.ts
│ │ ├── promptApi.ts
│ │ ├── types.ts
│ │ └── userApi.ts
│ ├── features
│ │ ├── genieSlice.ts
│ │ └── userSlice.ts
│ └── store.ts
├── reportWebVitals.ts
├── setupTests.ts
└── theme.ts
├── tsconfig.json
└── yarn.lock
/.babelrc.js:
--------------------------------------------------------------------------------
1 | const plugins = [
2 | [
3 | "babel-plugin-import",
4 | {
5 | libraryName: "@mui/material",
6 | libraryDirectory: "",
7 | camel2DashComponentName: false,
8 | },
9 | "core",
10 | ],
11 | [
12 | "babel-plugin-import",
13 | {
14 | libraryName: "@mui/icons-material",
15 | libraryDirectory: "",
16 | camel2DashComponentName: false,
17 | },
18 | "icons",
19 | ],
20 | ];
21 |
22 | module.exports = { plugins };
23 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | REACT_APP_SERVER_ENDPOINT=https://backend.code-genie.ai
2 | REACT_APP_GG_APP_ID=531434323354-h4nohoohiuhefrj0cigr4rratflf1ngm.apps.googleusercontent.com
3 | REACT_APP_GITHUB_APP_ID=769c7da805be050a5d7d
4 | REACT_APP_GITHUB_APP_SECRET=ff0549dbf72cd345e928a1ee0a6bb6e836e7fe78
--------------------------------------------------------------------------------
/.env.dev:
--------------------------------------------------------------------------------
1 | REACT_APP_SERVER_ENDPOINT=http://localhost:8000
2 | REACT_APP_GG_APP_ID=531434323354-h4nohoohiuhefrj0cigr4rratflf1ngm.apps.googleusercontent.com
3 | REACT_APP_GITHUB_APP_ID=769c7da805be050a5d7d
4 | REACT_APP_GITHUB_APP_SECRET=ff0549dbf72cd345e928a1ee0a6bb6e836e7fe78
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.pnp
6 | .pnp.js
7 |
8 | # testing
9 | /coverage
10 |
11 | # production
12 | /build
13 |
14 | # misc
15 | .DS_Store
16 | .env.local
17 | .env.development.local
18 | .env.test.local
19 | .env.production.local
20 |
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Getting Started with Create React App
2 |
3 | This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
4 |
5 | ## Available Scripts
6 |
7 | In the project directory, you can run:
8 |
9 | ### `yarn start`
10 |
11 | Runs the app in the development mode.\
12 | Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
13 |
14 | The page will reload if you make edits.\
15 | You will also see any lint errors in the console.
16 |
17 | ### `yarn test`
18 |
19 | Launches the test runner in the interactive watch mode.\
20 | See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
21 |
22 | ### `yarn build`
23 |
24 | Builds the app for production to the `build` folder.\
25 | It correctly bundles React in production mode and optimizes the build for the best performance.
26 |
27 | The build is minified and the filenames include the hashes.\
28 | Your app is ready to be deployed!
29 |
30 | See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
31 |
32 | ### `yarn eject`
33 |
34 | **Note: this is a one-way operation. Once you `eject`, you can’t go back!**
35 |
36 | If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
37 |
38 | Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
39 |
40 | You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
41 |
42 | ## Learn More
43 |
44 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
45 |
46 | To learn React, check out the [React documentation](https://reactjs.org/).
47 |
--------------------------------------------------------------------------------
/config-overrides.js:
--------------------------------------------------------------------------------
1 | /* config-overrides.js */
2 | /* eslint-disable react-hooks/rules-of-hooks */
3 | const { useBabelRc, override } = require("customize-cra");
4 |
5 | module.exports = override(useBabelRc());
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "codegenie",
3 | "version": "0.1.0",
4 | "private": true,
5 | "dependencies": {
6 | "@emotion/react": "^11.11.1",
7 | "@emotion/styled": "^11.11.0",
8 | "@hookform/resolvers": "^3.1.1",
9 | "@mui/icons-material": "^5.14.1",
10 | "@mui/lab": "^5.0.0-alpha.137",
11 | "@mui/material": "^5.14.1",
12 | "@mui/styled-engine-sc": "^5.12.0",
13 | "@reduxjs/toolkit": "^1.9.5",
14 | "@testing-library/jest-dom": "^5.14.1",
15 | "@testing-library/react": "^13.0.0",
16 | "@testing-library/user-event": "^13.2.1",
17 | "@types/jest": "^27.0.1",
18 | "@types/node": "^16.7.13",
19 | "@types/react": "^18.0.0",
20 | "@types/react-dom": "^18.0.0",
21 | "@uiw/react-textarea-code-editor": "^2.1.7",
22 | "async-mutex": "^0.4.0",
23 | "axios": "^1.4.0",
24 | "react": "^18.2.0",
25 | "react-cookie": "^4.1.1",
26 | "react-dom": "^18.2.0",
27 | "react-hook-form": "^7.45.2",
28 | "react-redux": "^8.1.1",
29 | "react-router-dom": "^6.14.2",
30 | "react-scripts": "5.0.1",
31 | "react-toastify": "^9.1.3",
32 | "reactjs-social-login": "^2.6.2",
33 | "styled-components": "^6.0.5",
34 | "typescript": "^4.4.2",
35 | "web-vitals": "^2.1.0",
36 | "zod": "^3.21.4"
37 | },
38 | "scripts": {
39 | "start": "react-app-rewired start",
40 | "build": "react-app-rewired build",
41 | "test": "react-app-rewired test",
42 | "eject": "react-scripts eject"
43 | },
44 | "eslintConfig": {
45 | "extends": [
46 | "react-app",
47 | "react-app/jest"
48 | ]
49 | },
50 | "browserslist": {
51 | "production": [
52 | ">0.2%",
53 | "not dead",
54 | "not op_mini all"
55 | ],
56 | "development": [
57 | "last 1 chrome version",
58 | "last 1 firefox version",
59 | "last 1 safari version"
60 | ]
61 | },
62 | "devDependencies": {
63 | "@babel/plugin-proposal-private-property-in-object": "^7.21.11",
64 | "babel-plugin-import": "^1.13.6",
65 | "customize-cra": "^1.0.0",
66 | "react-app-rewired": "^2.2.1"
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 | Code Genie
18 |
36 |
40 |
48 |
49 |
50 |
51 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/public/logo192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/public/logo192.png
--------------------------------------------------------------------------------
/public/logo512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/public/logo512.png
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | },
10 | {
11 | "src": "logo192.png",
12 | "type": "image/png",
13 | "sizes": "192x192"
14 | },
15 | {
16 | "src": "logo512.png",
17 | "type": "image/png",
18 | "sizes": "512x512"
19 | }
20 | ],
21 | "start_url": ".",
22 | "display": "standalone",
23 | "theme_color": "#000000",
24 | "background_color": "#ffffff"
25 | }
26 |
--------------------------------------------------------------------------------
/public/robots.txt:
--------------------------------------------------------------------------------
1 | # https://www.robotstxt.org/robotstxt.html
2 | User-agent: *
3 | Disallow:
4 |
--------------------------------------------------------------------------------
/src/App.test.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, screen } from '@testing-library/react';
3 | import App from './App';
4 |
5 | test('renders learn react link', () => {
6 | render();
7 | const linkElement = screen.getByText(/learn react/i);
8 | expect(linkElement).toBeInTheDocument();
9 | });
10 |
--------------------------------------------------------------------------------
/src/App.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useMemo } from "react";
2 | import { CssBaseline } from "@mui/material";
3 | import { Routes, Route } from "react-router-dom";
4 | import { PaletteMode } from "@mui/material";
5 | import { createTheme, ThemeProvider } from "@mui/material/styles";
6 |
7 | import "react-toastify/dist/ReactToastify.css";
8 |
9 | import { ToastContainer } from "react-toastify";
10 | import Layout from "./components/Layout";
11 | import { getDesignTokens, ColorModeContext } from "./theme";
12 | import ProductConfigurator from "./pages/admin/product.page";
13 | import PriceConfigurator from "./pages/admin/price.page";
14 | import PromptConfigurator from "./pages/admin/prompt.page";
15 | import Dashboard from "./pages/admin/dashboard.page";
16 | import ContentGenerator from "./pages/admin/blogcreate.page";
17 | import GeniePage from "./pages/genie.page";
18 | import LandingPage from "./pages/landing.page";
19 | import SignupPage from "./pages/auth/signup.page";
20 | import TermsPage from "./pages/auth/terms.page";
21 | import SigninPage from "./pages/auth/signin.page";
22 | import ForgotPage from "./pages/auth/forgot.page";
23 | import VerifyPage from "./pages/auth/verify.page";
24 | import RequireUser from "./components/requireUser";
25 | import UnauthorizePage from "./pages/unauthorized.page";
26 | import PricingPage from "./pages/pricing.page";
27 |
28 | function App() {
29 | const [mode, setMode] = useState("light");
30 | const colorMode = useMemo(
31 | () => ({
32 | toggleColorMode: () => {
33 | setMode((prevMode: PaletteMode) =>
34 | prevMode === "light" ? "dark" : "light"
35 | );
36 | },
37 | }),
38 | []
39 | );
40 | const theme = useMemo(() => createTheme(getDesignTokens(mode)), [mode]);
41 |
42 | return (
43 | <>
44 |
45 |
46 |
47 |
48 |
49 | } />
50 | }>
51 | }>
52 | } />
53 | } />
54 |
55 |
56 | }>
57 | }>
58 | } />
59 |
60 | } />
61 | } />
62 | } />
63 |
64 |
65 | } />
66 |
67 |
68 |
69 | } />
70 | } />
71 | } />
72 | } />
73 | } />
74 | } />
75 |
76 |
77 |
78 | >
79 | );
80 | }
81 |
82 | export default App;
83 |
--------------------------------------------------------------------------------
/src/assets/back_genie.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/back_genie.png
--------------------------------------------------------------------------------
/src/assets/back_graphics.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/src/assets/back_herograd.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/src/assets/back_heroicons.svg:
--------------------------------------------------------------------------------
1 |
80 |
--------------------------------------------------------------------------------
/src/assets/back_product_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/back_product_1.png
--------------------------------------------------------------------------------
/src/assets/back_product_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/back_product_2.png
--------------------------------------------------------------------------------
/src/assets/back_product_3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/back_product_3.png
--------------------------------------------------------------------------------
/src/assets/back_product_4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/back_product_4.png
--------------------------------------------------------------------------------
/src/assets/back_section2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/back_section2.png
--------------------------------------------------------------------------------
/src/assets/back_signin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/back_signin.png
--------------------------------------------------------------------------------
/src/assets/back_signup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/back_signup.png
--------------------------------------------------------------------------------
/src/assets/back_video.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/back_video.png
--------------------------------------------------------------------------------
/src/assets/ico_anycode.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/ico_apidoc.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/ico_bug.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/assets/ico_bugfree.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/ico_calendar.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/assets/ico_copy.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/ico_crown.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/ico_del.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/assets/ico_document.svg:
--------------------------------------------------------------------------------
1 |
13 |
--------------------------------------------------------------------------------
/src/assets/ico_downarr.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/ico_export.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/ico_eye.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/ico_facebook.svg:
--------------------------------------------------------------------------------
1 |
12 |
--------------------------------------------------------------------------------
/src/assets/ico_github.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/assets/ico_google.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/assets/ico_image.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/ico_leftarrow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/ico_linkedin.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/ico_monolithic.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/assets/ico_play.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/ico_plus.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/ico_plus_white.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/ico_product.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/ico_refactor.svg:
--------------------------------------------------------------------------------
1 |
9 |
--------------------------------------------------------------------------------
/src/assets/ico_review.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/ico_rewrite.svg:
--------------------------------------------------------------------------------
1 |
7 |
--------------------------------------------------------------------------------
/src/assets/ico_search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/ico_smartcon.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/ico_suggest.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/ico_testcase.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/assets/ico_text.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/ico_tool.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/src/assets/ico_twtter.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/ico_url.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/ico_value.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/src/assets/ico_wish.svg:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/assets/logo_corning.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/logo_corning.png
--------------------------------------------------------------------------------
/src/assets/logo_hp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/logo_hp.png
--------------------------------------------------------------------------------
/src/assets/logo_nevada.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/logo_nevada.png
--------------------------------------------------------------------------------
/src/assets/logo_oracle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/logo_oracle.png
--------------------------------------------------------------------------------
/src/assets/logo_peoplesoft.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/logo_peoplesoft.png
--------------------------------------------------------------------------------
/src/assets/logo_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/softdev629/codegenie-react/6f44dbaabb983ee9a7989ac2f307932093e9ece3/src/assets/logo_white.png
--------------------------------------------------------------------------------
/src/components/FAQItem.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { Typography, Stack, IconButton, Collapse, Box } from "@mui/material";
3 | import { KeyboardArrowUp, KeyboardArrowDown } from "@mui/icons-material";
4 |
5 | const FAQItem = (props: { title: string; content: string }) => {
6 | const [open, setOpen] = useState(false);
7 | return (
8 | <>
9 |
10 |
11 |
17 | {props.title}
18 |
19 | setOpen(!open)}>
20 | {open ? : }
21 |
22 |
23 |
24 | {props.content}
25 |
26 |
27 | >
28 | );
29 | };
30 |
31 | export default FAQItem;
32 |
--------------------------------------------------------------------------------
/src/components/FullScreenLoader.tsx:
--------------------------------------------------------------------------------
1 | import { Box, CircularProgress, Container } from "@mui/material";
2 |
3 | const FullScreenLoader = () => {
4 | return (
5 |
6 |
12 |
13 |
14 |
15 | );
16 | };
17 |
18 | export default FullScreenLoader;
19 |
--------------------------------------------------------------------------------
/src/components/Layout.tsx:
--------------------------------------------------------------------------------
1 | import { Outlet } from "react-router-dom";
2 | import Header from "./headers/Header";
3 | import AdminHeader from "./headers/AdminHeader";
4 |
5 | const Layout = (props: { type: "admin" | "user" }) => {
6 | return (
7 | <>
8 | {props.type === "admin" ? : }
9 |
10 | >
11 | );
12 | };
13 |
14 | export default Layout;
15 |
--------------------------------------------------------------------------------
/src/components/MagicWand.tsx:
--------------------------------------------------------------------------------
1 | const MagicWand = () => {
2 | return (
3 | <>
4 |
5 |
52 |
53 |
54 | >
55 | );
56 | };
57 |
58 | export default MagicWand;
59 |
--------------------------------------------------------------------------------
/src/components/Prompt.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import { Box, Stack, Typography, TextField, MenuItem } from "@mui/material";
3 | import { useForm, FormProvider, SubmitHandler } from "react-hook-form";
4 | import { object, string, TypeOf, number } from "zod";
5 | import { zodResolver } from "@hookform/resolvers/zod";
6 | import { LoadingButton } from "@mui/lab";
7 | import { toast } from "react-toastify";
8 |
9 | import {
10 | useLazyGetModulesQuery,
11 | useLazyGetPricesQuery,
12 | } from "../redux/api/productApi";
13 | import {
14 | useAddPromptMutation,
15 | useUpdatePromptMutation,
16 | } from "../redux/api/promptApi";
17 |
18 | const promptSchema = object({
19 | product: string(),
20 | plan: string().optional(),
21 | module: string(),
22 | prompt_name: string(),
23 | order: number(),
24 | prompt: string(),
25 | });
26 |
27 | export type IPromptSchema = TypeOf;
28 |
29 | const Prompt = (props: {
30 | id: string;
31 | product: string;
32 | plan: string;
33 | module: string;
34 | prompt_name: string;
35 | order: number;
36 | prompt: string;
37 | products: string[];
38 | }) => {
39 | const [plans, setPlans] = useState([props.plan]);
40 | const [modules, setModules] = useState([props.module]);
41 |
42 | const [getModules, modulesState] = useLazyGetModulesQuery();
43 | const [getPrices, pricesState] = useLazyGetPricesQuery();
44 | const [addPrompt, addState] = useAddPromptMutation();
45 | const [updatePrompt, updateState] = useUpdatePromptMutation();
46 |
47 | const methods = useForm({
48 | resolver: zodResolver(promptSchema),
49 | defaultValues: {
50 | product: props.product,
51 | plan: props.plan,
52 | module: props.module,
53 | prompt_name: props.prompt_name,
54 | order: props.order,
55 | prompt: props.prompt,
56 | },
57 | });
58 |
59 | const { handleSubmit, getValues, register, setValue } = methods;
60 |
61 | useEffect(() => {
62 | if (props.product !== "") {
63 | getModules(props.product);
64 | getPrices({ product_name: props.product, product_module: props.module });
65 | }
66 |
67 | // eslint-disable-next-line react-hooks/exhaustive-deps
68 | }, []);
69 |
70 | useEffect(() => {
71 | if (modulesState.isSuccess) {
72 | setModules(modulesState.data);
73 | }
74 | }, [modulesState]);
75 |
76 | useEffect(() => {
77 | if (pricesState.isSuccess) {
78 | if (pricesState.data)
79 | setPlans(pricesState.data.map((item) => item.plan_name));
80 | else {
81 | setPlans([""]);
82 | setValue("plan", "");
83 | }
84 | }
85 | // eslint-disable-next-line react-hooks/exhaustive-deps
86 | }, [pricesState]);
87 |
88 | useEffect(() => {
89 | if (addState.isSuccess) toast.success("Prompt added successfully.");
90 | }, [addState]);
91 |
92 | useEffect(() => {
93 | if (updateState.isSuccess) toast.success("Prompt updated successfully.");
94 | }, [updateState]);
95 |
96 | const onSubmitHandler: SubmitHandler = (
97 | values: IPromptSchema
98 | ) => {
99 | if (props.id === "") addPrompt(values);
100 | else updatePrompt({ id: props.id, info: values });
101 | };
102 |
103 | return (
104 | <>
105 |
106 |
114 |
115 |
116 | Save
117 |
118 |
119 |
120 | Products
121 | Plans
122 | Module
123 | Prompt name
124 | Feature list order
125 |
126 |
127 | {
134 | getModules(event.target.value);
135 | }}
136 | >
137 | {props.products.map((product, index) => (
138 |
141 | ))}
142 |
143 |
150 | {plans.map((plan, index) => (
151 |
154 | ))}
155 |
156 | {
163 | let product_name = getValues("product");
164 | getPrices({
165 | product_name: product_name,
166 | product_module: event.target.value,
167 | });
168 | }}
169 | >
170 | {modules.map((module, index) => (
171 |
174 | ))}
175 |
176 |
182 |
189 |
190 |
191 | Note: 3rd listed in UI
192 |
193 | Prompt
194 |
201 |
202 |
203 | >
204 | );
205 | };
206 |
207 | export default Prompt;
208 |
--------------------------------------------------------------------------------
/src/components/genie/TotalPanel.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import {
3 | Box,
4 | Stack,
5 | Typography,
6 | SvgIcon,
7 | IconButton,
8 | Button,
9 | Divider,
10 | Tabs,
11 | Tab,
12 | Menu,
13 | MenuItem,
14 | } from "@mui/material";
15 |
16 | import { ReactComponent as CopyIcon } from "../../assets/ico_copy.svg";
17 | import { ReactComponent as ExportIcon } from "../../assets/ico_export.svg";
18 |
19 | import { useGetPromptNamesQuery } from "../../redux/api/promptApi";
20 | import { useAppDispatch, useAppSelector } from "../../redux/store";
21 | import { setPromptName } from "../../redux/features/genieSlice";
22 | import { useExportFileMutation } from "../../redux/api/genieApi";
23 |
24 | interface TabPanelProps {
25 | children?: React.ReactNode;
26 | value: number;
27 | }
28 |
29 | function TabPanel(props: TabPanelProps) {
30 | const { children, value, ...other } = props;
31 |
32 | return (
33 |
34 | ({
36 | p: 3,
37 | backgroundColor: theme.palette.background.paper,
38 | height: "100%",
39 | })}
40 | >
41 | {children}
42 |
43 |
44 | );
45 | }
46 |
47 | function a11yProps(index: number) {
48 | return {
49 | id: `vertical-tab-${index}`,
50 | "aria-controls": `vertical-tabpanel-${index}`,
51 | };
52 | }
53 |
54 | export default function TotalPanel({
55 | export_check,
56 | export_text,
57 | export_pdf,
58 | export_word,
59 | }: {
60 | export_check: string[];
61 | export_text: string;
62 | export_pdf: string;
63 | export_word: string;
64 | }) {
65 | const [value, setValue] = useState(0);
66 | const [anchorEl, setAnchorEl] = useState(null);
67 |
68 | const genieSelector = useAppSelector((state) => state.genieState);
69 | const dispatch = useAppDispatch();
70 |
71 | const [exportFile, exportState] = useExportFileMutation();
72 |
73 | const promptsInfo = useGetPromptNamesQuery({
74 | product_name: "CodeGenie",
75 | product_module: genieSelector.module ? genieSelector.module : "",
76 | });
77 |
78 | useEffect(() => {
79 | if (promptsInfo.isSuccess) {
80 | dispatch(setPromptName(promptsInfo.data[0]));
81 | }
82 | // eslint-disable-next-line react-hooks/exhaustive-deps
83 | }, [promptsInfo]);
84 |
85 | useEffect(() => {
86 | if (exportState.isSuccess) {
87 | fetch(
88 | `${process.env.REACT_APP_SERVER_ENDPOINT}/static/${exportState.data.path}`
89 | )
90 | .then((response) => response.blob())
91 | .then((blob) => {
92 | const url = window.URL.createObjectURL(blob);
93 | const link = document.createElement("a");
94 | link.href = url;
95 | link.setAttribute("download", `${exportState.data.path}`);
96 | document.body.appendChild(link);
97 | link.click();
98 | });
99 | }
100 | }, [exportState]);
101 |
102 | const handleChange = (event: React.SyntheticEvent, newValue: number) => {
103 | setValue(newValue);
104 | if (promptsInfo.data) dispatch(setPromptName(promptsInfo.data[newValue]));
105 | };
106 |
107 | if (!promptsInfo.data || promptsInfo.isLoading || promptsInfo.isFetching)
108 | return (
109 | ({
111 | flexGrow: 1,
112 | display: "flex",
113 | height: "100%",
114 |
115 | border: "1px solid",
116 | borderColor: theme.palette.divider,
117 | borderRadius: 1,
118 | })}
119 | >
120 | );
121 |
122 | return (
123 | ({
125 | flexGrow: 1,
126 | display: "flex",
127 | height: "100%",
128 |
129 | border: "1px solid",
130 | borderColor: theme.palette.divider,
131 | borderRadius: 1,
132 | })}
133 | >
134 | ({
139 | borderRight: 1,
140 | borderColor: "divider",
141 | overflow: "visible",
142 | backgroundColor:
143 | theme.palette.mode === "dark"
144 | ? theme.palette.background.default
145 | : "white",
146 | ".MuiTabs-indicator": {
147 | visibility: "hidden",
148 | },
149 | ".MuiTabs-scroller": {
150 | overflow: "visible !important",
151 | },
152 | })}
153 | >
154 | {promptsInfo.data.map((panel, index) => (
155 | ({
158 | textTransform: "none",
159 | alignItems: "flex-start",
160 | color: theme.palette.mode === "dark" ? "#F8FAFC" : "#475569",
161 | overflow: "visible",
162 | padding: "24px 14px",
163 | borderBottom: "1px solid",
164 | borderColor: "divider",
165 | "&.Mui-selected": {
166 | borderLeft: "3px solid",
167 | backgroundColor: theme.palette.background.paper,
168 | },
169 | "&.Mui-selected::after": {
170 | overflow: "visible",
171 | content: '" "',
172 | left: "98%",
173 | position: "absolute",
174 | width: 10,
175 | height: "100%",
176 | zIndex: 101,
177 | backgroundColor: theme.palette.background.paper,
178 | },
179 | })}
180 | label={panel}
181 | {...a11yProps(index)}
182 | />
183 | ))}
184 |
185 |
186 |
187 |
188 |
189 |
195 | Results
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
220 |
262 |
263 |
264 |
265 | ({
268 | whiteSpace: "pre-wrap",
269 | overflow: "auto",
270 | height: "calc(100vh - 400px)",
271 | "&.MuiBox-root::-webkit-scrollbar": {
272 | width: 4,
273 | },
274 | "&.MuiBox-root::-webkit-scrollbar-thumb": {
275 | backgroundColor: theme.palette.divider,
276 | borderRadius: 4,
277 | },
278 | "&.MuiBox-root::-webkit-scrollbar-track": {
279 | backgroundColor:
280 | theme.palette.mode === "dark" ? "#2D2D2D" : "#fff",
281 | },
282 | })}
283 | >
284 | {
285 | genieSelector.msg[
286 | genieSelector.prompt_name ? genieSelector.prompt_name : ""
287 | ]
288 | }
289 |
290 |
291 |
292 |
293 | );
294 | }
295 |
--------------------------------------------------------------------------------
/src/components/headers/AdminHeader.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import { useNavigate } from "react-router-dom";
3 | import {
4 | Box,
5 | SvgIcon,
6 | Typography,
7 | Stack,
8 | Divider,
9 | Tabs,
10 | Tab,
11 | } from "@mui/material";
12 |
13 | import { ReactComponent as Logo } from "../../logo.svg";
14 |
15 | const pages = [
16 | {
17 | text: "Dashboard",
18 | link: "/dashboard",
19 | },
20 | {
21 | text: "Content Generator",
22 | link: "/content/generate",
23 | },
24 | {
25 | text: "Content Editor",
26 | link: "/content/edit",
27 | },
28 | {
29 | text: "Price Configurator",
30 | link: "/config/prices",
31 | },
32 |
33 | {
34 | text: "API Configurator",
35 | link: "/config/api",
36 | },
37 | {
38 | text: "Prompt Configurator",
39 | link: "/config/prompts",
40 | },
41 | {
42 | text: "Product Configurator",
43 | link: "/config/products",
44 | },
45 | ];
46 |
47 | const AdminHeader = () => {
48 | const [value, setValue] = useState(0);
49 | const navigate = useNavigate();
50 | return (
51 | <>
52 |
53 |
54 |
55 |
62 |
63 |
64 |
78 | CodeGenie
79 |
80 |
81 |
83 | setValue(newValue)
84 | }
85 | value={value}
86 | >
87 | {pages.map((page, index) => (
88 | navigate(`/admin${page.link}`)}
97 | />
98 | ))}
99 |
100 |
101 |
102 |
103 | >
104 | );
105 | };
106 |
107 | export default AdminHeader;
108 |
--------------------------------------------------------------------------------
/src/components/headers/Header.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useContext, useEffect } from "react";
2 | import {
3 | Box,
4 | Toolbar,
5 | IconButton,
6 | Typography,
7 | Menu,
8 | Container,
9 | Button,
10 | MenuItem,
11 | SvgIcon,
12 | FormControlLabel,
13 | Switch,
14 | Divider,
15 | } from "@mui/material";
16 | import { Menu as MenuIcon } from "@mui/icons-material";
17 | import { styled } from "@mui/material/styles";
18 | import { useNavigate } from "react-router-dom";
19 |
20 | import { ReactComponent as Logo } from "../../logo.svg";
21 | import { ReactComponent as CrownIcon } from "../../assets/ico_crown.svg";
22 | import { ReactComponent as ProductIcon } from "../../assets/ico_product.svg";
23 | import { ReactComponent as DownIcon } from "../../assets/ico_downarr.svg";
24 |
25 | import { ColorModeContext } from "../../theme";
26 | import { useLazyGetModulesQuery } from "../../redux/api/productApi";
27 | import { useAppDispatch } from "../../redux/store";
28 | import { setModule } from "../../redux/features/genieSlice";
29 |
30 | const AntSwitch = styled(Switch)(({ theme }) => ({
31 | width: 32,
32 | height: 16,
33 | padding: 0,
34 | marginLeft: 10,
35 | border: "1px solid #1D252D",
36 | borderRadius: 8,
37 | display: "flex",
38 | "&:active": {
39 | "& .MuiSwitch-thumb": {
40 | width: 15,
41 | },
42 | "& .MuiSwitch-switchBase.Mui-checked": {
43 | transform: "translateX(9px)",
44 | },
45 | },
46 | "& .MuiSwitch-switchBase": {
47 | padding: 2,
48 | "&.Mui-checked": {
49 | transform: "translateX(16px)",
50 | color: "#fff",
51 | "& + .MuiSwitch-track": {
52 | opacity: 1,
53 | backgroundColor: theme.palette.mode === "dark" ? "#177ddc" : "#1890ff",
54 | },
55 | },
56 | },
57 | "& .MuiSwitch-thumb": {
58 | boxShadow: "0 2px 4px 0 rgb(0 35 11 / 20%)",
59 | width: 10,
60 | height: 10,
61 | borderRadius: 6,
62 | transition: theme.transitions.create(["width"], {
63 | duration: 200,
64 | }),
65 | background: theme.palette.mode === "dark" ? "white" : "#1D252D",
66 | },
67 | "& .MuiSwitch-track": {
68 | borderRadius: 16 / 2,
69 | opacity: 1,
70 | backgroundColor:
71 | theme.palette.mode === "dark"
72 | ? "linear-gradient(#0168B5, #4BA5EB)"
73 | : "rgba(255,255,255,1)",
74 | boxSizing: "border-box",
75 | },
76 | }));
77 |
78 | function Header() {
79 | const [anchorElNav, setAnchorElNav] = useState(null);
80 | const colorMode = useContext(ColorModeContext);
81 |
82 | const [modules, setModules] = useState([]);
83 | const [anchorEl, setAnchorEl] = useState(null);
84 |
85 | const navigate = useNavigate();
86 | const dispatch = useAppDispatch();
87 |
88 | const open = Boolean(anchorEl);
89 | const handleClick = (event: React.MouseEvent) => {
90 | setAnchorEl(event.currentTarget);
91 | };
92 | const handleClose = () => {
93 | setAnchorEl(null);
94 | };
95 |
96 | const [getModules, getState] = useLazyGetModulesQuery();
97 |
98 | useEffect(() => {
99 | getModules("CodeGenie");
100 | // eslint-disable-next-line react-hooks/exhaustive-deps
101 | }, []);
102 |
103 | useEffect(() => {
104 | if (getState.isSuccess)
105 | setModules(getState.data.filter((item) => item !== ""));
106 | }, [getState]);
107 |
108 | const handleOpenNavMenu = (event: React.MouseEvent) => {
109 | setAnchorElNav(event.currentTarget);
110 | };
111 |
112 | const handleCloseNavMenu = () => {
113 | setAnchorElNav(null);
114 | };
115 |
116 | return (
117 | <>
118 |
119 |
120 |
127 |
128 |
129 | {
142 | event.preventDefault();
143 | navigate("/");
144 | }}
145 | >
146 | CodeGenie
147 |
148 |
149 |
163 | CodeGenie
164 |
165 |
166 |
174 |
175 |
176 |
194 |
195 |
203 |
223 |
248 |
251 |
252 |
253 |
254 |
255 |
256 | }
259 | label="Darkmode"
260 | labelPlacement="start"
261 | />
262 |
278 |
279 |
280 |
281 |
282 | >
283 | );
284 | }
285 | export default Header;
286 |
--------------------------------------------------------------------------------
/src/components/headers/LandingHeader.tsx:
--------------------------------------------------------------------------------
1 | import { useState, useEffect } from "react";
2 | import {
3 | Container,
4 | Toolbar,
5 | SvgIcon,
6 | Typography,
7 | Box,
8 | IconButton,
9 | Menu,
10 | Button,
11 | Divider,
12 | MenuItem,
13 | } from "@mui/material";
14 | import { Menu as MenuIcon } from "@mui/icons-material";
15 |
16 | import { ReactComponent as Logo } from "../../logo.svg";
17 | import { ReactComponent as ProductIcon } from "../../assets/ico_product.svg";
18 | import { ReactComponent as DownIcon } from "../../assets/ico_downarr.svg";
19 |
20 | import { useLazyGetModulesQuery } from "../../redux/api/productApi";
21 | import { setModule } from "../../redux/features/genieSlice";
22 | import { useAppDispatch } from "../../redux/store";
23 | import { useNavigate } from "react-router-dom";
24 |
25 | const LandingHeader = () => {
26 | const [anchorElNav, setAnchorElNav] = useState(null);
27 | const [anchorEl, setAnchorEl] = useState(null);
28 | const [modules, setModules] = useState([]);
29 |
30 | const [getModules, getState] = useLazyGetModulesQuery();
31 |
32 | const dispatch = useAppDispatch();
33 | const navigate = useNavigate();
34 |
35 | useEffect(() => {
36 | getModules("CodeGenie");
37 | // eslint-disable-next-line react-hooks/exhaustive-deps
38 | }, []);
39 |
40 | useEffect(() => {
41 | if (getState.isSuccess) {
42 | setModules(getState.data.filter((item) => item !== ""));
43 | dispatch(setModule(getState.data[0]));
44 | }
45 | // eslint-disable-next-line react-hooks/exhaustive-deps
46 | }, [getState]);
47 |
48 | const open = Boolean(anchorEl);
49 |
50 | const handleClick = (event: React.MouseEvent) => {
51 | setAnchorEl(event.currentTarget);
52 | };
53 | const handleClose = () => {
54 | setAnchorEl(null);
55 | };
56 |
57 | const handleOpenNavMenu = (event: React.MouseEvent) => {
58 | setAnchorElNav(event.currentTarget);
59 | };
60 |
61 | const handleCloseNavMenu = () => {
62 | setAnchorElNav(null);
63 | };
64 |
65 | return (
66 | <>
67 |
68 |
69 |
76 |
77 |
78 |
91 | CodeGenie
92 |
93 |
94 |
108 | CodeGenie
109 |
110 |
111 |
119 |
120 |
121 |
139 |
140 |
148 |
168 |
190 |
191 |
192 |
207 |
208 |
220 |
221 |
222 |
223 |
224 |
225 | >
226 | );
227 | };
228 |
229 | export default LandingHeader;
230 |
--------------------------------------------------------------------------------
/src/components/requireUser.tsx:
--------------------------------------------------------------------------------
1 | import { useCookies } from "react-cookie";
2 | import { Navigate, Outlet, useLocation } from "react-router-dom";
3 | import { userApi } from "../redux/api/userApi";
4 | import FullScreenLoader from "./FullScreenLoader";
5 |
6 | const RequireUser = ({ allowedRoles }: { allowedRoles: string[] }) => {
7 | const [cookies] = useCookies(["logged_in"]);
8 | const location = useLocation();
9 |
10 | const { isLoading, isFetching } = userApi.endpoints.getMe.useQuery(null, {
11 | skip: false,
12 | refetchOnMountOrArgChange: true,
13 | });
14 |
15 | const loading = isLoading || isFetching;
16 |
17 | const userData = userApi.endpoints.getMe.useQueryState(null);
18 |
19 | if (loading) {
20 | return ;
21 | }
22 |
23 | return (cookies.logged_in || userData) &&
24 | allowedRoles.includes(userData?.data?.role as string) ? (
25 |
26 | ) : cookies.logged_in && userData ? (
27 |
28 | ) : (
29 |
30 | );
31 | };
32 |
33 | export default RequireUser;
34 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | .spinner-container {
2 | position: relative;
3 | width: 160px;
4 | height: 160px;
5 | }
6 |
7 | .main-wand {
8 | position: absolute;
9 | left: calc(50% - 60px);
10 | top: calc(50% - 60px);
11 | }
12 |
13 | .spinner {
14 | border: 8px solid #f3f3f3; /* Light grey */
15 | border-top: 8px solid #5db9d1; /* Blue */
16 | border-radius: 50%;
17 | width: 120px;
18 | height: 120px;
19 | animation: spin 2s linear infinite;
20 | position: absolute;
21 | left: calc(50% - 60px);
22 | top: calc(50% - 60px);
23 | }
24 |
25 | .stars1 {
26 | fill: #dd7f36;
27 | animation: flicker 1s linear infinite;
28 | }
29 |
30 | .stars2 {
31 | fill: #dd7f36;
32 | animation: flicker 2s linear infinite;
33 | }
34 |
35 | .stars3 {
36 | fill: #dd7f36;
37 | animation: flicker 3s linear infinite;
38 | }
39 |
40 | .stars4 {
41 | fill: #dd7f36;
42 | animation: flicker 4s linear infinite;
43 | }
44 |
45 | .wandfill {
46 | fill: #7fcde0;
47 | }
48 |
49 | .wand {
50 | fill: #5ebad2;
51 | }
52 |
53 | @keyframes spin {
54 | 0% {
55 | transform: rotate(0deg);
56 | }
57 | 100% {
58 | transform: rotate(360deg);
59 | }
60 | }
61 |
62 | @keyframes flicker {
63 | 0%,
64 | 30%,
65 | 22%,
66 | 62%,
67 | 64%,
68 | 64.999%,
69 | 70%,
70 | 100% {
71 | opacity: 0.99;
72 | }
73 | 20%,
74 | 22%,
75 | 63%,
76 | 63.999%,
77 | 65%,
78 | 69.999% {
79 | opacity: 0.5;
80 | }
81 | }
82 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import { BrowserRouter as Router } from "react-router-dom";
4 | import { Provider } from "react-redux";
5 |
6 | import "./index.css";
7 |
8 | import App from "./App";
9 | import reportWebVitals from "./reportWebVitals";
10 | import { store } from "./redux/store";
11 |
12 | const root = ReactDOM.createRoot(
13 | document.getElementById("root") as HTMLElement
14 | );
15 | root.render(
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | );
24 |
25 | // If you want to start measuring performance in your app, pass a function
26 | // to log results (for example: reportWebVitals(console.log))
27 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
28 | reportWebVitals();
29 |
--------------------------------------------------------------------------------
/src/pages/admin/blogcreate.page.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react";
2 | import {
3 | Container,
4 | Box,
5 | Typography,
6 | Divider,
7 | Autocomplete,
8 | TextField,
9 | } from "@mui/material";
10 |
11 | const ContentGenerator = () => {
12 | const [options] = useState([]);
13 |
14 | return (
15 | <>
16 |
22 |
34 | Search Content
35 |
36 | (
40 |
45 | )}
46 | />
47 |
48 |
49 |
50 | >
51 | );
52 | };
53 |
54 | export default ContentGenerator;
55 |
--------------------------------------------------------------------------------
/src/pages/admin/dashboard.page.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Container,
3 | Stack,
4 | Typography,
5 | Box,
6 | TextField,
7 | MenuItem,
8 | SvgIcon,
9 | InputAdornment,
10 | } from "@mui/material";
11 |
12 | import { ReactComponent as CalendarIcon } from "../../assets/ico_calendar.svg";
13 |
14 | const Dashboard = () => {
15 | return (
16 | <>
17 |
18 |
19 |
20 | Your Overview
21 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
33 |
34 |
35 | ),
36 | }}
37 | defaultValue="15 Mar. - 30 Mar."
38 | />
39 |
40 |
41 | Compared to
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | TOTAl USERS
59 |
60 |
65 | +20% Increase
66 |
67 |
68 |
69 | 200
70 |
71 |
72 |
78 | More Info >
79 |
80 |
81 |
82 |
83 |
84 |
85 | TOTAL REVENUE
86 |
87 |
92 | +20% Increase
93 |
94 |
95 |
96 | $12,989
97 |
98 |
99 |
105 | More Info >
106 |
107 |
108 |
109 |
110 |
111 |
112 | TOTAL WISHES
113 |
114 |
119 | +20 New Wisher
120 |
121 |
122 |
123 | 78
124 |
125 |
126 |
132 | More Info >
133 |
134 |
135 |
136 |
137 |
138 |
139 | >
140 | );
141 | };
142 |
143 | export default Dashboard;
144 |
--------------------------------------------------------------------------------
/src/pages/admin/price.page.tsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import {
3 | Box,
4 | Typography,
5 | Divider,
6 | Container,
7 | Stack,
8 | Grid,
9 | TextField,
10 | SvgIcon,
11 | IconButton,
12 | MenuItem,
13 | Autocomplete,
14 | } from "@mui/material";
15 | import { LoadingButton } from "@mui/lab";
16 | import { object, string, TypeOf, array, number } from "zod";
17 | import { SubmitHandler, useForm, FormProvider } from "react-hook-form";
18 | import { zodResolver } from "@hookform/resolvers/zod";
19 | import { toast } from "react-toastify";
20 |
21 | import { ReactComponent as DeleteIcon } from "../../assets/ico_del.svg";
22 | import { ReactComponent as PlustIcon } from "../../assets/ico_plus.svg";
23 | import { IPlanDetail, IProductHeadings } from "../../redux/api/types";
24 | import {
25 | useLazyGetProductQuery,
26 | useLazySearchProductQuery,
27 | useUpdatePriceMutation,
28 | } from "../../redux/api/productApi";
29 |
30 | const saveSchema = object({
31 | product_name: string().min(1, "Product name is required"),
32 | product_module: string().optional(),
33 | module_description: string().optional(),
34 | plan_details: array(
35 | object({
36 | plan_name: string(),
37 | total_wishes: number().optional(),
38 | price: string(),
39 | period: string(),
40 | })
41 | ),
42 | });
43 |
44 | export type PriceSettingSaveInput = TypeOf;
45 |
46 | const PriceConfigurator = () => {
47 | const [options, setOptions] = useState([]);
48 | const [filter, setFilter] = useState(null);
49 | const [plans, setPlans] = useState([
50 | {
51 | plan_name: "",
52 | total_wishes: 0,
53 | price: "",
54 | period: "",
55 | },
56 | ]);
57 |
58 | const methods = useForm({
59 | resolver: zodResolver(saveSchema),
60 | defaultValues: {},
61 | });
62 |
63 | const [searchProduct, searchState] = useLazySearchProductQuery();
64 | const [getProduct, getState] = useLazyGetProductQuery();
65 | const [updatePrice, updateState] = useUpdatePriceMutation();
66 |
67 | const { handleSubmit, register, setValue } = methods;
68 |
69 | useEffect(() => {
70 | searchProduct("");
71 | // eslint-disable-next-line react-hooks/exhaustive-deps
72 | }, []);
73 |
74 | useEffect(() => {
75 | if (searchState.data) setOptions(searchState.data);
76 | }, [searchState]);
77 |
78 | useEffect(() => {
79 | if (updateState.isSuccess)
80 | toast.success("Price plan updated successfully!");
81 | }, [updateState]);
82 |
83 | useEffect(() => {
84 | const { data } = getState;
85 | setValue("product_name", data?.product_name as string);
86 | setValue("product_module", data?.product_module as string);
87 | setValue("module_description", data?.module_description as string);
88 | if (data?.plan_details) setPlans([...data.plan_details]);
89 | else
90 | setPlans([
91 | {
92 | plan_name: "",
93 | total_wishes: 0,
94 | price: "",
95 | period: "",
96 | },
97 | ]);
98 | }, [getState, setValue]);
99 |
100 | const onSubmitHandler: SubmitHandler = (
101 | values: PriceSettingSaveInput
102 | ) => {
103 | console.log(values);
104 | updatePrice(values);
105 | };
106 |
107 | return (
108 | <>
109 |
110 |
122 | Pricing Configurator
123 |
124 |
125 |
126 |
127 |
128 |
129 | (
134 |
140 | )}
141 | getOptionLabel={(option) =>
142 | `${option.product_name} : ${option.product_module}`
143 | }
144 | renderOption={(props, option) => {
145 | return (
146 |
147 | {option.product_name} : {option.product_module}
148 |
149 | );
150 | }}
151 | value={filter}
152 | onChange={(event, newValue) => {
153 | if (newValue) {
154 | setFilter(newValue);
155 | getProduct(newValue);
156 | }
157 | }}
158 | />
159 |
160 |
168 |
169 |
170 |
176 | Configure pricing here
177 |
178 |
179 |
185 | Save
186 |
187 |
188 |
189 |
190 |
191 |
192 |
197 | Product Name
198 |
199 |
200 |
201 |
209 |
210 |
211 |
212 |
213 |
218 | Product Module
219 |
220 |
221 |
228 |
234 |
239 |
240 |
241 |
242 |
243 |
248 | Plan Details
249 |
250 |
251 |
258 |
259 | Plan Name
260 | Total Wishes
261 | Price
262 | Period
263 |
264 |
265 | {plans.map((plan, index) => (
266 |
271 | {
277 | plans[index].plan_name = e.target.value;
278 | setPlans([...plans]);
279 | }}
280 | />
281 |
291 | ) => {
292 | plans[index].total_wishes = e.target.valueAsNumber;
293 | setPlans([...plans]);
294 | }}
295 | />
296 | {
302 | plans[index].price = e.target.value;
303 | setPlans([...plans]);
304 | }}
305 | />
306 | {
312 | plans[index].period = e.target.value;
313 | setPlans([...plans]);
314 | }}
315 | >
316 |
317 |
318 |
319 |
324 | {
327 | plans.splice(index, 1);
328 | if (plans.length === 0)
329 | setPlans([
330 | {
331 | plan_name: "",
332 | total_wishes: 0,
333 | price: "",
334 | period: "",
335 | },
336 | ]);
337 | else setPlans([...plans]);
338 | }}
339 | >
340 |
341 |
342 |
343 |
344 | {index === plans.length - 1 && (
345 |
348 | setPlans([
349 | ...plans,
350 | {
351 | plan_name: "",
352 | total_wishes: 0,
353 | price: "",
354 | period: "",
355 | },
356 | ])
357 | }
358 | >
359 |
360 |
361 |
362 |
363 | )}
364 |
365 |
366 | ))}
367 |
368 |
369 |
370 |
371 |
372 |
373 |
374 | >
375 | );
376 | };
377 |
378 | export default PriceConfigurator;
379 |
--------------------------------------------------------------------------------
/src/pages/admin/prompt.page.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import {
3 | Box,
4 | Typography,
5 | Divider,
6 | Container,
7 | Stack,
8 | Button,
9 | SvgIcon,
10 | } from "@mui/material";
11 |
12 | import { ReactComponent as PlustWhiteIcon } from "../../assets/ico_plus_white.svg";
13 | import Prompt from "../../components/Prompt";
14 | import { IPromptAcceptSchema } from "../../redux/api/types";
15 | import { useGetProductsNamesQuery } from "../../redux/api/productApi";
16 | import { useGetPromptsQuery } from "../../redux/api/promptApi";
17 |
18 | const PromptConfigurator = () => {
19 | const [prompts, setPrompts] = useState([]);
20 | const [products, setProducts] = useState([]);
21 |
22 | const getNamesState = useGetProductsNamesQuery();
23 | const getPromptsState = useGetPromptsQuery();
24 |
25 | useEffect(() => {
26 | if (getNamesState.isSuccess) setProducts(getNamesState.data);
27 | }, [getNamesState]);
28 |
29 | useEffect(() => {
30 | if (getPromptsState.isSuccess) setPrompts([...getPromptsState.data]);
31 | }, [getPromptsState]);
32 |
33 | return (
34 | <>
35 |
36 |
48 | Prompt Configurator
49 |
50 |
51 |
52 |
53 |
54 |
55 |
80 |
81 | {prompts.map((prompt, index) => (
82 |
93 | ))}
94 |
95 |
96 | >
97 | );
98 | };
99 |
100 | export default PromptConfigurator;
101 |
--------------------------------------------------------------------------------
/src/pages/auth/forgot.page.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Container,
3 | Grid,
4 | Stack,
5 | Typography,
6 | FormControl,
7 | TextField,
8 | Box,
9 | SvgIcon,
10 | } from "@mui/material";
11 | import { KeyboardBackspace } from "@mui/icons-material";
12 | import { Link, useNavigate } from "react-router-dom";
13 | import { toast } from "react-toastify";
14 |
15 | import BackSignin from "../../assets/back_signin.png";
16 | import Logo from "../../logo.svg";
17 | import { useEffect, useState } from "react";
18 | import { useResetPasswordMutation } from "../../redux/api/authApi";
19 | import { LoadingButton } from "@mui/lab";
20 |
21 | const ForgotPage = () => {
22 | const [email, setEmail] = useState("");
23 |
24 | const [resetPassword, resetState] = useResetPasswordMutation();
25 |
26 | const navigate = useNavigate();
27 |
28 | useEffect(() => {
29 | if (resetState.isSuccess) {
30 | toast.success("Password reset!");
31 | navigate("/signin");
32 | }
33 | if (resetState.isError) {
34 | if (Array.isArray((resetState.error as any).data.detail)) {
35 | (resetState.error as any).data.detail.map((el: any) =>
36 | toast.error(`${el.loc[1]} ${el.msg}`)
37 | );
38 | } else toast.error((resetState.error as any).data.detail);
39 | }
40 | }, [resetState]);
41 |
42 | return (
43 | <>
44 |
45 |
46 |
47 |
48 |
57 | Audit, Fix, Refactor, Document any Code Within Seconds
58 |
59 |
60 |
68 |
76 |
77 |
78 | CodeGenie
79 |
80 |
81 |
82 |
83 | Forgot password?
84 |
85 |
86 | No worries, we will send you reset instructions
87 |
88 |
89 |
90 |
91 | Email address
92 |
93 | {
100 | setEmail(e.target.value);
101 | }}
102 | />
103 |
104 |
105 | {
115 | if (email === "") return;
116 | resetPassword({ email });
117 | }}
118 | loading={resetState.isLoading}
119 | >
120 | Reset Password
121 |
122 |
123 |
132 |
133 |
134 |
135 | Back to log in
136 |
137 |
138 |
139 |
140 |
141 | >
142 | );
143 | };
144 |
145 | export default ForgotPage;
146 |
--------------------------------------------------------------------------------
/src/pages/auth/signin.page.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import {
3 | Container,
4 | Grid,
5 | Box,
6 | Typography,
7 | Stack,
8 | Divider,
9 | FormControl,
10 | TextField,
11 | SvgIcon,
12 | } from "@mui/material";
13 | import { Link, useNavigate } from "react-router-dom";
14 | import { useForm, FormProvider, SubmitHandler } from "react-hook-form";
15 | import { object, string, TypeOf } from "zod";
16 | import { zodResolver } from "@hookform/resolvers/zod";
17 | import { toast } from "react-toastify";
18 | import {
19 | LoginSocialGoogle,
20 | LoginSocialGithub,
21 | IResolveParams,
22 | } from "reactjs-social-login";
23 | import { LoadingButton } from "@mui/lab";
24 |
25 | import BackSignin from "../../assets/back_signin.png";
26 | import Logo from "../../logo.svg";
27 |
28 | import { ReactComponent as GoogleIcon } from "../../assets/ico_google.svg";
29 | import { ReactComponent as FacebookIcon } from "../../assets/ico_facebook.svg";
30 | import { ReactComponent as TwitterIcon } from "../../assets/ico_twtter.svg";
31 | import { ReactComponent as GithubIcon } from "../../assets/ico_github.svg";
32 | import { ReactComponent as LinkedinIcon } from "../../assets/ico_linkedin.svg";
33 |
34 | import {
35 | useSigninUserMutation,
36 | useSocialAuthMutation,
37 | } from "../../redux/api/authApi";
38 | import { useAppDispatch } from "../../redux/store";
39 | import { setModule } from "../../redux/features/genieSlice";
40 |
41 | const signinSchema = object({
42 | email: string()
43 | .min(1, "Email address is required")
44 | .email("Email address is invalid"),
45 | password: string()
46 | .min(1, "Password is required")
47 | .min(8, "Password must be more than 8 characters"),
48 | });
49 |
50 | export type SigninInput = TypeOf;
51 |
52 | const SigninPage = () => {
53 | const [signinUser, signinState] = useSigninUserMutation();
54 | const navigate = useNavigate();
55 |
56 | const dispatch = useAppDispatch();
57 | const [authSocial, socialState] = useSocialAuthMutation();
58 |
59 | useEffect(() => {
60 | if (signinState.isSuccess) {
61 | toast.success("Login Success");
62 | if (!signinState.data.verified) navigate("/verify");
63 | else {
64 | if (signinState.data.role === "user") {
65 | localStorage.setItem("module", "All Code");
66 | dispatch(setModule("All Code"));
67 | navigate("/codegenie/all_code");
68 | } else {
69 | navigate("/admin/dashboard");
70 | }
71 | }
72 | }
73 | if (signinState.isError) {
74 | console.log(signinState);
75 | if (Array.isArray((signinState.error as any).data.detail)) {
76 | (signinState.error as any).data.detail.map((el: any) =>
77 | toast.error(`${el.loc[1]} ${el.msg}`)
78 | );
79 | } else toast.error((signinState.error as any).data.detail);
80 | }
81 | // eslint-disable-next-line react-hooks/exhaustive-deps
82 | }, [signinState]);
83 |
84 | useEffect(() => {
85 | if (socialState.isSuccess) {
86 | toast.success("Social singup success");
87 | if (socialState.data.role === "user") {
88 | localStorage.setItem("module", "All Code");
89 | dispatch(setModule("All Code"));
90 | navigate("/codegenie/all_code");
91 | } else {
92 | navigate("/admin/dashboard");
93 | }
94 | }
95 | if (socialState.isError) {
96 | if (Array.isArray((socialState.error as any).data.detail)) {
97 | (socialState.error as any).data.detail.map((el: any) =>
98 | toast.error(`${el.loc[1]} ${el.msg}`)
99 | );
100 | } else toast.error((socialState.error as any).data.detail);
101 | }
102 | // eslint-disable-next-line react-hooks/exhaustive-deps
103 | }, [socialState]);
104 |
105 | const methods = useForm({
106 | resolver: zodResolver(signinSchema),
107 | });
108 |
109 | const {
110 | register,
111 | handleSubmit,
112 | formState: { errors },
113 | } = methods;
114 |
115 | const onSubmitHandler: SubmitHandler = (values) => {
116 | signinUser(values);
117 | };
118 |
119 | return (
120 | <>
121 |
122 |
123 |
124 |
125 |
134 | Audit, Fix, Refactor, Document any Code Within Seconds
135 |
136 |
137 |
145 |
153 |
154 |
155 | CodeGenie
156 |
157 |
158 |
159 |
160 | Sign in your account
161 |
162 |
163 |
168 |
169 |
170 |
171 | Email address
172 |
173 |
180 |
181 |
182 |
187 | Password
188 |
195 | Forgot Password?
196 |
197 |
198 |
205 |
206 |
207 |
219 | Log in
220 |
221 |
222 |
223 |
230 |
231 | Or
232 |
233 |
234 |
235 |
244 | {
247 | if (data)
248 | authSocial({
249 | provider: provider as string,
250 | email: data.email as string,
251 | name: data.name as string,
252 | });
253 | }}
254 | onReject={(err) => {
255 | console.log(err);
256 | }}
257 | >
258 |
259 |
260 |
261 |
262 |
263 |
272 |
273 |
274 |
275 |
276 |
285 |
286 |
287 |
288 |
289 |
298 | console.log(err)}
304 | redirect_uri={window.location.href}
305 | onResolve={({ provider, data }: IResolveParams) => {
306 | if (data)
307 | authSocial({
308 | provider: provider as string,
309 | username: data.login as string,
310 | name: data.name,
311 | });
312 | }}
313 | >
314 |
315 |
316 |
317 |
318 |
319 |
328 |
329 |
330 |
331 |
332 |
333 |
334 | New user?{" "}
335 |
341 | Create an account
342 |
343 |
344 |
345 |
346 |
347 |
348 | >
349 | );
350 | };
351 |
352 | export default SigninPage;
353 |
--------------------------------------------------------------------------------
/src/pages/auth/signup.page.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState } from "react";
2 | import {
3 | Grid,
4 | Box,
5 | Typography,
6 | Container,
7 | Stack,
8 | SvgIcon,
9 | Divider,
10 | FormControl,
11 | TextField,
12 | Checkbox,
13 | } from "@mui/material";
14 | import { Link } from "react-router-dom";
15 | import {
16 | LoginSocialGoogle,
17 | LoginSocialGithub,
18 | IResolveParams,
19 | } from "reactjs-social-login";
20 | import { toast } from "react-toastify";
21 | import { object, string, TypeOf } from "zod";
22 | import { useForm, FormProvider, SubmitHandler } from "react-hook-form";
23 | import { zodResolver } from "@hookform/resolvers/zod";
24 | import { useNavigate } from "react-router-dom";
25 | import { LoadingButton } from "@mui/lab";
26 |
27 | import { ReactComponent as GoogleIcon } from "../../assets/ico_google.svg";
28 | import { ReactComponent as FacebookIcon } from "../../assets/ico_facebook.svg";
29 | import { ReactComponent as TwitterIcon } from "../../assets/ico_twtter.svg";
30 | import { ReactComponent as GithubIcon } from "../../assets/ico_github.svg";
31 | import { ReactComponent as LinkedinIcon } from "../../assets/ico_linkedin.svg";
32 |
33 | import BackSignup from "../../assets/back_signup.png";
34 | import Logo from "../../assets/logo_white.png";
35 |
36 | import {
37 | useSignupUserMutation,
38 | useSocialAuthMutation,
39 | } from "../../redux/api/authApi";
40 | import { useAppDispatch } from "../../redux/store";
41 | import { setModule } from "../../redux/features/genieSlice";
42 |
43 | const signupSchema = object({
44 | name: string().min(1, "Full name is required"),
45 | email: string()
46 | .min(1, "Email address is required")
47 | .email("Email address is invalid"),
48 | password: string()
49 | .min(1, "Password is required")
50 | .min(8, "Password must be more than 8 characters"),
51 | passwordConfirm: string().min(1, "Please confirm your password"),
52 | }).refine((data) => data.password === data.passwordConfirm, {
53 | path: ["passwordConfirm"],
54 | message: "Passwords do not match",
55 | });
56 |
57 | export type SignupInput = TypeOf;
58 |
59 | const SignupPage = () => {
60 | const [termsCheck, setTermsCheck] = useState(false);
61 |
62 | const [authSocial, socialState] = useSocialAuthMutation();
63 | const [signupUser, signupState] = useSignupUserMutation();
64 |
65 | const navigate = useNavigate();
66 | const dispatch = useAppDispatch();
67 |
68 | const methods = useForm({
69 | resolver: zodResolver(signupSchema),
70 | });
71 |
72 | const {
73 | register,
74 | handleSubmit,
75 | formState: { errors },
76 | } = methods;
77 |
78 | useEffect(() => {
79 | if (socialState.isSuccess) {
80 | toast.success("Social singup success");
81 | if (socialState.data.role === "user") {
82 | localStorage.setItem("module", "All Code");
83 | dispatch(setModule("All Code"));
84 | navigate("/codegenie/all_code");
85 | } else {
86 | navigate("/admin/dashboard");
87 | }
88 | }
89 | if (socialState.isError) {
90 | if (Array.isArray((socialState.error as any).data.detail)) {
91 | (socialState.error as any).data.detail.map((el: any) =>
92 | toast.error(`${el.loc[1]} ${el.msg}`)
93 | );
94 | } else toast.error((socialState.error as any).data.detail);
95 | }
96 | // eslint-disable-next-line react-hooks/exhaustive-deps
97 | }, [socialState]);
98 |
99 | useEffect(() => {
100 | if (signupState.isSuccess) {
101 | toast.success("User created successfully");
102 | navigate("/signin");
103 | }
104 | if (signupState.isError) {
105 | if (Array.isArray((signupState.error as any).data.detail)) {
106 | (signupState.error as any).data.detail.map((el: any) =>
107 | toast.error(`${el.loc[1]} ${el.msg}`)
108 | );
109 | } else toast.error((signupState.error as any).data.detail);
110 | }
111 | // eslint-disable-next-line react-hooks/exhaustive-deps
112 | }, [signupState]);
113 |
114 | const onSubmitHandler: SubmitHandler = (values) => {
115 | signupUser(values);
116 | };
117 |
118 | return (
119 | <>
120 |
121 |
122 |
123 |
124 |
132 |
133 |
134 | CodeGenie
135 |
136 |
137 |
146 | Audit, Fix, Refactor, Document any Code Within Seconds
147 |
148 |
149 |
156 |
157 |
158 | Create an account
159 |
160 |
161 | Sign up with social
162 |
163 |
164 |
173 | {
176 | if (data)
177 | authSocial({
178 | provider: provider as string,
179 | email: data.email as string,
180 | name: data.name as string,
181 | });
182 | }}
183 | onReject={(err) => {
184 | console.log(err);
185 | }}
186 | >
187 |
188 |
189 |
190 |
191 |
192 |
201 |
202 |
203 |
204 |
205 |
214 |
215 |
216 |
217 |
218 |
227 | console.log(err)}
233 | redirect_uri={window.location.href}
234 | onResolve={({ provider, data }: IResolveParams) => {
235 | if (data)
236 | authSocial({
237 | provider: provider as string,
238 | username: data.login as string,
239 | name: data.name,
240 | });
241 | }}
242 | >
243 |
244 |
245 |
246 |
247 |
248 |
257 |
258 |
259 |
260 |
261 |
262 |
269 |
270 | Or
271 |
272 |
273 |
274 |
279 |
280 |
281 |
282 | Name
283 |
284 |
290 |
291 |
292 |
293 | Email address
294 |
295 |
302 |
303 |
304 |
305 | Password
306 |
307 |
314 |
315 |
316 |
317 | Confirm Password
318 |
319 |
326 |
327 |
328 | setTermsCheck(e.target.checked)}
331 | />{" "}
332 |
333 | I agree to the{" "}
334 |
340 | Terms & Privacy Policy
341 |
342 |
343 |
344 |
345 |
358 | Sign Up
359 |
360 |
361 |
362 |
363 | Have an account?{" "}
364 |
370 | Sign In
371 |
372 |
373 |
374 |
375 |
376 |
377 | >
378 | );
379 | };
380 |
381 | export default SignupPage;
382 |
--------------------------------------------------------------------------------
/src/pages/auth/terms.page.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Typography, Container, Divider, SvgIcon } from "@mui/material";
2 | import { Link } from "react-router-dom";
3 | import { KeyboardBackspace } from "@mui/icons-material";
4 |
5 | const TermsPage = () => {
6 | return (
7 | <>
8 |
9 |
10 |
17 | Code Genie Terms of Service
18 |
19 |
20 | Last Updated: August 3, 2023
21 |
22 |
23 | These Terms of Service ("Terms") govern your access to and use of
24 | Code Genie, a product owned and operated by OceSha, Inc., a Florida
25 | company ("we," "our," or "us"). Please read these Terms carefully
26 | before using Code Genie.
27 |
28 |
29 | 1. Acceptance of Terms
30 |
31 |
32 | By accessing or using Code Genie, you agree to be bound by these
33 | Terms. If you do not agree with these Terms, you must not access or
34 | use Code Genie.
35 |
36 |
37 | 2. Registration
38 |
39 |
40 | You may be required to register for an account to use certain
41 | features of Code Genie. You agree to provide accurate and complete
42 | information during registration and to keep your account information
43 | up to date.
44 |
45 |
46 | 3. Use of Code Genie
47 |
48 |
49 | You agree to use Code Genie in accordance with all applicable laws
50 | and regulations. You may not:
51 |
52 |
53 | Use Code Genie for any unlawful or fraudulent purpose
54 |
55 |
56 | Interfere with or disrupt the operation of Code Genie
57 |
58 |
59 | Reverse engineer, decompile, or disassemble Code Genie
60 |
61 |
62 | Use Code Genie in a way that infringes the rights of others
63 |
64 |
65 |
66 |
67 |
68 | 4. Intellectual Property
69 |
70 |
71 | Code Genie and its content, features, and functionality are owned by
72 | OceSha, Inc. and are protected by intellectual property laws. You
73 | are granted a limited, non-exclusive, non-transferable license to
74 | use Code Genie for your personal or business use. You may not
75 | reproduce, distribute, or create derivative works of Code Genie
76 | without our express written permission.
77 |
78 |
79 | 5. User Content
80 |
81 |
82 | You may be able to submit content to Code Genie, such as code,
83 | comments, and feedback. You retain ownership of your content, but
84 | you grant us a worldwide, royalty-free license to use, reproduce,
85 | modify, and distribute your content as necessary to provide Code
86 | Genie.
87 |
88 |
89 | 6. Termination
90 |
91 |
92 | We may terminate or suspend your access to Code Genie at our sole
93 | discretion, without notice, for conduct that we believe violates
94 | these Terms or is harmful to us, other users of Code Genie, or third
95 | parties, or for any other reason.
96 |
97 |
98 | 7. Disclaimers
99 |
100 |
101 | Code Genie is provided "as is" and "as available" without any
102 | warranties of any kind, either express or implied. We do not warrant
103 | that Code Genie will be uninterrupted, error-free, or free of
104 | harmful components.
105 |
106 |
107 | 8. Limitation of Liability
108 |
109 |
110 | To the fullest extent permitted by law, OceSha, Inc. shall not be
111 | liable for any indirect, incidental, special, consequential, or
112 | punitive damages, or any loss of profits or revenues, whether
113 | incurred directly or indirectly, arising out of or in connection
114 | with your use of Code Genie.
115 |
116 |
117 | 9. Governing Law
118 |
119 |
120 | These Terms are governed by the laws of the State of Delaware, USA,
121 | without regard to its conflict of law principles.
122 |
123 |
124 | 10. Changes to Terms
125 |
126 |
127 | We may revise these Terms from time to time. We will notify you of
128 | any changes by posting the updated Terms on this page. Your
129 | continued use of Code Genie after the changes are posted constitutes
130 | your acceptance of the new Terms.
131 |
132 |
133 | 11. Contact Us
134 |
135 |
136 | If you have any questions or concerns about these Terms, please
137 | contact us at:
138 |
139 |
140 | OceSha, Inc.
141 |
142 | Los Angeles, Ca
143 |
144 | 310-748-8901
145 |
146 | support@ocesha.com
147 |
148 |
149 |
150 | By using Code Genie, you acknowledge that you have read, understood,
151 | and agree to be bound by these Terms. If you do not agree with these
152 | Terms, please do not use Code Genie.
153 |
154 |
163 |
164 |
165 |
166 | Back to log in
167 |
168 |
169 |
170 | >
171 | );
172 | };
173 |
174 | export default TermsPage;
175 |
--------------------------------------------------------------------------------
/src/pages/auth/verify.page.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect } from "react";
2 | import { LoadingButton } from "@mui/lab";
3 | import {
4 | Container,
5 | Stack,
6 | Card,
7 | Typography,
8 | TextField,
9 | Box,
10 | } from "@mui/material";
11 | import { toast } from "react-toastify";
12 | import { object, string, TypeOf } from "zod";
13 | import { useForm, FormProvider, SubmitHandler } from "react-hook-form";
14 | import { zodResolver } from "@hookform/resolvers/zod";
15 | import { useNavigate } from "react-router-dom";
16 |
17 | import { useVerifyEmailMutation } from "../../redux/api/authApi";
18 | import { useAppDispatch } from "../../redux/store";
19 | import { setModule } from "../../redux/features/genieSlice";
20 |
21 | const verifySchema = object({
22 | code: string().min(1, "Verification code is required"),
23 | });
24 |
25 | export type VerifyInput = TypeOf;
26 |
27 | const VerifyPage = () => {
28 | const [verifyEmail, verifyState] = useVerifyEmailMutation();
29 | const dispatch = useAppDispatch();
30 | const navigate = useNavigate();
31 |
32 | const methods = useForm({
33 | resolver: zodResolver(verifySchema),
34 | });
35 |
36 | const {
37 | register,
38 | handleSubmit,
39 | formState: { errors },
40 | } = methods;
41 |
42 | const onSubmitHandler: SubmitHandler = (values) => {
43 | verifyEmail(values);
44 | };
45 |
46 | useEffect(() => {
47 | if (verifyState.isSuccess) {
48 | toast.success("Verified successfully");
49 | localStorage.setItem("module", "All Code");
50 | dispatch(setModule("All Code"));
51 | navigate("/codegenie/all_code");
52 | }
53 | if (verifyState.isError) {
54 | if (Array.isArray((verifyState.error as any).data.detail)) {
55 | (verifyState.error as any).data.detail.map((el: any) =>
56 | toast.error(`${el.loc[1]} ${el.msg}`)
57 | );
58 | } else toast.error((verifyState.error as any).data.detail);
59 | }
60 | // eslint-disable-next-line react-hooks/exhaustive-deps
61 | }, [verifyState]);
62 |
63 | return (
64 | <>
65 |
66 |
67 |
68 |
73 |
74 |
75 | Verification Code
76 |
77 |
85 |
92 | Send
93 |
94 |
95 |
96 |
97 |
98 |
99 | >
100 | );
101 | };
102 |
103 | export default VerifyPage;
104 |
--------------------------------------------------------------------------------
/src/pages/genie.page.tsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useState, useRef } from "react";
2 | import {
3 | Container,
4 | Link,
5 | Typography,
6 | Breadcrumbs,
7 | Divider,
8 | Grid,
9 | Stack,
10 | SvgIcon,
11 | Box,
12 | Tabs,
13 | Tab,
14 | Backdrop,
15 | CircularProgress,
16 | Modal,
17 | Button,
18 | TextField,
19 | } from "@mui/material";
20 | import { NavigateNext } from "@mui/icons-material";
21 | import { styled } from "@mui/material/styles";
22 | import CodeEditor from "@uiw/react-textarea-code-editor";
23 | import { LoadingButton } from "@mui/lab";
24 | import { toast } from "react-toastify";
25 | import {
26 | useSendUrlMutation,
27 | useUploadImageMutation,
28 | } from "../redux/api/genieApi";
29 |
30 | import { ReactComponent as TextIcon } from "../assets/ico_text.svg";
31 | import { ReactComponent as ImageIcon } from "../assets/ico_image.svg";
32 | import { ReactComponent as UrlIcon } from "../assets/ico_url.svg";
33 | import { ReactComponent as WishIcon } from "../assets/ico_wish.svg";
34 | import TotalPanel from "../components/genie/TotalPanel";
35 | import { useAppDispatch, useAppSelector } from "../redux/store";
36 | import { useGetProductQuery } from "../redux/api/productApi";
37 | import { useRunPromptMutation } from "../redux/api/promptApi";
38 | import { setMsg } from "../redux/features/genieSlice";
39 | import { useNavigate } from "react-router-dom";
40 | import MagicWand from "../components/MagicWand";
41 |
42 | const loadTypes = [
43 | {
44 | icon: (
45 |
53 |
54 |
55 |
56 |
57 | ),
58 | },
59 | {
60 | icon: (
61 |
69 |
70 |
71 |
72 |
73 | ),
74 | },
75 | {
76 | icon: (
77 |
85 |
86 |
87 |
88 |
89 | ),
90 | },
91 | ];
92 |
93 | const CodeBox = styled(Box)(({ theme }) => ({
94 | border: "1px solid",
95 | borderColor: theme.palette.mode === "dark" ? "#737373" : "#E3E3E3",
96 | borderRadius: 4,
97 | height: "500px",
98 | overflow: "auto",
99 | "::-webkit-scrollbar": {
100 | width: 4,
101 | },
102 | "::-webkit-scrollbar-thumb": {
103 | backgroundColor: theme.palette.divider,
104 | borderRadius: 4,
105 | },
106 | "::-webkit-scrollbar-track": {
107 | backgroundColor: theme.palette.mode === "dark" ? "#2D2D2D" : "#fff",
108 | },
109 | }));
110 |
111 | const GeniePage = () => {
112 | const [value, setValue] = useState(0);
113 | const [code, setCode] = useState(``);
114 | const [open, setOpen] = useState(false);
115 | const wrapperRef = useRef(null);
116 | const [url, setURL] = useState("");
117 |
118 | const genieSelector = useAppSelector((state) => state.genieState);
119 | const dipatch = useAppDispatch();
120 | const navigate = useNavigate();
121 |
122 | const productState = useGetProductQuery({
123 | _id: "",
124 | product_name: "CodeGenie",
125 | product_module: genieSelector.module ? genieSelector.module : "",
126 | });
127 |
128 | const [runPrompt, runState] = useRunPromptMutation();
129 | const [uploadImage, uploadState] = useUploadImageMutation();
130 | const [sendUrl, urlState] = useSendUrlMutation();
131 |
132 | useEffect(() => {
133 | if (uploadState.isSuccess) {
134 | setCode(uploadState.data.content);
135 | }
136 | }, [uploadState]);
137 |
138 | useEffect(() => {
139 | if (runState.isSuccess) {
140 | toast.success("Executed successfully");
141 | dipatch(setMsg(runState.data));
142 | }
143 | // eslint-disable-next-line react-hooks/exhaustive-deps
144 | }, [runState]);
145 |
146 | useEffect(() => {
147 | if (urlState.isSuccess) setCode(urlState.data.content);
148 | }, [urlState]);
149 |
150 | if (productState.isLoading || productState.isFetching || !productState.data)
151 | return (
152 | theme.zIndex.drawer + 1 }}
154 | open={true}
155 | >
156 |
157 |
158 | );
159 |
160 | const breadcrumbs = [
161 | {
166 | navigate("/");
167 | }}
168 | >
169 | Home
170 | ,
171 |
172 | {genieSelector.module}
173 | ,
174 | ];
175 |
176 | const {
177 | module_description,
178 | source_check,
179 | source_text,
180 | source_image,
181 | source_url,
182 | input_box_title,
183 | input_box_description,
184 | export_check,
185 | export_text,
186 | export_pdf,
187 | export_word,
188 | } = productState.data;
189 |
190 | return (
191 | <>
192 | {runState.isLoading && (
193 |
194 | theme.zIndex.drawer + 1 }}
196 | open={true}
197 | >
198 |
199 |
200 | Executing your wish
201 |
202 |
203 |
204 | )}
205 |
206 |
207 | }
209 | sx={{ marginY: 3 }}
210 | >
211 | {breadcrumbs}
212 |
213 |
214 |
215 |
216 | {module_description}
217 |
218 | {
223 | let formData = new FormData();
224 | if (event.target.files) {
225 | formData.append("image", event.target.files[0]);
226 | uploadImage(formData);
227 | }
228 | }}
229 | />
230 |
232 | setValue(newValue)
233 | }
234 | value={value}
235 | sx={{
236 | "& .MuiTabs-scroller .MuiTabs-flexContainer": { gap: 2 },
237 | }}
238 | >
239 | {source_check.includes("source_text") && (
240 |
253 | )}
254 | {source_check.includes("source_image") && (
255 | wrapperRef.current?.click()}
268 | />
269 | )}
270 | {source_check.includes("source_url") && (
271 | setOpen(true)}
284 | />
285 | )}
286 |
287 |
288 | {input_box_title}
289 |
290 |
291 |
292 | setCode(evn.target.value)}
297 | padding={15}
298 | style={{
299 | fontSize: 16,
300 | backgroundColor: "inherit",
301 | fontFamily:
302 | "ui-monospace,SFMono-Regular,SF Mono,Consolas,Liberation Mono,Menlo,monospace",
303 | }}
304 | />
305 |
306 |
307 |
310 |
311 |
312 | }
313 | loading={runState.isLoading}
314 | sx={{
315 | background:
316 | "linear-gradient(270deg, #4BA5EB 0%, #0168B5 100%)",
317 | marginLeft: 5,
318 | color: "white",
319 | paddingX: "20px",
320 | paddingY: "12px",
321 | borderRadius: "4px",
322 | width: "fit-content",
323 | }}
324 | onClick={() => {
325 | if (code === "") {
326 | toast.error("No empty code!");
327 | return;
328 | }
329 | runPrompt({
330 | product_name: "CodeGenie",
331 | product_module: genieSelector.module
332 | ? genieSelector.module
333 | : "",
334 | code: code,
335 | });
336 | }}
337 | >
338 | Execute Wish
339 |
340 |
341 |
342 |
343 |
344 |
345 |
351 |
352 |
353 |
354 |
355 | setOpen(false)}
358 | aria-labelledby="child-modal-title"
359 | aria-describedby="child-modal-description"
360 | >
361 |
376 | URL
377 | Input code location URL
378 | setURL(e.target.value)}
381 | error={url === ""}
382 | helperText={url === "" ? "URL field is required." : ""}
383 | size="small"
384 | fullWidth
385 | placeholder="URL"
386 | sx={{ mb: 2 }}
387 | />
388 |
389 |
399 |
407 |
408 |
409 |
410 | >
411 | );
412 | };
413 |
414 | export default GeniePage;
415 |
--------------------------------------------------------------------------------
/src/pages/pricing.page.tsx:
--------------------------------------------------------------------------------
1 | const PricingPage = () => {
2 | return <>>;
3 | };
4 |
5 | export default PricingPage;
6 |
--------------------------------------------------------------------------------
/src/pages/unauthorized.page.tsx:
--------------------------------------------------------------------------------
1 | import { Box, Container, Typography } from "@mui/material";
2 |
3 | const UnauthorizePage = () => {
4 | return (
5 |
6 |
16 |
21 | Unauthorized Page
22 |
23 |
24 |
25 | );
26 | };
27 |
28 | export default UnauthorizePage;
29 |
--------------------------------------------------------------------------------
/src/react-app-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/src/redux/api/authApi.ts:
--------------------------------------------------------------------------------
1 | import { createApi } from "@reduxjs/toolkit/query/react";
2 | import customFetchBase from "./customFetchBase";
3 | import {
4 | IGenericResponse,
5 | ISigninReseponseSchema,
6 | ISocialSignupSchema,
7 | } from "./types";
8 | import { SignupInput } from "../../pages/auth/signup.page";
9 | import { SigninInput } from "../../pages/auth/signin.page";
10 | import { userApi } from "./userApi";
11 |
12 | export const authApi = createApi({
13 | reducerPath: "authApi",
14 | baseQuery: customFetchBase,
15 | endpoints: (builder) => ({
16 | socialAuth: builder.mutation<
17 | { access_token: string; role: string },
18 | ISocialSignupSchema
19 | >({
20 | query(data) {
21 | return {
22 | url: "auth/social",
23 | method: "POST",
24 | body: data,
25 | credentials: "include",
26 | };
27 | },
28 | async onQueryStarted(args, { dispatch, queryFulfilled }) {
29 | try {
30 | await queryFulfilled;
31 | await dispatch(userApi.endpoints.getMe.initiate(null));
32 | } catch (error) {}
33 | },
34 | }),
35 | signupUser: builder.mutation({
36 | query(data) {
37 | return {
38 | url: "auth/signup",
39 | method: "POST",
40 | body: data,
41 | };
42 | },
43 | }),
44 | signinUser: builder.mutation({
45 | query(data) {
46 | return {
47 | url: "auth/signin",
48 | method: "POST",
49 | body: data,
50 | credentials: "include",
51 | };
52 | },
53 | async onQueryStarted(args, { dispatch, queryFulfilled }) {
54 | try {
55 | await queryFulfilled;
56 | await dispatch(userApi.endpoints.getMe.initiate(null));
57 | } catch (error) {}
58 | },
59 | }),
60 | verifyEmail: builder.mutation({
61 | query(data) {
62 | return {
63 | url: "auth/verify",
64 | method: "PATCH",
65 | body: data,
66 | };
67 | },
68 | }),
69 | resetPassword: builder.mutation({
70 | query(data) {
71 | return {
72 | url: "auth/forgot",
73 | method: "PATCH",
74 | body: data,
75 | };
76 | },
77 | }),
78 | }),
79 | });
80 |
81 | export const {
82 | useSocialAuthMutation,
83 | useSignupUserMutation,
84 | useSigninUserMutation,
85 | useVerifyEmailMutation,
86 | useResetPasswordMutation,
87 | } = authApi;
88 |
--------------------------------------------------------------------------------
/src/redux/api/customFetchBase.ts:
--------------------------------------------------------------------------------
1 | import {
2 | BaseQueryFn,
3 | FetchArgs,
4 | fetchBaseQuery,
5 | FetchBaseQueryError,
6 | } from "@reduxjs/toolkit/query";
7 | import { Mutex } from "async-mutex";
8 | import { logout } from "../features/userSlice";
9 |
10 | const baseUrl = `${process.env.REACT_APP_SERVER_ENDPOINT}/api/`;
11 |
12 | // Create a new mutex
13 | const mutex = new Mutex();
14 |
15 | const baseQuery = fetchBaseQuery({
16 | baseUrl,
17 | });
18 |
19 | const customFetchBase: BaseQueryFn<
20 | string | FetchArgs,
21 | unknown,
22 | FetchBaseQueryError
23 | > = async (args, api, extraOptions) => {
24 | // wait until the mutex is available without locking it
25 | await mutex.waitForUnlock();
26 | let result = await baseQuery(args, api, extraOptions);
27 | if ((result.error?.data as any)?.message === "You are not logged in") {
28 | if (!mutex.isLocked()) {
29 | const release = await mutex.acquire();
30 |
31 | try {
32 | const refreshResult = await baseQuery(
33 | { credentials: "include", url: "auth/refresh" },
34 | api,
35 | extraOptions
36 | );
37 |
38 | if (refreshResult.data) {
39 | // Retry the initial query
40 | result = await baseQuery(args, api, extraOptions);
41 | } else {
42 | api.dispatch(logout());
43 | window.location.href = "/login";
44 | }
45 | } finally {
46 | // release must be called once the mutex should be released again.
47 | release();
48 | }
49 | } else {
50 | // wait until the mutex is available without locking it
51 | await mutex.waitForUnlock();
52 | result = await baseQuery(args, api, extraOptions);
53 | }
54 | }
55 |
56 | return result;
57 | };
58 |
59 | export default customFetchBase;
60 |
--------------------------------------------------------------------------------
/src/redux/api/genieApi.ts:
--------------------------------------------------------------------------------
1 | import { createApi } from "@reduxjs/toolkit/query/react";
2 | import customFetchBase from "./customFetchBase";
3 |
4 | export const genieApi = createApi({
5 | reducerPath: "",
6 | baseQuery: customFetchBase,
7 | endpoints: (builder) => ({
8 | uploadImage: builder.mutation<{ content: string }, FormData>({
9 | query(data) {
10 | return {
11 | url: "genie/image",
12 | method: "POST",
13 | credentials: "include",
14 | body: data,
15 | };
16 | },
17 | }),
18 | sendUrl: builder.mutation<{ content: string }, { url: string }>({
19 | query(data) {
20 | return {
21 | url: "genie/url",
22 | method: "POST",
23 | credentials: "include",
24 | body: data,
25 | };
26 | },
27 | }),
28 | exportFile: builder.mutation<
29 | { path: string },
30 | { doc_type: string; advice: any }
31 | >({
32 | query({ doc_type, advice }) {
33 | return {
34 | url: `genie/export/${doc_type}`,
35 | method: "POST",
36 | credentials: "include",
37 | body: { advice },
38 | };
39 | },
40 | }),
41 | }),
42 | });
43 |
44 | export const {
45 | useUploadImageMutation,
46 | useSendUrlMutation,
47 | useExportFileMutation,
48 | } = genieApi;
49 |
--------------------------------------------------------------------------------
/src/redux/api/productApi.ts:
--------------------------------------------------------------------------------
1 | import { createApi } from "@reduxjs/toolkit/query/react";
2 | import customFetchBase from "./customFetchBase";
3 |
4 | import { ProductSettingSaveInput } from "../../pages/admin/product.page";
5 | import { PriceSettingSaveInput } from "../../pages/admin/price.page";
6 | import {
7 | IGenericResponse,
8 | IPlanDetail,
9 | IProduct,
10 | IProductHeadings,
11 | } from "./types";
12 |
13 | export const productApi = createApi({
14 | reducerPath: "productApi",
15 | baseQuery: customFetchBase,
16 | tagTypes: ["Product"],
17 | endpoints: (builder) => ({
18 | getProduct: builder.query({
19 | query({ product_name, product_module }) {
20 | return {
21 | url: `products?product_name=${product_name}&product_module=${product_module}`,
22 | };
23 | },
24 | transformResponse: (results: { data: IProduct }) => results.data,
25 | providesTags: [{ type: "Product", id: "LIST" }],
26 | }),
27 | addProduct: builder.mutation({
28 | query(data) {
29 | return {
30 | url: "products",
31 | method: "POST",
32 | body: data,
33 | };
34 | },
35 | invalidatesTags: [{ type: "Product", id: "LIST" }],
36 | }),
37 | updateProduct: builder.mutation({
38 | query(data) {
39 | return {
40 | url: "products",
41 | method: "PATCH",
42 | body: data,
43 | };
44 | },
45 | invalidatesTags: [{ type: "Product", id: "LIST" }],
46 | }),
47 | searchProduct: builder.query({
48 | query(searchKey: string) {
49 | return {
50 | url: `products/search?search_key=${searchKey}`,
51 | };
52 | },
53 | transformResponse: (results: { data: IProductHeadings[] }) =>
54 | results.data,
55 | }),
56 | updatePrice: builder.mutation({
57 | query(data) {
58 | return {
59 | url: "products/update_price",
60 | method: "PATCH",
61 | body: data,
62 | };
63 | },
64 | }),
65 | getProductsNames: builder.query({
66 | query() {
67 | return {
68 | url: "products/names",
69 | method: "GET",
70 | };
71 | },
72 | transformResponse: (results: { data: string[] }) => results.data,
73 | }),
74 | getModules: builder.query({
75 | query(product_name: string) {
76 | return {
77 | url: `products/modules?product_name=${product_name}`,
78 | method: "GET",
79 | };
80 | },
81 | transformResponse: (results: { data: { product_module: string }[] }) =>
82 | results.data.map((item) => item.product_module),
83 | }),
84 | getPrices: builder.query<
85 | IPlanDetail[] | null,
86 | { product_name: string; product_module: string }
87 | >({
88 | query({ product_name, product_module }) {
89 | return {
90 | url: `products/prices?product_name=${product_name}&product_module=${product_module}`,
91 | method: "GET",
92 | };
93 | },
94 | transformResponse: (results: {
95 | data: { plan_details: IPlanDetail[] } | null;
96 | }) => (results.data ? results.data.plan_details : null),
97 | }),
98 | }),
99 | });
100 |
101 | export const {
102 | useUpdateProductMutation,
103 | useLazyGetProductQuery,
104 | useGetProductQuery,
105 | useLazySearchProductQuery,
106 | useUpdatePriceMutation,
107 | useAddProductMutation,
108 | useGetProductsNamesQuery,
109 | useLazyGetModulesQuery,
110 | useLazyGetPricesQuery,
111 | } = productApi;
112 |
--------------------------------------------------------------------------------
/src/redux/api/promptApi.ts:
--------------------------------------------------------------------------------
1 | import { createApi } from "@reduxjs/toolkit/query/react";
2 | import customFetchBase from "./customFetchBase";
3 |
4 | import {
5 | IGenericResponse,
6 | IPromptAcceptSchema,
7 | IPromptRunSchema,
8 | } from "./types";
9 | import { IPromptSchema } from "../../components/Prompt";
10 |
11 | export const promptApi = createApi({
12 | reducerPath: "promptApi",
13 | baseQuery: customFetchBase,
14 | tagTypes: ["Prompt"],
15 | endpoints: (builder) => ({
16 | addPrompt: builder.mutation({
17 | query(data) {
18 | return {
19 | url: "prompts",
20 | method: "POST",
21 | body: data,
22 | };
23 | },
24 | invalidatesTags: [{ type: "Prompt", id: "LIST" }],
25 | }),
26 | getPrompts: builder.query({
27 | query() {
28 | return {
29 | url: "prompts",
30 | method: "GET",
31 | };
32 | },
33 | transformResponse: (results: { data: IPromptAcceptSchema[] }) =>
34 | results.data,
35 | providesTags: [{ type: "Prompt", id: "LIST" }],
36 | }),
37 | updatePrompt: builder.mutation<
38 | IGenericResponse,
39 | { id: string; info: IPromptSchema }
40 | >({
41 | query({ id, info }) {
42 | return {
43 | url: `prompts/${id}`,
44 | method: "PATCH",
45 | body: info,
46 | };
47 | },
48 | invalidatesTags: [{ type: "Prompt", id: "LIST" }],
49 | }),
50 | getPromptNames: builder.query<
51 | string[],
52 | { product_name: string; product_module: string }
53 | >({
54 | query({ product_name, product_module }) {
55 | return {
56 | url: `prompts/names?product_name=${product_name}&product_module=${product_module}`,
57 | };
58 | },
59 | transformResponse: (results: { data: { prompt_name: string }[] }) =>
60 | results.data.map((item) => item.prompt_name),
61 | }),
62 | runPrompt: builder.mutation, IPromptRunSchema>({
63 | query(data) {
64 | return {
65 | url: "prompts/run",
66 | method: "POST",
67 | body: data,
68 | };
69 | },
70 | transformResponse: (results: { msg: Array }) => results.msg,
71 | }),
72 | }),
73 | });
74 |
75 | export const {
76 | useAddPromptMutation,
77 | useGetPromptsQuery,
78 | useUpdatePromptMutation,
79 | useGetPromptNamesQuery,
80 | useRunPromptMutation,
81 | } = promptApi;
82 |
--------------------------------------------------------------------------------
/src/redux/api/types.ts:
--------------------------------------------------------------------------------
1 | export interface IGenericResponse {
2 | status: string;
3 | message: string;
4 | }
5 |
6 | export interface IProduct {
7 | id: string;
8 | product_name: string;
9 | product_module: string;
10 | module_description: string;
11 | source_check: string[];
12 | source_text: string;
13 | source_image: string;
14 | source_url: string;
15 | input_box_title: string;
16 | input_box_description: string;
17 | export_check: string[];
18 | export_word: string;
19 | export_pdf: string;
20 | export_text: string;
21 | plan_details: IPlanDetail[] | null;
22 | }
23 |
24 | export interface IProductHeadings {
25 | _id: string;
26 | product_name: string;
27 | product_module: string;
28 | }
29 |
30 | export interface IPlanDetail {
31 | plan_name: string;
32 | total_wishes: number;
33 | price: string;
34 | period: string;
35 | }
36 |
37 | export interface IPrompt {
38 | _id: string;
39 | product: string;
40 | plan: string;
41 | module: string;
42 | prompt_name: string;
43 | order: number;
44 | prompt: string;
45 | }
46 |
47 | export interface IPromptAcceptSchema {
48 | _id: string;
49 | product_name: string;
50 | product_module: string;
51 | plan: string;
52 | prompt_name: string;
53 | order: number;
54 | prompt: string;
55 | }
56 |
57 | export interface IPromptRunSchema {
58 | product_name: string;
59 | product_module: string;
60 | code: string;
61 | }
62 |
63 | export interface ISocialSignupSchema {
64 | provider: string;
65 | email?: string | null;
66 | username?: string | null;
67 | name: string;
68 | }
69 |
70 | export interface ISigninReseponseSchema {
71 | access_token: string;
72 | role: string;
73 | verified: boolean;
74 | }
75 |
76 | export interface IUser {
77 | provider: string;
78 | name: string;
79 | email: string | null;
80 | role: string;
81 | username: string | null;
82 | }
83 |
--------------------------------------------------------------------------------
/src/redux/api/userApi.ts:
--------------------------------------------------------------------------------
1 | import { createApi } from "@reduxjs/toolkit/query/react";
2 | import customFetchBase from "./customFetchBase";
3 |
4 | import { setUser } from "../features/userSlice";
5 | import { IUser } from "./types";
6 |
7 | export const userApi = createApi({
8 | reducerPath: "userApi",
9 | baseQuery: customFetchBase,
10 | tagTypes: ["User"],
11 | endpoints: (builder) => ({
12 | getMe: builder.query({
13 | query() {
14 | return {
15 | url: "users/me",
16 | credentials: "include",
17 | };
18 | },
19 | transformResponse: (result: { user: IUser }) => result.user,
20 | async onQueryStarted(args, { dispatch, queryFulfilled }) {
21 | try {
22 | const { data } = await queryFulfilled;
23 | dispatch(setUser(data));
24 | } catch (error) {}
25 | },
26 | }),
27 | }),
28 | });
29 |
--------------------------------------------------------------------------------
/src/redux/features/genieSlice.ts:
--------------------------------------------------------------------------------
1 | import { createSlice, PayloadAction } from "@reduxjs/toolkit";
2 |
3 | interface GenieState {
4 | module?: string | null;
5 | prompt_name: string | null;
6 | msg: any;
7 | }
8 |
9 | const initialState: GenieState = {
10 | module: localStorage.getItem("module"),
11 | prompt_name: null,
12 | msg: {},
13 | };
14 |
15 | export const genieSlice = createSlice({
16 | name: "genieSlice",
17 | initialState,
18 | reducers: {
19 | setModule: (state, action: PayloadAction) => {
20 | state.module = action.payload;
21 | },
22 | setPromptName: (state, action: PayloadAction) => {
23 | state.prompt_name = action.payload;
24 | },
25 | setMsg: (state, action: PayloadAction