├── .gitignore ├── README.md ├── package-lock.json ├── package.json ├── public ├── assets │ └── favicon.png ├── index.html ├── style.css └── tooltips.js ├── screenshots └── 1.PNG └── src ├── app.jsx ├── components ├── footer.jsx ├── header.jsx ├── minors │ └── card.jsx ├── newNote.jsx └── note.jsx ├── index.js └── notes.js /.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 | 25 | .now -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![HitCount](http://hits.dwyl.com/ishandeveloper/Notes-Keeper.svg)](http://hits.dwyl.com/ishandeveloper/Notes-Keeper) 2 | 3 | 4 | 5 | # NOTES KEEPER 6 | 7 | 8 | This is a Google Keep inspired, Notes keeping app. The best part? All the notes you save are kept locally on your computer! using your browser's LocalStorage. 9 | 10 | So, no more worrying about giving access to your secrets to 3rd-party companies. 11 | 12 | Built in React.js with ❤️ 13 | 14 | 15 | #### View Live Demo 16 |
keep.ishandeveloper.com
17 | 18 | ## Setup 19 | 20 | ##### Clone the repository 21 | ```bash 22 | git clone https://github.com/ishandeveloper/Notes-Keeper.git 23 | ``` 24 | ##### Move to the desired folder 25 | ```bash 26 | cd \Notes-Keeper 27 | ``` 28 | ##### To install the dependencies, simply write 29 | ```bash 30 | npm install 31 | ``` 32 | 33 | ##### To run the app, simply write 34 | ```bash 35 | npm start 36 | ``` 37 | 38 | ## Learn More 39 | 40 | You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). 41 | 42 | ##### Made with ♥ by ishandeveloper 43 | 44 | [![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://github.com/ishandeveloper) 45 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "keeper", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^4.2.4", 7 | "@testing-library/react": "^10.3.0", 8 | "@testing-library/user-event": "^10.4.0", 9 | "local-storage": "^2.0.0", 10 | "materialize-css": "^1.0.0-rc.2", 11 | "react": "^16.13.1", 12 | "react-dom": "^16.13.1", 13 | "react-scripts": "3.4.1" 14 | }, 15 | "scripts": { 16 | "start": "react-scripts start", 17 | "build": "react-scripts build", 18 | "test": "react-scripts test", 19 | "eject": "react-scripts eject" 20 | }, 21 | "eslintConfig": { 22 | "extends": "react-app" 23 | }, 24 | "browserslist": { 25 | "production": [ 26 | ">0.2%", 27 | "not dead", 28 | "not op_mini all" 29 | ], 30 | "development": [ 31 | "last 1 chrome version", 32 | "last 1 firefox version", 33 | "last 1 safari version" 34 | ] 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /public/assets/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishandeveloper/Notes-Keeper/32b020ecf07e21127e866e40d8f08336daa72f07/public/assets/favicon.png -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | NotesKeeper 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /public/style.css: -------------------------------------------------------------------------------- 1 | @import url('https://fonts.googleapis.com/css?family=Poppins&display=swap'); 2 | 3 | .logo { 4 | padding: 0px 20px !important; 5 | } 6 | 7 | .hero-text { 8 | font-size: 0.8em; 9 | } 10 | 11 | .input-field { 12 | width: 70%; 13 | height: 50px !important; 14 | padding: 0px !important; 15 | position: absolute; 16 | /* margin-left:15%!important; */ 17 | margin: 10px 18% !important; 18 | background: #f1f3f4; 19 | } 20 | 21 | input[type=note] { 22 | background-color: transparent; 23 | border: none; 24 | border-radius: 0; 25 | outline: none; 26 | height: 3rem; 27 | width: 100%; 28 | font-size: 1.5em; 29 | margin: 0 0 8px 0; 30 | padding: 0; 31 | border-bottom: 0px !important; 32 | } 33 | 34 | .text-justify { 35 | text-align: justify; 36 | } 37 | 38 | .search-icon { 39 | height: 100%; 40 | font-size: 2em !important; 41 | } 42 | 43 | .close-icon { 44 | height: 100%; 45 | margin-top: -5px !important; 46 | font-size: 1.5em !important; 47 | } 48 | 49 | .label-icon { 50 | margin-top: -5px !important; 51 | } 52 | 53 | .row { 54 | width: 90%; 55 | padding: 20px 10px; 56 | min-height: calc(90vh - 74px); 57 | } 58 | 59 | .newnote { 60 | height: auto !important; 61 | margin-left: auto; 62 | margin-right: auto; 63 | margin-top: 50px; 64 | margin-bottom: 50px; 65 | width: 50%; 66 | } 67 | 68 | .materialize-textarea { 69 | font-size: 1.2em !important; 70 | border-bottom: 0px !important; 71 | transition: none !important; 72 | box-shadow: none !important; 73 | } 74 | 75 | .hero-icon { 76 | font-size: 1.25em; 77 | } 78 | 79 | nav { 80 | font-family: 'Poppins'; 81 | min-height: 70px; 82 | } 83 | 84 | nav .brand-logo i, 85 | nav .brand-logo [class^="mdi-"], 86 | nav .brand-logo [class*="mdi-"], 87 | nav .brand-logo i.material-icons { 88 | font-size: 1.25em; 89 | } 90 | 91 | .card { 92 | transition: all 1s !important; 93 | } 94 | 95 | .card-content { 96 | transition: all 1s !important; 97 | } 98 | 99 | .input-title { 100 | 101 | transition: all ease-in-out 1s !important; 102 | 103 | } 104 | 105 | .page-footer { 106 | position: relative; 107 | bottom: 0; 108 | width: 100%; 109 | } 110 | 111 | /* CUSTOM SCROLLBAR */ 112 | 113 | ::-webkit-scrollbar { 114 | width: 5px; 115 | } 116 | 117 | /* Track */ 118 | ::-webkit-scrollbar-track { 119 | background: white; 120 | 121 | } 122 | 123 | /* Handle */ 124 | ::-webkit-scrollbar-thumb { 125 | background: #2196F3; 126 | border-radius: 50px; 127 | 128 | } 129 | 130 | /* Handle on hover */ 131 | ::-webkit-scrollbar-thumb:hover { 132 | background: #64B5F6; 133 | 134 | } 135 | 136 | 137 | @media only screen and (max-width: 768px) { 138 | .newnote { 139 | width: 80%; 140 | } 141 | 142 | .m3 { 143 | width: 50% !important; 144 | min-width: 50% !important; 145 | } 146 | } 147 | 148 | @media only screen and (max-width: 1072px) { 149 | 150 | .m3 { 151 | min-width: 33.333333% !important; 152 | } 153 | } 154 | 155 | @media only screen and (max-width: 600px) { 156 | .newnote { 157 | width: 80%; 158 | } 159 | 160 | .m3 { 161 | width: 100% !important; 162 | min-width: 100% !important; 163 | } 164 | } -------------------------------------------------------------------------------- /public/tooltips.js: -------------------------------------------------------------------------------- 1 | M.AutoInit(); -------------------------------------------------------------------------------- /screenshots/1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ishandeveloper/Notes-Keeper/32b020ecf07e21127e866e40d8f08336daa72f07/screenshots/1.PNG -------------------------------------------------------------------------------- /src/app.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import Header from "./components/header"; 3 | import createCard from "./components/minors/card"; 4 | import Footer from "./components/footer"; 5 | import NewNote from "./components/newNote"; 6 | var ls = require("local-storage"); 7 | 8 | function App() { 9 | const storedNotes = JSON.parse(ls.get("notes")); 10 | const nullNote = { 11 | id: 9999999, 12 | title: "NULL", 13 | note: "NULL", 14 | }; 15 | // console.log(storedNotes); 16 | const [notes, setnotes] = React.useState(() => { 17 | if (storedNotes != null) { 18 | return [ 19 | storedNotes[0] ? storedNotes[0] : nullNote, 20 | storedNotes[2] ? storedNotes[2] : nullNote, 21 | storedNotes[1] ? storedNotes[1] : nullNote, 22 | storedNotes[3] ? storedNotes[3] : nullNote, 23 | storedNotes[4] ? storedNotes[4] : nullNote, 24 | storedNotes[5] ? storedNotes[5] : nullNote, 25 | storedNotes[6] ? storedNotes[6] : nullNote, 26 | storedNotes[7] ? storedNotes[7] : nullNote, 27 | ]; 28 | } 29 | return [ 30 | { 31 | id: 0, 32 | title: "Hey, I'm a note!", 33 | note: 34 | "Click the delete icon below to delete me and start making your own notes ;)", 35 | }, 36 | ]; 37 | }); 38 | 39 | function saveNotestoLocal(oldNotes, id) { 40 | if (notes !== oldNotes) { 41 | const savedNotes = notes.filter((note) => { 42 | return note.id !== 9999999; 43 | }); 44 | ls("notes", JSON.stringify(savedNotes)); 45 | console.log("Notes Saved"); 46 | } else { 47 | console.log(id); 48 | setnotes((prevNotes) => { 49 | oldNotes = prevNotes; 50 | return prevNotes.filter((note) => note.id !== id); 51 | }); 52 | setTimeout(() => { 53 | saveNotestoLocal(oldNotes, id); 54 | }, 1000); 55 | } 56 | } 57 | 58 | function addNote(title, content) { 59 | const newId = Math.round(Math.random() * 100); 60 | setnotes((prev) => { 61 | return [ 62 | ...prev, 63 | { 64 | id: newId, 65 | title: title, 66 | note: content, 67 | }, 68 | ]; 69 | }); 70 | setTimeout(saveNotestoLocal, 1000); 71 | } 72 | function deleteNote(id) { 73 | var oldnotes; 74 | setnotes((prevNotes) => { 75 | oldnotes = prevNotes; 76 | return prevNotes.filter((note) => note.id !== id); 77 | }); 78 | saveNotestoLocal(oldnotes, id); 79 | } 80 | return ( 81 |
82 |
83 | 84 |
85 | {notes.map((note) => createCard(note, deleteNote))} 86 |
87 |
89 | ); 90 | } 91 | 92 | export default App; 93 | -------------------------------------------------------------------------------- /src/components/footer.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | // const year=new Date().getFullYear(); 4 | 5 | function Footer() { 6 | return ( 7 |
8 | 17 |
18 | ); 19 | } 20 | 21 | export default Footer; 22 | -------------------------------------------------------------------------------- /src/components/header.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function Heading() { 4 | return ( 5 |
6 |
7 | 39 |
40 |
41 | ); 42 | } 43 | 44 | export default Heading; 45 | -------------------------------------------------------------------------------- /src/components/minors/card.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | function createCard(content, deletenote) { 4 | if (content.note !== "NULL") { 5 | return ( 6 | 13 | ); 14 | } 15 | } 16 | 17 | function Card(props) { 18 | function copyToClipboard() { 19 | navigator.clipboard.writeText(props.content); 20 | } 21 | function taskDelete() { 22 | props.del(props.id); 23 | } 24 | return ( 25 |
26 |
27 |
28 |
29 | {props.title} 30 |

{props.content}

31 |
32 |
33 | 42 | 48 | delete 49 | 50 | 57 | file_copy 58 | 59 | 60 |
61 |
62 |
63 |
64 | ); 65 | } 66 | 67 | export default createCard; 68 | -------------------------------------------------------------------------------- /src/components/newNote.jsx: -------------------------------------------------------------------------------- 1 | import React, {useState} from "react"; 2 | 3 | function NewNote(props) { 4 | 5 | const [typing, settyping] = useState(false); 6 | 7 | const [textareaStyle, settextareaStyle] = React.useState({ 8 | textAlign: "justfiy", 9 | }); 10 | const [content, setcontent] = useState('') 11 | const [title, settitle] = useState(''); 12 | 13 | function newnoteadded() { 14 | {props.add(title,content)}; 15 | settitle(''); 16 | setcontent(''); 17 | } 18 | 19 | function textareaHeight(e) { 20 | settextareaStyle({ 21 | height: e.target.scrollHeight + "px", 22 | textAlign: "justfiy", 23 | maxHeight: "500px", 24 | }); 25 | } 26 | function titlechanged(e) { 27 | settitle(e.target.value); 28 | } 29 | function contentchanged(e) { 30 | settyping(true); 31 | setcontent(e.target.value); 32 | } 33 | return ( 34 |
35 |
36 |
37 |
38 | 39 |
40 |
41 | {typing?
42 | 43 |
:null} 44 |

45 | 55 |

56 |
57 | {typing? 58 | add 59 | :null} 60 |
61 |
62 |
63 | ); 64 | } 65 | 66 | export default NewNote; 67 | -------------------------------------------------------------------------------- /src/components/note.jsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import createCard from "./minors/card"; 3 | import notes from "../notes"; 4 | 5 | function Notes() { 6 | return
{notes.map(createCard)}
; 7 | } 8 | 9 | export default Notes; 10 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom"; 3 | import App from "./app"; 4 | 5 | ReactDOM.render(, document.getElementById("root")); 6 | -------------------------------------------------------------------------------- /src/notes.js: -------------------------------------------------------------------------------- 1 | const notes = [ 2 | { 3 | id: 0, 4 | title: "First Note", 5 | note: 6 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi elementum dictum tincidunt. Nullam in convallis lectus. Donec vestibulum sagittis lectus, sit amet posuere odio pharetra ac. Nullam pulvinar orci vel aliquet malesuada. Nulla maximus, lorem non rutrum viverra, mauris mi interdum neque, id commodo dui ante sit amet nisi. ", 7 | }, 8 | { 9 | id: 0, 10 | title: "First Note", 11 | note: 12 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi elementum dictum tincidunt. Nullam in convallis lectus. Donec vestibulum sagittis lectus, sit amet posuere odio pharetra ac. Nullam pulvinar orci vel aliquet malesuada. Nulla maximus, lorem non rutrum viverra, mauris mi interdum neque, id commodo dui ante sit amet nisi. ", 13 | }, 14 | { 15 | id: 0, 16 | title: "First Note", 17 | note: 18 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Morbi elementum dictum tincidunt. Nullam in convallis lectus. Donec vestibulum sagittis lectus, sit amet posuere odio pharetra ac. Nullam pulvinar orci vel aliquet malesuada. Nulla maximus, lorem non rutrum viverra, mauris mi interdum neque, id commodo dui ante sit amet nisi. ", 19 | }, 20 | ]; 21 | 22 | export default notes; 23 | --------------------------------------------------------------------------------