Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion api/models.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
from django.db import models

# Create your models here.

class Folder(models.Model):
name = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)


class Note(models.Model):
body = models.TextField(null=True, blank=True)
updated = models.DateTimeField(auto_now=True)
created = models.DateTimeField(auto_now_add=True)
folder = models.ForeignKey(Folder, on_delete=models.CASCADE)

def __str__(self):
return self.body[0:69]
13 changes: 11 additions & 2 deletions api/serializers.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
from rest_framework.serializers import ModelSerializer
from .models import Note
from .models import Note, Folder


class FolderSerializer(ModelSerializer):
class Meta:
model = Folder
fields = ('id', 'name', 'created_at')


class NoteSerializer(ModelSerializer):
folder = FolderSerializer(read_only=True)

class Meta:
model = Note
fields = '__all__'
fields = '__all__'
6 changes: 5 additions & 1 deletion api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,8 @@
path('notes/<str:pk>/delete/', deleteNote, name="delete-note"),
path('notes/create/', createNote, name="create-note"),
path('notes/<str:pk>/', getNote, name="note"),
]
path('folders/', getFolders, name="folders"),
path('folders/create/', createFolder, name="create-folder"),
path('folders/<str:pk>/update/', updateFolder, name="update-folder"),
path('folders/<str:pk>/delete/', deleteFolder, name="delete-folder"),
]
77 changes: 0 additions & 77 deletions api/views.py
Original file line number Diff line number Diff line change
@@ -1,78 +1 @@
from django.shortcuts import render
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .serializers import NoteSerializer
from .models import Note

# Create your views here.

@api_view(['GET'])
def getRoutes(request):
routes = [
{
'Endpoint': '/notes/',
'method': 'GET',
'body': None,
'description': 'Returns an array of notes'
},
{
'Endpoint': '/notes/id',
'method': 'GET',
'body': None,
'description': 'Returns a single note object'
},
{
'Endpoint': '/notes/create/',
'method': 'POST',
'body': {'body': ""},
'description': 'Creates new note with data sent in post request'
},
{
'Endpoint': '/notes/id/update/',
'method': 'PUT',
'body': {'body': ""},
'description': 'Creates an existing note with data sent in post request'
},
{
'Endpoint': '/notes/id/delete/',
'method': 'DELETE',
'body': None,
'description': 'Deletes and exiting note'
},
]
return Response(routes)

@api_view(['GET'])
def getNotes(request):
notes = Note.objects.all().order_by('-created')
serializer = NoteSerializer(notes, many=True)
return Response(serializer.data)

@api_view(['GET'])
def getNote(request, pk):
note = Note.objects.get(id=pk)
serializer = NoteSerializer(note, many=False)
return Response(serializer.data)

@api_view(['PUT'])
def updateNote(request, pk):
note = Note.objects.get(id=pk)
serializer = NoteSerializer(instance=note, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)

@api_view(['DELETE'])
def deleteNote(request, pk):
note = Note.objects.get(id=pk)
note.delete()
return Response('Note was deleted!')

@api_view(['POST'])
def createNote(request):
data = request.data
note = Note.objects.create(
body=data['body']
)
serializer = NoteSerializer(note, many=False)
return Response(serializer.data)
24 changes: 17 additions & 7 deletions mynotes/src/App.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
import React, { useState } from 'react';
import {
HashRouter as Router,
Routes,
Route,
} from "react-router-dom";
} from 'react-router-dom';

import './App.css';
import Header from './components/header';
import Header from './components/Header';
import NotesListPage from './pages/NotesListPage';
import NotePage from './pages/NotePage';
import FolderList from './components/FolderList';

function App() {
const [folders, setFolders] = useState([]);

const addFolder = (folderName) => {
const newFolders = [...folders, folderName];
setFolders(newFolders);
};

return (
<Router>
<div className="container dark">
<div className="app">
<Header />
<Routes>
<Route path='/' element={ <NotesListPage/> } />
<Route path='/note/:id' element={ <NotePage/> } />
</Routes>
<Header />
<FolderList folders={folders} onAddFolder={addFolder} />
<Routes>
<Route path='/' element={<NotesListPage />} />
<Route path='/note/:id' element={<NotePage />} />
</Routes>
</div>
</div>
</Router>
Expand Down
5 changes: 3 additions & 2 deletions mynotes/src/components/ListItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@ let getContent = (note) => {
const ListItem = ({note}) => {
return (
<div className='notes-list-item'>
<Link to={`/note/${note.id}`}>
<Link to={`/note/${note.id}`}>
<h3>{getTitle(note)}</h3>
{note.folder && <h4>Folder: {note.folder}</h4>}
<p>{getContent(note)}</p>
<p>{getDate(note)}</p>
</Link>
</div>
)
}

export default ListItem
export default ListItem
82 changes: 1 addition & 81 deletions mynotes/src/pages/NotePage.js
Original file line number Diff line number Diff line change
@@ -1,81 +1 @@
import React, { useEffect, useState } from 'react'
import { useParams,useNavigate,Link } from 'react-router-dom'
// import notes from '../assets/data.js'
import { ReactComponent as ArrowLeft } from '../assets/arrow-left.svg'

const NotePage = () => {
let { id } = useParams();
let navigate = useNavigate()
let [note, setNote] = useState({})
useEffect(() => {
let getNote = async () => {
if (id === 'new') return
let response = await fetch(`/api/notes/${id}`)
let data = await response.json()
console.log(data)
setNote(data)
}
getNote()
}, [id])

let createNote = async () => {
await fetch(`/api/notes/create/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({...note, 'updated': new Date()})
})
}

let updateNote = async () => {
await fetch(`/api/notes/${id}/update/`, {
method: 'PUT',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({...note, 'updated': new Date()})
})
}

let deleteNote = async () => {
await fetch(`/api/notes/${id}/delete/`, {
method: 'DELETE'
})
navigate('/')
}

let handleSubmit = () => {
if (id !== 'new' && !note.body) {
deleteNote()
} else if (id !== 'new') {
updateNote()
} else if (id ==='new' && note !== null) {
createNote()
}
navigate('/')
}

return (
<div className='note'>
<div className="note-header">
<h3>
<Link to='/'>
<ArrowLeft onClick={handleSubmit} />
</Link>
</h3>
{id !== 'new' ? (
<button onClick={deleteNote}>Delete</button>
):(
<button onClick={handleSubmit}>Save</button>
)}
</div>
<div className="note-body">
<textarea onChange={(e) => {setNote({...note, 'body':e.target.value})}} value={note.body}>
</textarea>
</div>
</div>
)
}

export default NotePage
import React, { useEffect, useState } from 'react';
56 changes: 35 additions & 21 deletions mynotes/src/pages/NotesListPage.js
Original file line number Diff line number Diff line change
@@ -1,42 +1,56 @@
import React, { useState,useEffect } from 'react'
// import notes from '../assets/data.js'
import React, { useState, useEffect } from 'react'
import ListItem from '../components/ListItem.js'
import AddButton from '../components/AddButton.js'
import FolderList from '../components/FolderList.js' // Import the new FolderList component

const NotesListPage = () => {
let [notes, setNote] = useState([])
let [notes, setNotes] = useState([])
let [folders, setFolders] = useState([]) // Add state for folders

useEffect(() => {
getNotes()
}, []) // fires once when the component is mounted
getFolders() // Fetch folders when the component mounts
}, [])

let getNotes = async () => {
let response = await fetch('/api/notes/')
let data = await response.json()
console.log(data)
setNote(data)
setNotes(data)
}

let getFolders = async () => { // New function to fetch folders
let response = await fetch('/api/folders/')
let data = await response.json()
console.log(data)
setFolders(data)
}

return (
<div className='notes'>
<div className="notes-header">
<h2 className="notes-title">
&#9782; Notes
</h2>
<p className="notes-count">{notes.length}</p>
<div className='notes-page'>
<div className='folders-section'>
<FolderList folders={folders} />
</div>
<div className='notes-list'>
{notes.map((note,index) => {
return (
<div className='note-preview' key={index}>
<ListItem note={note}/>
</div>
)
})}
<div className='notes-section'>
<div className="notes-header">
<h2 className="notes-title">
&#9782; Notes
</h2>
<p className="notes-count">{notes.length}</p>
</div>
<div className='notes-list'>
{notes.map((note, index) => {
return (
<div className='note-preview' key={index}>
<ListItem note={note} />
</div>
)
})}
</div>
<AddButton />
</div>
<AddButton/>
</div>
)
}

export default NotesListPage
export default NotesListPage