This commit is contained in:
louiscklaw
2025-01-31 21:26:01 +08:00
parent c9ec760f31
commit 7d30025aed
211 changed files with 144112 additions and 0 deletions

View File

@@ -0,0 +1,3 @@
# Basic Example
A simple [create-react-app](CRA-README.md) setup, showcasing one of the lastest React-Bootstrap components!

View File

@@ -0,0 +1,7 @@
#!/usr/bin/env bash
set -ex
yarn
yarn start

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,38 @@
{
"name": "code-sandbox-examples",
"version": "0.1.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^6.2.1",
"@fortawesome/free-regular-svg-icons": "^6.2.1",
"@fortawesome/free-solid-svg-icons": "^6.2.1",
"@fortawesome/react-fontawesome": "^0.2.0",
"bootstrap": "^5.1.3",
"fontawesome-react": "^2.0.0",
"react": "^17.0.2",
"react-bootstrap": "^2.0.0",
"react-dom": "^17.0.2",
"react-scripts": "4.0.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>React-Bootstrap CodeSandbox Starter</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
</body>
</html>

View File

@@ -0,0 +1,143 @@
.username-container{
padding-left: 2rem;
font-size: 2rem;
}
.list-group-container {
width:80%;
}
.viewnote-body{
width: 75%;
}
.input-container {
padding-top: 2rem;
}
.login-input-container{
padding-left: 1rem;
}
.button-container {
padding-left: 2rem
}
.icon-button-container{
display: flex;
flex-direction: row;
}
.icon-button-text{
padding-left: 0.5rem;
}
.viewnote-title {
display: flex;
flex-direction: row;
justify-content: flex-end;
}
.viewnote-container{
display: flex;
flex-direction: row;
justify-content: center;
}
.confirm-logout-container{
display: block;
position: fixed;
margin-top: 33vh;
}
.user-avatar {
width: 80px;
height: 80px;
background-size: contain;
background-repeat: no-repeat;
background-position: center;
}
.logout-button-container{
height: 100px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
padding-right: 2rem;
}
.note-container{
width: 80vw;
border-left: 2px solid black;
padding-top: 2rem;
}
.add-note-button-container{
position: fixed;
top: 80vh;
left: 90vw;
}
.left-nav-bar-notes-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.left-nav-bar-container {
width: 100vw;
display: flex;
flex-flow: row;
height: calc( 100vh - 200px );
}
.main-content {
}
.name-nav-bar {
}
.top-nav-bar {
height: 100px;
width: calc( 100vw - 0.001px );
border-bottom: 2px solid black ;
}
.home-background {
width: 100vw;
height: 100px;
display: flex;
justify-content: center;
align-items: center;
font-size: 2rem;
}
.home-container {
width:100vw;
height:100vh;
}
.login-background {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
}
.menu-input-field {
display: flex;
flex-direction: row;
align-items: baseline;
}
* {
box-sizing: border-box;
margin:0;
padding:0;
}

View File

@@ -0,0 +1,654 @@
import React, { useEffect, useState } from "react";
import Button from "react-bootstrap/Button";
import Container from "react-bootstrap/Container";
import Form from "react-bootstrap/Form";
import InputGroup from "react-bootstrap/InputGroup";
import ListGroup from "react-bootstrap/ListGroup";
import Modal from "react-bootstrap/Modal";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faUser, faPlus, faRemove, faSave, faSearch, faSignOut } from "@fortawesome/free-solid-svg-icons";
import CONSTANTS from "./constants";
import "./App.css";
function ConfirmLogout({ setOpenConfirmLogout, setLoginState, fetchNotes, setViewState }) {
const handleConfirmLogout = () => {
fetch(`//${CONSTANTS.LOGOUT_URL}`)
.then((res) => res.json())
.then((res_json) => {
setLoginState(CONSTANTS.NOT_LOGGED_IN);
setOpenConfirmLogout(false);
});
};
return (
<div className="modal show" style={{ display: "block", position: "fixed", marginTop: "33vh" }}>
<Modal.Dialog>
<Modal.Header closeButton>
<Modal.Title>Are you sure to quit editing the note and log out ? </Modal.Title>
</Modal.Header>
<Modal.Footer>
<Button variant="secondary" onClick={(e) => setOpenConfirmLogout(false)}>
Cancel
</Button>
<Button
variant="primary"
onClick={(e) => {
handleConfirmLogout(e);
}}
>
Logout
</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
);
}
function ConfirmCancelEdit({ setOpenConfirmCancelEdit, fetchNotes, setViewState }) {
return (
<div className="modal show" style={{ display: "block", position: "fixed", marginTop: "33vh" }}>
<Modal.Dialog>
<Modal.Header closeButton>
<Modal.Title>Are you sure to quit editing the note ? </Modal.Title>
</Modal.Header>
<Modal.Footer>
<Button variant="secondary" onClick={(e) => setOpenConfirmCancelEdit(false)}>
Close
</Button>
<Button
variant="primary"
onClick={(e) => {
setViewState(CONSTANTS.VIEW_STATE_VIEW_NOTE);
fetchNotes();
setOpenConfirmCancelEdit(false);
}}
>
cancel edit
</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
);
}
function ConfirmDeleteNote({ note_id, setOpenConfirmDeleteNote, fetchNotes, setViewState }) {
const handleDeleteClick = () => {
fetch(`//${CONSTANTS.DELETE_NOTE_ENDPOINT}/${note_id}`, {
method: "DELETE",
credentials: "include",
})
.then((res) => res.json())
.then((res_json) => {
fetchNotes();
setViewState(CONSTANTS.VIEW_STATE_EMPTY_NOTE);
setOpenConfirmDeleteNote(false);
});
};
return (
<div className="modal show" style={{ display: "block", position: "fixed", marginTop: "33vh" }}>
<Modal.Dialog>
<Modal.Header closeButton>
<Modal.Title>Are you sure to quit editing the note ? </Modal.Title>
</Modal.Header>
<Modal.Footer>
<Button variant="secondary" onClick={(e) => setOpenConfirmDeleteNote(false)}>
Close
</Button>
<Button variant="primary" onClick={(e) => handleDeleteClick(e)}>
Confirm delete
</Button>
</Modal.Footer>
</Modal.Dialog>
</div>
);
}
const ViewNote = ({ view_note_id, setViewState, setViewNoteId, first_note_id, fetchNotes }) => {
var [note_detail, setNoteDetail] = useState("");
var [iso_day_string, setIsoDayString] = useState("");
var [open_confirm_delete_note, setOpenConfirmDeleteNote] = useState(false);
const handleDeleteClick = () => {
setOpenConfirmDeleteNote(true);
};
useEffect(() => {
fetch(`//${CONSTANTS.GET_NOTE_ENDPOINT}/${view_note_id}`, { credentials: "include" })
.then((res) => res.json())
.then((res_json) => {
setNoteDetail(res_json[0]);
if (res_json[0]?.lastsavedtime && res_json[0]?.lastsavedtime != "") {
var d = new Date(res_json[0].lastsavedtime);
setIsoDayString(d.toISOString().split(".")[0].replace("T", " "));
} else {
setIsoDayString("");
}
});
}, [view_note_id]);
return (
<>
{open_confirm_delete_note ? (
<ConfirmDeleteNote
note_id={note_detail._id}
setViewState={setViewState}
fetchNotes={fetchNotes}
setOpenConfirmDeleteNote={setOpenConfirmDeleteNote}
/>
) : (
<></>
)}
<div class="viewnote-container">
<div class="viewnote-body">
<div style={{ display: "flex", flexDirection: "row", justifyContent: "space-between", alignItems: "center" }}>
<div>Last saved: {iso_day_string || ""}</div>
<div class="button-container">
<Button variant="primary" onClick={(e) => handleDeleteClick(e)}>
<div class="icon-button-container">
<div>
<FontAwesomeIcon icon={faSave} />
</div>
<div class="icon-button-text">Delete</div>
</div>
</Button>
</div>
</div>
<div class="input-container">
<Form.Control
type="text"
id="note-title"
aria-describedby="note-title"
value={note_detail?.title || ""}
onClick={(e) => {
setViewState(CONSTANTS.VIEW_STATE_EDIT_NOTE);
}}
style={{ cursor: "pointer" }}
/>
</div>
<div class="input-container">
<Form.Control
as="textarea"
rows={10}
value={note_detail?.content || ""}
onClick={(e) => {
setViewState(CONSTANTS.VIEW_STATE_EDIT_NOTE);
}}
style={{ cursor: "pointer" }}
/>
</div>
</div>
</div>
</>
);
};
// EXPLAIN: After one clicks on the “New note icon” (on any page view where it is shown),
// EXPLAIN: a new node creation panel shows in the right panel (Fig. 3).
// EXPLAIN: There is a node title input field and a note content input field, into which the user can enter texts.
// EXPLAIN: There is a “Cancel” button, clicking which a confirmation box
// EXPLAIN: “Are you sure to quit editing the note?” will be popped up:
// EXPLAIN: if the user confirms quitting, the page view goes back to the one shown in Fig. 2;
// EXPLAIN: otherwise, the current page view remains.
// EXPLAIN: There is a “Save” button, clicking which the newly created note is shown on the right panel,
// EXPLAIN: with the “Last saved” time and a “Delete” button displayed on top of the note,
// EXPLAIN: as shown in Fig. 4; besides, the note title should be listed in the left panel,
// EXPLAIN: as the first in the list (as it is the latest), the note title should be highlighted in a different color than the
// EXPLAIN: rest of the note titles in the list (since this notes content is shown in the right panel),
// EXPLAIN: and the total number of notes in ( ) on top of the list should be incremented.
const NewNote = ({ fetchNotes, setViewState }) => {
var [note_title, setNoteTitle] = useState("");
var [note_content, setNoteContent] = useState("");
var [open_confirm_cancel_edit, setOpenConfirmCancelEdit] = useState(false);
const handleSaveNoteClick = () => {
fetch(`//${CONSTANTS.ADD_NEW_NOTE_ENDPOINT}`, {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title: note_title, content: note_content }),
})
.then((res) => res.json())
.then((res_json) => {
fetchNotes();
setViewState(CONSTANTS.VIEW_STATE_EMPTY_NOTE);
});
};
return (
<>
{open_confirm_cancel_edit ? (
<ConfirmCancelEdit
setViewState={setViewState}
fetchNotes={fetchNotes}
setOpenConfirmCancelEdit={setOpenConfirmCancelEdit}
/>
) : (
<></>
)}
<div class="viewnote-container">
<div class="viewnote-body">
<div class="viewnote-title">
<div class="button-container">
<Button variant="primary" onClick={(e) => setOpenConfirmCancelEdit(true)}>
<div class="icon-button-container">
<div>
<FontAwesomeIcon icon={faRemove} />
</div>
<div class="icon-button-text">Cancel</div>
</div>
</Button>
</div>
<div class="button-container">
<Button variant="primary" onClick={(e) => handleSaveNoteClick(e)}>
<div class="icon-button-container">
<div>
<FontAwesomeIcon icon={faSave} />
</div>
<div class="icon-button-text">Save</div>
</div>
</Button>
</div>
</div>
<div class="input-container">
<Form.Label htmlFor="note-title">Note title</Form.Label>
<Form.Control
type="text"
id="new-note-title"
aria-describedby="note-title"
onChange={(e) => setNoteTitle(e.target.value)}
/>
</div>
<div class="input-container">
<div>
<Form.Label htmlFor="new-note-content">Note Content</Form.Label>
<Form.Control as="textarea" rows={10} onChange={(e) => setNoteContent(e.target.value)} />
</div>
</div>
</div>
</div>
</>
);
};
const EditNote = ({ view_note_id, fetchNotes, setViewState }) => {
var [note_title, setNoteTitle] = useState("");
var [note_content, setNoteContent] = useState("");
var [open_confirm_cancel_edit, setOpenConfirmCancelEdit] = useState(false);
var [note_detail, setNoteDetail] = useState("");
const handleSaveNoteClick = () => {
fetch(`//${CONSTANTS.SAVE_NOTE_ENDPOINT}/${view_note_id}`, {
method: "PUT",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ title: note_title, content: note_content }),
})
.then((res) => res.json())
.then((res_json) => {
fetchNotes();
setViewState(CONSTANTS.VIEW_STATE_EMPTY_NOTE);
});
};
useEffect(() => {
fetch(`//${CONSTANTS.GET_NOTE_ENDPOINT}/${view_note_id}`, {
credentials: "include",
})
.then((res) => res.json())
.then((res_json) => {
setNoteTitle(res_json[0]?.title);
setNoteContent(res_json[0]?.content);
});
}, [view_note_id]);
return (
<>
{open_confirm_cancel_edit ? (
<ConfirmCancelEdit
setViewState={setViewState}
fetchNotes={fetchNotes}
setOpenConfirmCancelEdit={setOpenConfirmCancelEdit}
/>
) : (
<></>
)}
<div class="viewnote-container">
<div class="viewnote-body">
<div class="viewnote-title">
<div class="button-container">
<Button variant="primary" onClick={(e) => setOpenConfirmCancelEdit(true)}>
<div class="icon-button-container">
<div>
<FontAwesomeIcon icon={faRemove} />
</div>
<div style={{ paddingLeft: "0.5rem" }}>Cancel</div>
</div>
</Button>
</div>
<div class="button-container">
<Button variant="primary" onClick={(e) => handleSaveNoteClick(e)}>
<div class="icon-button-container">
<div>
<FontAwesomeIcon icon={faSave} />
</div>
<div style={{ paddingLeft: "0.5rem" }}>Save</div>
</div>
</Button>
</div>
</div>
<div class="input-container">
<Form.Label htmlFor="note-title">Note title</Form.Label>
<Form.Control
type="text"
id="new-note-title"
aria-describedby="note-title"
value={note_title}
onChange={(e) => setNoteTitle(e.target.value)}
/>
</div>
<div class="input-container">
<div>
<Form.Label htmlFor="new-note-content">Note Content</Form.Label>
<Form.Control
as="textarea"
rows={10}
value={note_content}
onChange={(e) => setNoteContent(e.target.value)}
/>
</div>
</div>
</div>
</div>
</>
);
};
const AddNoteButton = ({ setViewNoteId, view_state, setViewState }) => {
if ([CONSTANTS.VIEW_STATE_EMPTY_NOTE, CONSTANTS.VIEW_STATE_VIEW_NOTE].includes(view_state))
return (
<button
type="button"
class="btn btn-primary btn-circle btn-lg"
onClick={(e) => {
setViewNoteId("");
setViewState(CONSTANTS.VIEW_STATE_ADD_NOTE);
}}
>
<FontAwesomeIcon icon={faPlus} />
</button>
);
return <></>;
};
const Home = ({ user_info, setUserInfo, setLoginState }) => {
var [note_list, setNoteList] = useState([]);
var [is_loading, setIsLoading] = useState(true);
var [search_note, setSearchNote] = useState("");
var [view_state, setViewState] = useState(CONSTANTS.VIEW_STATE_VIEW_NOTE);
var [view_note_id, setViewNoteId] = useState("");
var [first_note_id, setFirstNoteId] = useState("");
var [open_confirm_logout, setOpenConfirmLogout] = useState(false);
const handleLogoutClick = () => {
setOpenConfirmLogout(true);
};
const fetchNotes = () => {
fetch(`//${CONSTANTS.GET_NOTE_ENDPOINT}/*`, {
credentials: "include",
})
.then((res) => res.json())
.then((res_json) => {
setIsLoading(false);
setNoteList(res_json);
});
};
useEffect(() => {
setIsLoading(true);
fetch(`//${CONSTANTS.SEARCH_URL}/${search_note}`, {
credentials: "include",
})
.then((res) => res.json())
.then((res_json) => {
setIsLoading(false);
setNoteList(res_json);
});
}, [search_note]);
useEffect(() => {
setViewState(CONSTANTS.VIEW_STATE_EMPTY_NOTE);
fetchNotes();
}, []);
if (is_loading) return <>loading...</>;
const EmptyNote = () => {
return <></>;
};
const NoteContent = ({ view_state, view_note_id, setViewNoteId }) => {
if (view_state == CONSTANTS.VIEW_STATE_VIEW_NOTE) {
return (
<ViewNote
view_note_id={view_note_id}
setViewNoteId={setViewNoteId}
first_note_id={first_note_id}
fetchNotes={fetchNotes}
setViewState={setViewState}
/>
);
}
if (view_state == CONSTANTS.VIEW_STATE_ADD_NOTE)
return <NewNote setViewState={setViewState} fetchNotes={fetchNotes} />;
if (view_state == CONSTANTS.VIEW_STATE_EDIT_NOTE)
return <EditNote view_note_id={view_note_id} setViewState={setViewState} fetchNotes={fetchNotes} />;
return <EmptyNote />;
};
if (note_list == []) return <>loading notes</>;
return (
<>
{open_confirm_logout ? (
<ConfirmLogout setOpenConfirmLogout={setOpenConfirmLogout} setLoginState={setLoginState} />
) : (
<></>
)}
<div class="home-container">
<div class="home-background">iNotes</div>
<div class="top-nav-bar">
<div style={{ display: "flex", flexDirection: "row", justifyContent: "space-between" }}>
<div
style={{
display: "flex",
flexDirection: "row",
alignItems: "center",
paddingLeft: "2rem",
}}
>
<div
class="user-avatar"
style={{ backgroundImage: `url("http://${CONSTANTS.BACKEND_HOST}/${user_info.icon}")` }}
></div>
<div class="username-container">{user_info.name}</div>
</div>
<div class="logout-button-container">
<Button variant="primary" onClick={(e) => handleLogoutClick(e)}>
<div class="icon-button-container">
<div>
<FontAwesomeIcon icon={faSignOut} />
</div>
<div class="icon-button-text">log out</div>
</div>
</Button>
</div>
</div>
</div>
<div class="left-nav-bar-container">
<div style={{ width: "20vw", display: "flex", flexDirection: "column", paddingTop: "1rem" }}>
<div style={{ display: "flex", flexDirection: "row", justifyContent: "center", paddingTop: "2rem" }}>
<div style={{ width: "80%", display: "flex" }}>
<InputGroup className="mb-3">
<InputGroup.Text>
<FontAwesomeIcon icon={faSearch} />
</InputGroup.Text>
<Form.Control id="search-note" onChange={(e) => setSearchNote(e.target.value)} />
</InputGroup>
</div>
</div>
<div class="left-nav-bar-notes-container">
<div style={{ fontSize: "2rem" }}>Notes ({note_list.length})</div>
{note_list.length < 1 ? (
<>sorry but the list is empty</>
) : (
<>
<ListGroup class="list-group-container">
{note_list
.filter((n) => {
const re = new RegExp(search_note);
return n.title?.search(re) > -1;
})
.map((n, idx) => (
<ListGroup.Item
key={`list_${idx}`}
onClick={(e) => {
setViewNoteId(n._id);
setViewState(CONSTANTS.VIEW_STATE_VIEW_NOTE);
}}
style={{ backgroundColor: n._id == view_note_id ? "cyan" : "" }}
>
{n.title || "no title"}
</ListGroup.Item>
))}
</ListGroup>
</>
)}
</div>
</div>
<div class="note-container">
<NoteContent setViewNoteId={setViewNoteId} view_state={view_state} view_note_id={view_note_id} />
</div>
<div class="add-note-button-container">
<AddNoteButton setViewNoteId={setViewNoteId} view_state={view_state} setViewState={setViewState} />
</div>
</div>
</div>
</>
);
};
const Login = ({ login_state, setLoginState, setUserInfo }) => {
var [debug, setDebug] = useState();
var [username, setUsername] = useState("");
var [password, setPassword] = useState("");
const helloworld_alert = (username, password) => {
fetch("//localhost:3001/signin", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password }),
});
};
const handleSignIn = (username, password) => {
fetch(`//${CONSTANTS.SIGN_IN_URL}`, {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ username, password }),
})
.then((res) => res.json())
.then((res_json) => {
setDebug(JSON.stringify(res_json));
if (res_json.msg == CONSTANTS.MSG_LOGIN_SUCCESS) {
setLoginState(CONSTANTS.LOGGED_IN);
setUserInfo(res_json.user_meta);
}
});
};
return (
<Container>
<div>
<div class="login-background">
<div style={{ fontSize: "3rem" }}>iNotes</div>
<div style={{ paddingTop: "5rem" }}>
<Form>
<Form.Group className="mb-3">
<div class="menu-input-field">
<Form.Label>Username:</Form.Label>
<div class="login-input-container">
<Form.Control
type="text"
placeholder="username"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
</div>
</div>
</Form.Group>
<Form.Group className="mb-3">
<div class="menu-input-field">
<Form.Label>Password:</Form.Label>
<div class="login-input-container">
<Form.Control
type="password"
placeholder="password"
value={password}
onChange={(e) => {
setPassword(e.target.value);
}}
/>
</div>
</div>
</Form.Group>
</Form>
</div>
<div style={{ paddingTop: "5rem" }}>
<Button variant="primary" onClick={(e) => handleSignIn(username, password)}>
<div class="icon-button-container">
<div>
<FontAwesomeIcon icon={faUser} />
</div>
<div class="icon-button-text">Sign in</div>
</div>
</Button>
</div>
</div>
</div>
</Container>
);
};
const App = () => {
var [login_state, setLoginState] = useState(CONSTANTS.NOT_LOGGED_IN);
var [user_info, setUserInfo] = useState({});
if (login_state == CONSTANTS.NOT_LOGGED_IN) {
return <Login login_state={login_state} setLoginState={setLoginState} setUserInfo={setUserInfo} />;
}
return (
<div>
<Home user_info={user_info} setUserInfo={setUserInfo} setLoginState={setLoginState} />
</div>
);
};
export default App;

View File

@@ -0,0 +1,9 @@
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
it('renders without crashing', () => {
const div = document.createElement('div');
ReactDOM.render(<App />, div);
ReactDOM.unmountComponentAtNode(div);
});

BIN
james_endl/assignment/src/frontend/src/assets/notes.png (Stored with Git LFS) Normal file

Binary file not shown.

View File

@@ -0,0 +1,38 @@
const LOGGED_IN = "logged_in";
const NOT_LOGGED_IN = "not_logged_in";
const MSG_LOGIN_SUCCESS = "login success";
const BACKEND_HOST = "localhost:3001";
const VIEW_STATE_ADD_NOTE = "view_state_add_note";
const VIEW_STATE_VIEW_NOTE = "view_state_view_note";
const VIEW_STATE_EMPTY_NOTE = "view_state_empty_note";
const VIEW_STATE_EDIT_NOTE = "view_state_edit_note";
// ENDPOINTS
const ADD_NEW_NOTE_ENDPOINT = `${BACKEND_HOST}/addnote`;
const GET_NOTE_ENDPOINT = `${BACKEND_HOST}/getnote`;
const DELETE_NOTE_ENDPOINT = `${BACKEND_HOST}/deletenote`;
const SAVE_NOTE_ENDPOINT = `${BACKEND_HOST}/savenote`;
const LOGOUT_URL = `${BACKEND_HOST}/logout`;
const SIGN_IN_URL = `${BACKEND_HOST}/signin`;
const SEARCH_URL = `${BACKEND_HOST}/searchnotes`;
export default {
ADD_NEW_NOTE_ENDPOINT,
BACKEND_HOST,
LOGGED_IN,
MSG_LOGIN_SUCCESS,
NOT_LOGGED_IN,
VIEW_STATE_ADD_NOTE,
VIEW_STATE_EMPTY_NOTE,
VIEW_STATE_VIEW_NOTE,
VIEW_STATE_EDIT_NOTE,
GET_NOTE_ENDPOINT,
DELETE_NOTE_ENDPOINT,
SAVE_NOTE_ENDPOINT,
LOGOUT_URL,
SIGN_IN_URL,
SEARCH_URL,
};

View File

@@ -0,0 +1,8 @@
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
// Importing the Bootstrap CSS
import "bootstrap/dist/css/bootstrap.min.css";
ReactDOM.render(<App />, document.getElementById("root"));

View File

@@ -0,0 +1,4 @@
npm i -d
npm run start

File diff suppressed because it is too large Load Diff