├── .gitignore ├── README.md ├── package.json ├── public └── index.html ├── src ├── App.css ├── App.js ├── Components │ ├── Note │ │ ├── Note.css │ │ └── Note.js │ ├── NoteContainer │ │ ├── NoteContainer.css │ │ └── NoteContainer.js │ └── Sidebar │ │ ├── Sidebar.css │ │ └── Sidebar.js ├── assets │ ├── delete.png │ ├── delete.svg │ └── plus.png ├── index.css └── index.js └── yarn.lock /.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 | # Notes App in React.js 2 | 3 | ![Screenshot (421)](https://user-images.githubusercontent.com/89729177/132137360-3515b331-6d30-48ea-9959-3b5815e66593.png) 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "notes-app", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@testing-library/jest-dom": "^5.11.4", 7 | "@testing-library/react": "^11.1.0", 8 | "@testing-library/user-event": "^12.1.10", 9 | "react": "^17.0.2", 10 | "react-dom": "^17.0.2", 11 | "react-scripts": "4.0.3", 12 | "web-vitals": "^1.0.1" 13 | }, 14 | "scripts": { 15 | "start": "react-scripts start", 16 | "build": "react-scripts build", 17 | "test": "react-scripts test", 18 | "eject": "react-scripts eject" 19 | }, 20 | "eslintConfig": { 21 | "extends": [ 22 | "react-app", 23 | "react-app/jest" 24 | ] 25 | }, 26 | "browserslist": { 27 | "production": [ 28 | ">0.2%", 29 | "not dead", 30 | "not op_mini all" 31 | ], 32 | "development": [ 33 | "last 1 chrome version", 34 | "last 1 firefox version", 35 | "last 1 safari version" 36 | ] 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | Notes App 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | .App { 2 | height: 100vh; 3 | display: flex; 4 | gap: 20px; 5 | padding: 40px; 6 | } 7 | 8 | .custom-scroll::-webkit-scrollbar { 9 | width: 8px; 10 | } 11 | .custom-scroll::-webkit-scrollbar-track { 12 | background-color: transparent; 13 | } 14 | 15 | .custom-scroll::-webkit-scrollbar-thumb { 16 | border-radius: 20px; 17 | background-color: lightgray; 18 | transition: 300ms; 19 | } 20 | 21 | .custom-scroll::-webkit-scrollbar-thumb:hover { 22 | background-color: gray; 23 | } 24 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import React, { useEffect, useState } from "react"; 2 | 3 | import NoteContainer from "./Components/NoteContainer/NoteContainer"; 4 | import Sidebar from "./Components/Sidebar/Sidebar"; 5 | 6 | import "./App.css"; 7 | 8 | function App() { 9 | const [notes, setNotes] = useState( 10 | JSON.parse(localStorage.getItem("notes-app")) || [] 11 | ); 12 | 13 | const addNote = (color) => { 14 | const tempNotes = [...notes]; 15 | 16 | tempNotes.push({ 17 | id: Date.now() + "" + Math.floor(Math.random() * 78), 18 | text: "", 19 | time: Date.now(), 20 | color, 21 | }); 22 | setNotes(tempNotes); 23 | }; 24 | 25 | const deleteNote = (id) => { 26 | const tempNotes = [...notes]; 27 | 28 | const index = tempNotes.findIndex((item) => item.id === id); 29 | if (index < 0) return; 30 | 31 | tempNotes.splice(index, 1); 32 | setNotes(tempNotes); 33 | }; 34 | 35 | const updateText = (text, id) => { 36 | const tempNotes = [...notes]; 37 | 38 | const index = tempNotes.findIndex((item) => item.id === id); 39 | if (index < 0) return; 40 | 41 | tempNotes[index].text = text; 42 | setNotes(tempNotes); 43 | }; 44 | 45 | useEffect(() => { 46 | localStorage.setItem("notes-app", JSON.stringify(notes)); 47 | }, [notes]); 48 | 49 | return ( 50 |
51 | 52 | 57 |
58 | ); 59 | } 60 | 61 | export default App; 62 | -------------------------------------------------------------------------------- /src/Components/Note/Note.css: -------------------------------------------------------------------------------- 1 | .note { 2 | padding: 25px; 3 | height: 280px; 4 | width: 260px; 5 | display: flex; 6 | flex-direction: column; 7 | background-color: blueviolet; 8 | border-radius: 30px; 9 | } 10 | 11 | .note_text { 12 | flex: 1; 13 | resize: none; 14 | background-color: transparent; 15 | font-size: 1rem; 16 | line-height: 1.875rem; 17 | outline: none; 18 | border: none; 19 | } 20 | 21 | .note_footer { 22 | display: flex; 23 | justify-content: space-between; 24 | align-items: center; 25 | } 26 | 27 | .note_footer img { 28 | cursor: pointer; 29 | opacity: 0; 30 | transition: 300ms; 31 | } 32 | 33 | .note:hover .note_footer img { 34 | opacity: 1; 35 | } 36 | -------------------------------------------------------------------------------- /src/Components/Note/Note.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | 3 | import deleteIcon from "../../assets/delete.svg"; 4 | 5 | import "./Note.css"; 6 | 7 | let timer = 500, 8 | timeout; 9 | function Note(props) { 10 | const formatDate = (value) => { 11 | if (!value) return ""; 12 | 13 | const date = new Date(value); 14 | const monthNames = [ 15 | "Jan", 16 | "Feb", 17 | "March", 18 | "April", 19 | "May", 20 | "Jun", 21 | "Jul", 22 | "Aug", 23 | "Sept", 24 | "Oct", 25 | "Nov", 26 | "Dec", 27 | ]; 28 | 29 | let hrs = date.getHours(); 30 | let amPm = hrs >= 12 ? "PM" : "AM"; 31 | hrs = hrs ? hrs : "12"; 32 | hrs = hrs > 12 ? (hrs = 24 - hrs) : hrs; 33 | 34 | let min = date.getMinutes(); 35 | min = min < 10 ? "0" + min : min; 36 | 37 | let day = date.getDate(); 38 | const month = monthNames[date.getMonth()]; 39 | 40 | return `${hrs}:${min} ${amPm} ${day} ${month}`; 41 | }; 42 | 43 | const debounce = (func) => { 44 | clearTimeout(timeout); 45 | timeout = setTimeout(func, timer); 46 | }; 47 | 48 | const updateText = (text, id) => { 49 | debounce(() => props.updateText(text, id)); 50 | }; 51 | 52 | return ( 53 |
54 |