Skip to content

Commit

Permalink
[#2PlaysAmonth] NoteHack (reactplay#983)
Browse files Browse the repository at this point in the history
* Complete Project added

* CSS file comments added

* Dark Mode added

* Update Readme.md

* Readme update

* Project Video added

* API URL, API KEY & API HOST Variables added

* Optimized cover image added

* .env variables added

* unique class name added

* NoteHack play added

* Stackstream link added
  • Loading branch information
Bobby-coder committed Feb 23, 2023
1 parent 5edf8e9 commit e2eb247
Show file tree
Hide file tree
Showing 12 changed files with 480 additions and 0 deletions.
46 changes: 46 additions & 0 deletions src/plays/notehack/Notehack.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import PlayHeader from 'common/playlists/PlayHeader';
import { useState, useEffect } from 'react';
import Header from './components/header/Header';
import AddNote from './components/addNote/AddNote';
import NoteList from './components/noteList/NoteList';
import './styles.css';

// WARNING: Do not change the entry componenet name
function Notehack(props) {
const [noteList, setNoteList] = useState(JSON.parse(localStorage.getItem('noteList')) || []);
const [theme, setTheme] = useState(JSON.parse(localStorage.getItem('theme')) || 'gradient-one');
const [note, setNote] = useState({});
// save notes to local storage logic
useEffect(() => localStorage.setItem('noteList', JSON.stringify(noteList)), [noteList]);
// save theme to local storage logic
useEffect(() => localStorage.setItem('theme', JSON.stringify(theme)), [theme]);

return (
<>
<div className="play-details">
<PlayHeader play={props} />
<div className="play-details-body notehack-play">
<div className={`notehack-container-wrapper ${theme}`}>
<div className="notehack-container">
<Header setTheme={setTheme} theme={theme} />
<AddNote
note={note}
noteList={noteList}
setNote={setNote}
setNoteList={setNoteList}
/>
<NoteList
note={note}
noteList={noteList}
setNote={setNote}
setNoteList={setNoteList}
/>
</div>
</div>
</div>
</div>
</>
);
}

export default Notehack;
44 changes: 44 additions & 0 deletions src/plays/notehack/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# NoteHack 🔥

### **NoteHack** is a fully functional note taking react app where a user can add, update & delete notes.

## Features

- ### **This app is fully responsive across all the devices 📱**
- ### **This app has multiple themes 💯**
- ### **User can add, update & delete the notes 🥳**
- ### **This app has localStorage feature. Notes & themes will be saved to local storage ⚡**

## Project Screenshot

- ### **Theme 1**

<div align="center">
<img src="https://i.postimg.cc/MpR2510f/SS1.png" alt="NoteHack Screenshot" width="100%" target="_blank" />
<br>
</div>

- ### **Theme 2**
<div align="center">
<img src="https://i.postimg.cc/k5cHYs2G/SS2.png" alt="NoteHack Screenshot" width="100%" target="_blank" />
<br>
</div>

## Play Demographic

- ### **Language: JavaScript**
- ### **Level: Intermediate**

## Creator Information

- ### **Bobby Sadhwani** - **[Linkedin](https://www.linkedin.com/in/bobby-sadhwani)**, **[Twitter](https://twitter.com/BOBBY__SADHWANI)**, **[Github](https://github.com/Bobby-coder)**, **[Portfolio](https://bobby-sadhwani.netlify.app)**

## Video

- ### **[stackstream](https://www.stack-stream.com/v/notehack-3)**

## Resources

- ### **[React Icons](https://react-icons.github.io/react-icons/)**

### **Happy Coding!** 🤩
38 changes: 38 additions & 0 deletions src/plays/notehack/components/addNote/AddNote.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.notehack-play .add-note-container {
padding: 20px 15px;
border-radius: 5px;
background-color: #ffffff;
margin: 20px auto;
box-shadow: var(--box-shadow);
}

.notehack-play .add-note-form {
display: flex;
gap: 7px;
}

.notehack-play .add-note-input {
flex-grow: 1;
padding: 5px 5px;
border: 1px solid #eaeaea;
border-radius: 5px;
font-size: 18px;
}

.notehack-play .add-note-input:focus {
outline: 0.5px solid #eaeaea;
}

.notehack-play .add-note-button {
background-color: #03ba5c;
color: #ffffff;
border: none;
padding: 5px 20px;
border-radius: 5px;
cursor: pointer;
font-size: 18px;
}

.notehack-play .add-note-button:hover {
background-color: #03b056;
}
59 changes: 59 additions & 0 deletions src/plays/notehack/components/addNote/AddNote.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import './AddNote.css';

const AddNote = ({ note, noteList, setNote, setNoteList }) => {
// Submit form logic
const handleSubmit = (e) => {
e.preventDefault();
if (e.target.note.value.trim() === '') {
/* Does nothing */
} else {
// edit note logic
if (note.id) {
let newDate = new Date();
let updatedNoteList = noteList.map((currEle) =>
currEle.id === note.id
? {
...note,
name: note.name,
date: `${newDate.toLocaleTimeString()} ${newDate.toLocaleDateString()}`
}
: currEle
);
setNoteList(updatedNoteList);
setNote({});
} else {
// add note logic
let newDate = new Date();
const newNote = {
name: e.target.note.value,
id: crypto.randomUUID(),
date: `${newDate.toLocaleTimeString()} ${newDate.toLocaleDateString()}`
};
setNoteList([...noteList, newNote]);
setNote({});
}
}
};

return (
<>
<div className="add-note-container">
<form className="add-note-form" onSubmit={handleSubmit}>
<input
className="add-note-input"
name="note"
placeholder="Add note"
type="text"
value={note.name || ''}
onChange={(e) => setNote({ ...note, name: e.target.value })}
/>
<button className="add-note-button" type="submit">
{note.id ? 'Update' : 'Add'}
</button>
</form>
</div>
</>
);
};

export default AddNote;
38 changes: 38 additions & 0 deletions src/plays/notehack/components/header/Header.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
.notehack-play .header-container {
min-height: 70px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 15px;
margin-bottom: 70px;
background-color: #ffffff;
border-radius: 5px;
box-shadow: var(--box-shadow);
}

.notehack-play .header-title h1 {
font-size: 22px;
margin-left: 7px;
cursor: pointer;
color: #525252;
}

.notehack-play .header-theme-selector {
display: flex;
align-items: center;
gap: 5px;
}

.notehack-play .header-theme-selector span {
height: 20px;
width: 20px;
border-radius: 50%;
display: inline-block;
cursor: pointer;
border: 1px solid #dfdfdf;
}

.notehack-play .header-theme-selector .active-theme {
height: 30px;
width: 30px;
}
43 changes: 43 additions & 0 deletions src/plays/notehack/components/header/Header.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import './Header.css';
const Header = ({ theme, setTheme }) => {
return (
<>
<header className="header-container">
<div className="header-title">
<h1>NoteHack</h1>
</div>

<div className="header-theme-selector">
<span
className={theme === 'gradient-one' ? 'gradient-one active-theme' : 'gradient-one'}
onClick={() => setTheme('gradient-one')}
/>
<span
className={theme === 'gradient-two' ? 'gradient-two active-theme' : 'gradient-two'}
onClick={() => setTheme('gradient-two')}
/>
<span
className={
theme === 'gradient-three' ? 'gradient-three active-theme' : 'gradient-three'
}
onClick={() => setTheme('gradient-three')}
/>
<span
className={theme === 'gradient-four' ? 'gradient-four active-theme' : 'gradient-four'}
onClick={() => setTheme('gradient-four')}
/>
<span
className={theme === 'gradient-five' ? 'gradient-five active-theme' : 'gradient-five'}
onClick={() => setTheme('gradient-five')}
/>
<span
className={theme === 'gradient-six' ? 'gradient-six active-theme' : 'gradient-six'}
onClick={() => setTheme('gradient-six')}
/>
</div>
</header>
</>
);
};

export default Header;
53 changes: 53 additions & 0 deletions src/plays/notehack/components/noteList/NoteList.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
.notehack-play .notelist-container {
padding: 20px 15px;
border-radius: 5px;
background-color: #ffffff;
margin: 20px auto;
box-shadow: var(--box-shadow);
}

.notehack-play .notelist-header {
padding: 10px 0px 20px 0px;
border-bottom: 1px solid #dfdfdf;
display: flex;
align-items: center;
justify-content: space-between;
}

.notehack-play .notelist-header .title {
font-size: 18px;
font-weight: 600;
user-select: none;
}

.notehack-play .notelist-header .count {
background-color: #dfdfdf;
color: #525252;
padding: 5px 10px;
border-radius: 50%;
margin-left: 10px;
user-select: none;
}

.notehack-play .notelist-header .clear-all button {
background-color: #0f6af3;
color: #ffffff;
padding: 5px 10px;
border-radius: 5px;
border: none;
cursor: pointer;
font-size: 16px;
}

.notehack-play .notelist-header .clear-all button:hover {
background-color: #1061db;
}

.notehack-play .notelist-section {
margin: 30px 5px 20px 5px;
display: flex;
flex-direction: row;
justify-content: space-around;
flex-wrap: wrap;
gap: 15px;
}
41 changes: 41 additions & 0 deletions src/plays/notehack/components/noteList/NoteList.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import SingleNote from '../singleNote/SingleNote';
import './NoteList.css';

const NoteList = ({ note, noteList, setNote, setNoteList }) => {
// Clear All notes logic
const handleClear = () => {
setNoteList([]);
};

return (
<>
<div className="notelist-container">
<div className="notelist-header">
<div>
<span className="title">Notes</span>
<span className="count">{noteList.length}</span>
</div>
<div className="clear-all">
<button onClick={handleClear}>Clear All</button>
</div>
</div>
<div className="notelist-section">
{noteList.map(({ name, id, date }) => (
<SingleNote
date={date}
id={id}
key={id}
name={name}
note={note}
noteList={noteList}
setNote={setNote}
setNoteList={setNoteList}
/>
))}
</div>
</div>
</>
);
};

export default NoteList;
Loading

0 comments on commit e2eb247

Please sign in to comment.