├── .eslintrc.json ├── .gitignore ├── LICENSE ├── README.md ├── next.config.js ├── package-lock.json ├── package.json ├── pnpm-lock.yaml ├── postcss.config.js ├── public ├── favicon.png ├── practice.png └── testing.png ├── src └── app │ ├── Timer.tsx │ ├── dots.css │ ├── globals.css │ ├── layout.tsx │ ├── page.tsx │ ├── test │ └── page.tsx │ └── utils │ └── getWordCount.ts ├── tailwind.config.ts └── tsconfig.json /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /.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 | .yarn/install-state.gz 8 | 9 | # testing 10 | /coverage 11 | 12 | # next.js 13 | /.next/ 14 | /out/ 15 | 16 | # production 17 | /build 18 | 19 | # misc 20 | .DS_Store 21 | *.pem 22 | 23 | # debug 24 | npm-debug.log* 25 | yarn-debug.log* 26 | yarn-error.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | 34 | # typescript 35 | *.tsbuildinfo 36 | next-env.d.ts 37 | 38 | .env -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 - PRESENT Kunal Singh 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### ✨ This project is for [Quine Quest](https://quine.sh/repo/KunalSin9h-LearnNotes-731176181), upvote the project [here](https://quine.sh/repo/KunalSin9h-LearnNotes-731176181). 2 | 3 | # LeanNotes 4 | 5 | An Notion Like notes talking app with 2-layer AI assistance for better learning. Get your notes done in a breeze. Markdown supported. 6 | 7 | Project is live at [https://learnnotes.vercel.app/](https://learnnotes.vercel.app/) 8 | 9 | ### Local Setup 10 | 11 | Clone the repo: 12 | 13 | ```bash 14 | git clone https://github.com/kunalsin9h/LearnNotes.git 15 | ``` 16 | 17 | Install dependencies: 18 | 19 | ```bash 20 | cd LearnNotes 21 | 22 | pnpm install 23 | ``` 24 | 25 | First, put an `OPENAI_API_KEY` in your `.env` file. You can get one from [OpenAI](https://beta.openai.com/). 26 | 27 | And then run the development server: 28 | 29 | ```bash 30 | pnpm dev 31 | ``` 32 | 33 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 34 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = {} 3 | module.exports = nextConfig 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "whats-going-on", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "next": "14.0.4", 13 | "novel": "^0.1.22", 14 | "react": "^18.2.0", 15 | "react-dom": "^18.2.0", 16 | "react-hot-toast": "^2.4.1" 17 | }, 18 | "devDependencies": { 19 | "@types/node": "^20", 20 | "@types/react": "^18", 21 | "@types/react-dom": "^18", 22 | "autoprefixer": "^10.0.1", 23 | "eslint": "^8", 24 | "eslint-config-next": "14.0.4", 25 | "postcss": "^8.4.21", 26 | "tailwindcss": "^3.3.0", 27 | "typescript": "^5" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunalSin9h/LearnNotes/899c2520730aceca2d792b1e68acceb41b66a057/public/favicon.png -------------------------------------------------------------------------------- /public/practice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunalSin9h/LearnNotes/899c2520730aceca2d792b1e68acceb41b66a057/public/practice.png -------------------------------------------------------------------------------- /public/testing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KunalSin9h/LearnNotes/899c2520730aceca2d792b1e68acceb41b66a057/public/testing.png -------------------------------------------------------------------------------- /src/app/Timer.tsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from "react"; 2 | 3 | const Timer = () => { 4 | const [minutes, setMinutes] = useState(0); 5 | const [seconds, setSeconds] = useState(0); 6 | const [hr, setHr] = useState(0); 7 | 8 | useEffect(() => { 9 | const timer = setInterval(() => { 10 | if (seconds === 60) { 11 | setMinutes((m) => m + 1); 12 | setSeconds(0); 13 | } 14 | if (minutes === 60) { 15 | setHr((h) => (h += 1)); 16 | setMinutes(0); 17 | } 18 | 19 | setSeconds((s) => s + 1); 20 | }, 1000); 21 | 22 | return () => clearInterval(timer); 23 | }, [minutes, seconds]); 24 | 25 | return ( 26 |
27 |

{`${hr.toString().padStart(2, "0")}:${minutes 28 | .toString() 29 | .padStart(2, "0")}:${seconds.toString().padStart(2, "0")}`}

30 |
31 | ); 32 | }; 33 | 34 | export default Timer; 35 | -------------------------------------------------------------------------------- /src/app/dots.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-image: radial-gradient(black 1px, transparent 0); 3 | background-size: 40px 40px; 4 | background-position: -19px -19px; 5 | } 6 | -------------------------------------------------------------------------------- /src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | *::-webkit-scrollbar { 6 | display: none; 7 | } 8 | 9 | html { 10 | background-color: #f5f7f8; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/layout.tsx: -------------------------------------------------------------------------------- 1 | import type { Metadata } from "next"; 2 | import "./globals.css"; 3 | 4 | export const metadata: Metadata = { 5 | title: "Technocrats TNP Cell Essay Writing", 6 | description: "Technocrats TNP Cell Essay Writing", 7 | icons: "/favicon.png", 8 | 9 | publisher: "Kunal Singh", 10 | authors: [{ name: "Kunal Singh", url: "https://kunalsin9h.com" }], 11 | colorScheme: "light", 12 | openGraph: { 13 | title: "TNP Cell Essay Writing", 14 | description: "Technocrats TNP Cell Essay Writing", 15 | url: "https://tnpcell.vercel.app", 16 | siteName: "Essay Practice", 17 | images: [ 18 | { url: "https://i.imgur.com/e3jFZNC.jpeg", width: 1200, height: 650 }, 19 | ], 20 | locale: "en-US", 21 | type: "website", 22 | }, 23 | twitter: { 24 | card: "summary_large_image", 25 | title: "TNP Cell Essay Writing", 26 | images: { 27 | url: "https://i.imgur.com/e3jFZNC.jpeg", 28 | }, 29 | } 30 | }; 31 | 32 | export default function RootLayout({ 33 | children, 34 | }: { 35 | children: React.ReactNode; 36 | }) { 37 | return ( 38 | 39 | {children} 40 | 41 | ); 42 | } 43 | -------------------------------------------------------------------------------- /src/app/page.tsx: -------------------------------------------------------------------------------- 1 | import "./dots.css"; 2 | import Test from "./test/page"; 3 | 4 | export default function Index() { 5 | return 6 | } 7 | -------------------------------------------------------------------------------- /src/app/test/page.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState, useEffect } from "react"; 4 | import { getWordCount } from "../utils/getWordCount"; 5 | import Timer from "../Timer"; 6 | 7 | export default function Test() { 8 | const [text, setText] = useState(""); 9 | 10 | const [word, setWord] = useState(0); 11 | const [backspace, setBackspace] = useState(0); 12 | const [deleteCount, setDeleteCount] = useState(0); 13 | 14 | const [spelling, setSpelling] = useState(false); 15 | 16 | const [fontSz, setFontSz] = useState(16); 17 | 18 | useEffect(() => { 19 | setText(localStorage.getItem("text") || "") 20 | 21 | function handleKeyDown(e: KeyboardEvent) { 22 | if (e.key === "Backspace") { 23 | setBackspace((b) => b + 1); 24 | } 25 | 26 | if (e.key === "Delete") { 27 | setDeleteCount((d) => d + 1); 28 | } 29 | } 30 | 31 | document.addEventListener("keydown", handleKeyDown); 32 | 33 | return () => { 34 | document.removeEventListener("keydown", handleKeyDown); 35 | }; 36 | }); 37 | 38 | return ( 39 |
40 |
41 |
42 |
43 | 51 | 52 | 61 |
62 | 63 |
64 |
65 |

66 | Backspace:{" "} 67 | {backspace} 68 |

69 |

70 | Delete:{" "} 71 | {deleteCount} 72 |

73 |

74 | Words: {word} 75 |

76 |
77 | 78 |
79 | 83 | 84 | 87 |
88 |
89 | 90 |