This commit is contained in:
QkoSad
2023-08-08 16:02:54 +03:00
commit 0a7a469d56
315 changed files with 426907 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
node_modules
+1
View File
@@ -0,0 +1 @@
missing 2.19,2.20
+29913
View File
File diff suppressed because it is too large Load Diff
+39
View File
@@ -0,0 +1,39 @@
{
"name": "coutry-app",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

+43
View File
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

+25
View File
@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
+3
View File
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
+38
View File
@@ -0,0 +1,38 @@
.App {
text-align: center;
}
.App-logo {
height: 40vmin;
pointer-events: none;
}
@media (prefers-reduced-motion: no-preference) {
.App-logo {
animation: App-logo-spin infinite 20s linear;
}
}
.App-header {
background-color: #282c34;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
font-size: calc(10px + 2vmin);
color: white;
}
.App-link {
color: #61dafb;
}
@keyframes App-logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
+42
View File
@@ -0,0 +1,42 @@
import axios from "axios";
import { useState } from "react";
function App() {
const [countries, setCountries] = useState([]);
const [filter, setFilter] = useState("");
useState(() => {
axios
.get("https://studies.cs.helsinki.fi/restcountries/api/all")
.then((response) => setCountries(response.data))
.catch((err) => console.log(err));
}, []);
const countriesDisplay = countries.filter((el, index) =>
el.name.common.toLowerCase().includes(filter.toLowerCase())
);
return (
<>
<div>Find Countries</div>
<input value={filter} onChange={(e) => setFilter(e.target.value)} />
<ul>
{countriesDisplay.length > 10 ? (
"too many countries"
) : countriesDisplay.length > 1 ? (
countriesDisplay.map((el, index) => (
<li key={index}>{el.name.common}</li>
))
) : countriesDisplay.length === 1 ? (
<>
<li key={2}>
<h3>{countriesDisplay[0]?.name.official}</h3>
</li>
<li key={1}>catial{countriesDisplay[0]?.capital[0]}</li>
<li key={2}>languages</li>
</>
) : null}
</ul>
</>
);
}
export default App;
+8
View File
@@ -0,0 +1,8 @@
import { render, screen } from '@testing-library/react';
import App from './App';
test('renders learn react link', () => {
render(<App />);
const linkElement = screen.getByText(/learn react/i);
expect(linkElement).toBeInTheDocument();
});
+13
View File
@@ -0,0 +1,13 @@
body {
margin: 0;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
code {
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
monospace;
}
+17
View File
@@ -0,0 +1,17 @@
import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
+1
View File
@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 841.9 595.3"><g fill="#61DAFB"><path d="M666.3 296.5c0-32.5-40.7-63.3-103.1-82.4 14.4-63.6 8-114.2-20.2-130.4-6.5-3.8-14.1-5.6-22.4-5.6v22.3c4.6 0 8.3.9 11.4 2.6 13.6 7.8 19.5 37.5 14.9 75.7-1.1 9.4-2.9 19.3-5.1 29.4-19.6-4.8-41-8.5-63.5-10.9-13.5-18.5-27.5-35.3-41.6-50 32.6-30.3 63.2-46.9 84-46.9V78c-27.5 0-63.5 19.6-99.9 53.6-36.4-33.8-72.4-53.2-99.9-53.2v22.3c20.7 0 51.4 16.5 84 46.6-14 14.7-28 31.4-41.3 49.9-22.6 2.4-44 6.1-63.6 11-2.3-10-4-19.7-5.2-29-4.7-38.2 1.1-67.9 14.6-75.8 3-1.8 6.9-2.6 11.5-2.6V78.5c-8.4 0-16 1.8-22.6 5.6-28.1 16.2-34.4 66.7-19.9 130.1-62.2 19.2-102.7 49.9-102.7 82.3 0 32.5 40.7 63.3 103.1 82.4-14.4 63.6-8 114.2 20.2 130.4 6.5 3.8 14.1 5.6 22.5 5.6 27.5 0 63.5-19.6 99.9-53.6 36.4 33.8 72.4 53.2 99.9 53.2 8.4 0 16-1.8 22.6-5.6 28.1-16.2 34.4-66.7 19.9-130.1 62-19.1 102.5-49.9 102.5-82.3zm-130.2-66.7c-3.7 12.9-8.3 26.2-13.5 39.5-4.1-8-8.4-16-13.1-24-4.6-8-9.5-15.8-14.4-23.4 14.2 2.1 27.9 4.7 41 7.9zm-45.8 106.5c-7.8 13.5-15.8 26.3-24.1 38.2-14.9 1.3-30 2-45.2 2-15.1 0-30.2-.7-45-1.9-8.3-11.9-16.4-24.6-24.2-38-7.6-13.1-14.5-26.4-20.8-39.8 6.2-13.4 13.2-26.8 20.7-39.9 7.8-13.5 15.8-26.3 24.1-38.2 14.9-1.3 30-2 45.2-2 15.1 0 30.2.7 45 1.9 8.3 11.9 16.4 24.6 24.2 38 7.6 13.1 14.5 26.4 20.8 39.8-6.3 13.4-13.2 26.8-20.7 39.9zm32.3-13c5.4 13.4 10 26.8 13.8 39.8-13.1 3.2-26.9 5.9-41.2 8 4.9-7.7 9.8-15.6 14.4-23.7 4.6-8 8.9-16.1 13-24.1zM421.2 430c-9.3-9.6-18.6-20.3-27.8-32 9 .4 18.2.7 27.5.7 9.4 0 18.7-.2 27.8-.7-9 11.7-18.3 22.4-27.5 32zm-74.4-58.9c-14.2-2.1-27.9-4.7-41-7.9 3.7-12.9 8.3-26.2 13.5-39.5 4.1 8 8.4 16 13.1 24 4.7 8 9.5 15.8 14.4 23.4zM420.7 163c9.3 9.6 18.6 20.3 27.8 32-9-.4-18.2-.7-27.5-.7-9.4 0-18.7.2-27.8.7 9-11.7 18.3-22.4 27.5-32zm-74 58.9c-4.9 7.7-9.8 15.6-14.4 23.7-4.6 8-8.9 16-13 24-5.4-13.4-10-26.8-13.8-39.8 13.1-3.1 26.9-5.8 41.2-7.9zm-90.5 125.2c-35.4-15.1-58.3-34.9-58.3-50.6 0-15.7 22.9-35.6 58.3-50.6 8.6-3.7 18-7 27.7-10.1 5.7 19.6 13.2 40 22.5 60.9-9.2 20.8-16.6 41.1-22.2 60.6-9.9-3.1-19.3-6.5-28-10.2zM310 490c-13.6-7.8-19.5-37.5-14.9-75.7 1.1-9.4 2.9-19.3 5.1-29.4 19.6 4.8 41 8.5 63.5 10.9 13.5 18.5 27.5 35.3 41.6 50-32.6 30.3-63.2 46.9-84 46.9-4.5-.1-8.3-1-11.3-2.7zm237.2-76.2c4.7 38.2-1.1 67.9-14.6 75.8-3 1.8-6.9 2.6-11.5 2.6-20.7 0-51.4-16.5-84-46.6 14-14.7 28-31.4 41.3-49.9 22.6-2.4 44-6.1 63.6-11 2.3 10.1 4.1 19.8 5.2 29.1zm38.5-66.7c-8.6 3.7-18 7-27.7 10.1-5.7-19.6-13.2-40-22.5-60.9 9.2-20.8 16.6-41.1 22.2-60.6 9.9 3.1 19.3 6.5 28.1 10.2 35.4 15.1 58.3 34.9 58.3 50.6-.1 15.7-23 35.6-58.4 50.6zM320.8 78.4z"/><circle cx="420.9" cy="296.5" r="45.7"/><path d="M520.5 78.1z"/></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

+13
View File
@@ -0,0 +1,13 @@
const reportWebVitals = onPerfEntry => {
if (onPerfEntry && onPerfEntry instanceof Function) {
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
getCLS(onPerfEntry);
getFID(onPerfEntry);
getFCP(onPerfEntry);
getLCP(onPerfEntry);
getTTFB(onPerfEntry);
});
}
};
export default reportWebVitals;
+5
View File
@@ -0,0 +1,5 @@
// jest-dom adds custom jest matchers for asserting on DOM nodes.
// allows you to do things like:
// expect(element).toHaveTextContent(/react/i)
// learn more: https://github.com/testing-library/jest-dom
import '@testing-library/jest-dom';
+2
View File
@@ -0,0 +1,2 @@
PORT=3001
MONGODB_URI=mongodb+srv://admin:admin@cluster1.ciuxwxd.mongodb.net/personApp?retryWrites=true&w=majority
@@ -0,0 +1,13 @@
{
"files": {
"main.css": "/static/css/main.305410ed.css",
"main.js": "/static/js/main.dde63dc0.js",
"index.html": "/index.html",
"main.305410ed.css.map": "/static/css/main.305410ed.css.map",
"main.dde63dc0.js.map": "/static/js/main.dde63dc0.js.map"
},
"entrypoints": [
"static/css/main.305410ed.css",
"static/js/main.dde63dc0.js"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

+1
View File
@@ -0,0 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.dde63dc0.js"></script><link href="/static/css/main.305410ed.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

+25
View File
@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
+3
View File
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
@@ -0,0 +1,2 @@
.error{color:red}.error,.normal{background:#d3d3d3;border-radius:5px;border-style:solid;font-size:20px;margin-bottom:10px;padding:10px}.normal{color:green}
/*# sourceMappingURL=main.305410ed.css.map*/
@@ -0,0 +1 @@
{"version":3,"file":"static/css/main.305410ed.css","mappings":"AAAA,OACE,SAOF,CACA,eAPE,kBAAqB,CAGrB,iBAAkB,CADlB,kBAAmB,CADnB,cAAe,CAIf,kBAAmB,CADnB,YAWF,CARA,QACE,WAOF","sources":["index.css"],"sourcesContent":[".error {\n color: red;\n background: lightgrey;\n font-size: 20px;\n border-style: solid;\n border-radius: 5px;\n padding: 10px;\n margin-bottom: 10px;\n}\n.normal {\n color: green;\n background: lightgrey;\n font-size: 20px;\n border-style: solid;\n border-radius: 5px;\n padding: 10px;\n margin-bottom: 10px;\n}\n"],"names":[],"sourceRoot":""}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
+36
View File
@@ -0,0 +1,36 @@
const mongoose = require("mongoose");
mongoose.set("strictQuery", false);
const url = process.env.MONGODB_URI;
console.log("connecting to MongoDB");
mongoose
.connect(url)
.then((res) => {
console.log("connected to MongoDB");
})
.catch((err) => console.log("error connecting to MongoDB", err.message));
const personSchema = new mongoose.Schema({
name: { type: String, minLength: 3 },
number: {
type: String,
validate: {
validator: function (v) {
return /\d{2,3}-\d{5,25}/.test(v);
},
message: (props) => `${props.value} is not a valid phone number!`,
},
required: [true, "User phone number required"],
},
});
personSchema.set("toJSON", {
transform: (document, returnedObject) => {
returnedObject.id = returnedObject._id.toString();
delete returnedObject._id;
delete returnedObject.__v;
},
});
module.exports = mongoose.model("Person", personSchema);
File diff suppressed because it is too large Load Diff
+22
View File
@@ -0,0 +1,22 @@
{
"name": "p3exercise",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.1.4",
"express": "^4.18.2",
"mongoose": "^7.2.2",
"morgan": "^1.10.0"
},
"devDependencies": {
"nodemon": "^2.0.22"
}
}
+93
View File
@@ -0,0 +1,93 @@
require("dotenv").config();
const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const Person = require("./models/person");
const app = express();
const errorHandler = (error, req, res, next) => {
console.log(err.message);
if (err.name === "CastError")
return res.status(404).send({ error: "malformatted id" });
else if (err.name === "ValidationError")
return res.status(400).json({ error: err.message });
next(err);
};
morgan.token("type", function (req, res) {
return String(JSON.stringify(req.body));
});
// middleware to deal with same origin
app.use(cors());
// middleware to allow express to deliver html
// it is unclear to me why i cant just make a get method that deals with that
app.use(express.static("build"));
// transfprms it to jsontransfprms it to json
app.use(express.json());
// adding additional information on request
app.use(
morgan(":method :url :status :res[content-length] - :response-time ms :type")
);
app.use(errorHandler);
app.get("/api/persons", (req, res, next) => {
Person.find({})
.then((persons) => {
res.json(persons);
})
.catch((err) => next(err));
});
/* currently not used
const date = new Date();
app.get("/api/info", (req, res) => {
res.send(`Phonebook has info for ${data.length} persons <br />${date}`);
});
*/
app.get("/api/persons/:id", (req, res, next) => {
Person.findById(req.params.id)
.then((person) => {
if (person) res.json(person);
else res.status(404).end();
})
.catch((err) => next(err));
});
app.post("/api/persons", (req, res, next) => {
const body = req.body;
const person = new Person({
name: body.name,
number: body.number,
id: Math.floor(Math.random() * 1000),
});
person
.save()
.then((savedPerson) => {
res.json(savedPerson);
})
.catch((err) => next(err));
});
app.put("/api/persons/:id", (req, res, next) => {
const { name, number } = req.body;
Person.findOneAndUpdate(
{ id: req.params.id },
{ name, number },
{ new: true, runValidators: true, context: "query" }
)
.then((updatedPerson) => {
res.json(updatedPerson);
})
.catch((err) => next(err));
});
app.delete("/api/persons/:id", (req, res, next) => {
Person.findByIdAndRemove(req.params.id)
.then((result) => {
console.log("result:", result);
res.status(204).end();
})
.catch((err) => next(err));
});
const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
+8
View File
@@ -0,0 +1,8 @@
#! /usr/bin/bash
rm -r ./frontend/build
echo -n "removed build from frontend"
npm run build --prefix frontend
echo -n "made new build"
cp -r ./frontend/build ./backend
echo -n "copied build to frontend"
@@ -0,0 +1,13 @@
{
"files": {
"main.css": "/static/css/main.305410ed.css",
"main.js": "/static/js/main.dde63dc0.js",
"index.html": "/index.html",
"main.305410ed.css.map": "/static/css/main.305410ed.css.map",
"main.dde63dc0.js.map": "/static/js/main.dde63dc0.js.map"
},
"entrypoints": [
"static/css/main.305410ed.css",
"static/js/main.dde63dc0.js"
]
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

+1
View File
@@ -0,0 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1"/><meta name="theme-color" content="#000000"/><meta name="description" content="Web site created using create-react-app"/><link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/><title>React App</title><script defer="defer" src="/static/js/main.dde63dc0.js"></script><link href="/static/css/main.305410ed.css" rel="stylesheet"></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root"></div></body></html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

+25
View File
@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
+3
View File
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
@@ -0,0 +1,2 @@
.error{color:red}.error,.normal{background:#d3d3d3;border-radius:5px;border-style:solid;font-size:20px;margin-bottom:10px;padding:10px}.normal{color:green}
/*# sourceMappingURL=main.305410ed.css.map*/
@@ -0,0 +1 @@
{"version":3,"file":"static/css/main.305410ed.css","mappings":"AAAA,OACE,SAOF,CACA,eAPE,kBAAqB,CAGrB,iBAAkB,CADlB,kBAAmB,CADnB,cAAe,CAIf,kBAAmB,CADnB,YAWF,CARA,QACE,WAOF","sources":["index.css"],"sourcesContent":[".error {\n color: red;\n background: lightgrey;\n font-size: 20px;\n border-style: solid;\n border-radius: 5px;\n padding: 10px;\n margin-bottom: 10px;\n}\n.normal {\n color: green;\n background: lightgrey;\n font-size: 20px;\n border-style: solid;\n border-radius: 5px;\n padding: 10px;\n margin-bottom: 10px;\n}\n"],"names":[],"sourceRoot":""}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,39 @@
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
File diff suppressed because one or more lines are too long
+19
View File
@@ -0,0 +1,19 @@
{
"persons": [
{
"name": "dsdsd",
"number": "sdsdsds",
"id": 6
},
{
"name": "dfadf",
"number": "dafasdfa",
"id": 7
},
{
"name": "sdfadfadaf",
"number": "adfadfadsf",
"id": 9
}
]
}
File diff suppressed because it is too large Load Diff
+44
View File
@@ -0,0 +1,44 @@
{
"name": "p1",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/jest-dom": "^5.16.5",
"@testing-library/react": "^13.4.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.4.0",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-scripts": "5.0.1",
"web-vitals": "^2.1.4"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"server": "npx json-server --port 3001 --watch db.json"
},
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
]
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"json-serve": "^0.1.0"
},
"proxy": "http://localhost:3001"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

+43
View File
@@ -0,0 +1,43 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%PUBLIC_URL%/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="theme-color" content="#000000" />
<meta
name="description"
content="Web site created using create-react-app"
/>
<link rel="apple-touch-icon" href="%PUBLIC_URL%/logo192.png" />
<!--
manifest.json provides metadata used when your web app is installed on a
user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
-->
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
<!--
Notice the use of %PUBLIC_URL% in the tags above.
It will be replaced with the URL of the `public` folder during the build.
Only files inside the `public` folder can be referenced from the HTML.
Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
work correctly both with client-side routing and a non-root public URL.
Learn how to configure a non-root public URL by running `npm run build`.
-->
<title>React App</title>
</head>
<body>
<noscript>You need to enable JavaScript to run this app.</noscript>
<div id="root"></div>
<!--
This HTML file is a template.
If you open it directly in the browser, you will see an empty page.
You can add webfonts, meta tags, or analytics to this file.
The build step will place the bundled scripts into the <body> tag.
To begin the development, run `npm start` or `yarn start`.
To create a production bundle, use `npm run build` or `yarn build`.
-->
</body>
</html>
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

@@ -0,0 +1,25 @@
{
"short_name": "React App",
"name": "Create React App Sample",
"icons": [
{
"src": "favicon.ico",
"sizes": "64x64 32x32 24x24 16x16",
"type": "image/x-icon"
},
{
"src": "logo192.png",
"type": "image/png",
"sizes": "192x192"
},
{
"src": "logo512.png",
"type": "image/png",
"sizes": "512x512"
}
],
"start_url": ".",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
+3
View File
@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:
+44
View File
@@ -0,0 +1,44 @@
import Persons from "./components/Persons";
import Filter from "./components/Filter";
import PersonForm from "./components/PersonForm";
import Notification from "./components/Notification";
import { useState, useEffect } from "react";
import personServices from "./services/persons";
const App = () => {
const [persons, setPersons] = useState([]);
const [filter, setFilter] = useState("");
const [message, setMessage] = useState(null);
useEffect(() => {
personServices.getAll().then((response) => setPersons(response.data));
}, []);
function displayMessage(message, type = "normal") {
setMessage({message,type});
setTimeout(() => {
setMessage(null);
}, 5000);
}
return (
<div>
<h2>Phonebook</h2>
<Notification message={message} />
<Filter persons={persons} filter={filter} setFilter={setFilter} />
<h2>add a new</h2>
<PersonForm
persons={persons}
setPersons={setPersons}
displayMessage={displayMessage}
/>
<h2>Numbers</h2>
<Persons
persons={persons.filter((el) =>
el.name.toLowerCase().includes(filter.toLowerCase())
)}
setPersons={setPersons}
/>
</div>
);
};
export default App;
@@ -0,0 +1,19 @@
function Course({ course }) {
const total = course.parts.reduce((acc, curr) => acc + curr.exercises, 0);
return (
<>
<h1>{course.name}</h1>
<ul>
{course.parts.map((c) => (
<li key={c.id}>
{c.name} {c.exercises}
</li>
))}
<li>
<b>total of</b> {total} <b>exercises</b>
</li>
</ul>
</>
);
}
export default Course;
@@ -0,0 +1,12 @@
function Filter({ filter, setFilter}) {
function onFilter(e) {
setFilter(e.target.value);
}
return (
<div>
filter shown with <input value={filter} onChange={onFilter} />
</div>
);
}
export default Filter;
@@ -0,0 +1,5 @@
const Notification= ({message}) => {
if (message === null) return null;
return <div className={message.type}>{message.message}</div>;
};
export default Notification
@@ -0,0 +1,60 @@
import { useState } from "react";
import personServices from "../services/persons";
function PersonForm({ persons, setPersons, displayMessage }) {
const [newName, setNewName] = useState("");
const [newNumber, setNewNumber] = useState("");
function onAddPerson(e) {
e.preventDefault();
const newPerson = { name: newName, number: newNumber };
const id = persons.find((el) => el.name === newName)?.id;
if (id) {
personServices
.update(id, newPerson)
.then(() => {
setPersons(
persons.map((person) => (person.id !== id ? person : newPerson))
);
displayMessage("Number changed");
})
.catch((err) => {
console.error(err.message);
displayMessage("Number has already been removed", "error");
});
} else {
personServices
.create(newPerson)
.then(() => {
setPersons([...persons, newPerson]);
displayMessage("Person Added");
})
.catch((error) => {
console.log(error.response.data)
displayMessage('Validation Error', "error");
});
}
setNewName("");
setNewNumber("");
}
return (
<form onSubmit={onAddPerson}>
<div>
name:{" "}
<input value={newName} onChange={(e) => setNewName(e.target.value)} />
</div>
<div>
number:{" "}
<input
value={newNumber}
onChange={(e) => setNewNumber(e.target.value)}
/>
</div>
<div>
<button type="submit">add</button>
</div>
</form>
);
}
export default PersonForm;
@@ -0,0 +1,20 @@
import personServices from "../services/persons";
function Persons({ persons, setPersons }) {
function onDelete(id) {
personServices
.remove(id)
.then(setPersons(persons.filter((pred) => pred.id != id)));
}
return (
<ul>
{persons.map((person, index) => (
<li key={index}>
{person.name} {person.number}{" "}
<button onClick={() => onDelete(person.id)}>delete</button>
</li>
))}
</ul>
);
}
export default Persons;
+18
View File
@@ -0,0 +1,18 @@
.error {
color: red;
background: lightgrey;
font-size: 20px;
border-style: solid;
border-radius: 5px;
padding: 10px;
margin-bottom: 10px;
}
.normal {
color: green;
background: lightgrey;
font-size: 20px;
border-style: solid;
border-radius: 5px;
padding: 10px;
margin-bottom: 10px;
}
+27
View File
@@ -0,0 +1,27 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import './index.css'
import App from './App'
const notes = [
{
id: 1,
content: 'HTML is easy',
important: true
},
{
id: 2,
content: 'Browser can execute only JavaScript',
important: false
},
{
id: 3,
content: 'GET and POST are the most important methods of HTTP protocol',
important: true
}
]
ReactDOM.createRoot(document.getElementById('root')).render(
<App notes={notes} />
)
@@ -0,0 +1,15 @@
import axios from "axios";
const baseUrl = "/api/persons/";
const getAll = () => axios.get(baseUrl);
const create = (newPerson) => axios.post(baseUrl, newPerson);
const remove = (id) => axios.delete(baseUrl.concat(id.toString()));
const update = (id, newPerson) => axios.put(`${baseUrl}${id}`, newPerson);
export default {
getAll: getAll,
create: create,
remove: remove,
update: update,
};
+78
View File
@@ -0,0 +1,78 @@
import { useState } from "react";
function Statistics({ good, bad, neutral }) {
return (
<div>
<h1>statistics</h1>
<ul>
<StatisticsLine text={"good"} value={good} />
<StatisticsLine text={"neutral"} value={neutral} />
<StatisticsLine text={"bad"} value={bad} />
<StatisticsLine text={"all"} value={bad + good + neutral} />
<StatisticsLine
text={"average"}
value={(good - bad) / (good + bad + neutral)}
/>
</ul>
</div>
);
}
function StatisticsLine({ text, value }) {
return (
<li>
{text}: {value}
</li>
);
}
function Anecdotes({ anecdotes, selected }) {
return (
<>
<div>{anecdotes[selected]}</div>
</>
);
}
const App = () => {
// save clicks of each button to its own state
const [good, setGood] = useState(0);
const [neutral, setNeutral] = useState(0);
const [bad, setBad] = useState(0);
const [selected, setSelected] = useState(0);
const [votes, setVotes] = useState(new Array(7).fill(0));
const anecdotes = [
"If it hurts, do it more often.",
"Adding manpower to a late software project makes it later!",
"The first 90 percent of the code accounts for the first 10 percent of the development time...The remaining 10 percent of the code accounts for the other 90 percent of the development time.",
"Any fool can write code that a computer can understand. Good programmers write code that humans can understand.",
"Premature optimization is the root of all evil.",
"Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it.",
"Programming without an extremely heavy use of console.log is same as if a doctor would refuse to use x-rays or blood tests when diagnosing patients.",
"The only way to go fast, is to go well.",
];
let highest = Math.max(...votes)
function addVote() {
let newVotes = [...votes];
newVotes[selected] += 1;
setVotes(newVotes);
}
return (
<div>
<h1>give feedback</h1>
<button onClick={() => setGood(good + 1)}>good</button>
<button onClick={() => setNeutral(neutral + 1)}>neutral</button>
<button onClick={() => setBad(bad + 1)}>bad</button>
<Statistics good={good} bad={bad} neutral={neutral} />
<Anecdotes anecdotes={anecdotes} selected={selected} />
<h1>has {votes[selected]} votes</h1>
<button onClick={() => addVote()}>vote</button>
<button onClick={() => setSelected(Math.floor(Math.random() * 7))}>
next anecdote{" "}
</button>
<h1>Is the most liked</h1>
<Anecdotes anecdotes={anecdotes} selected={Math.max(...votes)}/>
</div>
);
};
export default App;
+6
View File
@@ -0,0 +1,6 @@
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
ReactDOM.createRoot(document.getElementById('root')).render(<App />)
+16
View File
@@ -0,0 +1,16 @@
#! /usr/bin/bash
echo -n "1 for get All, 2 for get with id, 3 for create, 4 for delete "
read action
if [[ $action == 1 ]]; then
curl http://localhost:3001/api/persons | json_pp -json_opt pretty,canonical
elif [[ $action == 2 ]]; then
echo -n "gib id "
read id
curl http://localhost:3001/api/persons/${id} | json_pp -json_opt pretty,canonical
elif [[ $action == 3 ]]; then
curl -H "Content-Type: application/json" -X POST -d '{"name":"xyz","number":"xyz"}' http://localhost:3001/api/persons | json_pp -json_opt pretty,canonical
elif [[ $action == 4 ]]; then
echo -n "gib id "
read id
curl -H "Content-Type: application/json" -X DELETE http://localhost:3001/api/persons/6482b803a270efb823a3cfb0 | json_pp -json_opt pretty,canonical
fi
+4
View File
@@ -0,0 +1,4 @@
PORT=3003
MONGODB_URI='mongodb+srv://admin:admin@cluster1.ciuxwxd.mongodb.net/blogApp?retryWrites=true&w=majority'
TEST_MONGODB_URI='mongodb+srv://admin:admin@cluster1.ciuxwxd.mongodb.net/testBlogApp?retryWrites=true&w=majority'
SECRET='kdsajf90u234ijkasl;sdafds90812jpsakdy3894ioeklj321;ljx098zxxc'
+1
View File
@@ -0,0 +1 @@
missing testing execise 4.23 maybe even 4.8 -4.14
+22
View File
@@ -0,0 +1,22 @@
const express = require("express");
const cors = require("cors");
const mongoose = require("mongoose");
const blogsRouter = require("./controllers/blogs");
const usersRouter = require("./controllers/users");
const loginRouter = require("./controllers/login");
const config = require("./utils/config");
const middleware = require("./utils/middleware");
const app = express();
mongoose.connect(config.MONGODB_URI).then(() => {
console.log("connected to mongodb");
});
app.use(cors());
app.use(express.json());
app.use(middleware.tokenExtractor);
app.use("/api/blogs" , blogsRouter);
app.use("/api/users", usersRouter);
app.use("/api/login", loginRouter);
module.exports = app;
+56
View File
@@ -0,0 +1,56 @@
const blogsRouter = require("express").Router();
const Blog = require("../models/blog");
const User = require("../models/user");
const middleware = require("../utils/middleware");
blogsRouter.get("", (request, response) => {
Blog.find({})
.populate("user", { name: 1 })
.then((blogs) => {
response.json(blogs);
});
});
blogsRouter.delete("/:id", middleware.userExtractor, async (req, res) => {
const id = req.params.id;
const blog = await Blog.findById(id);
let result = null;
const userId = req.user._id.toString();
if (blog.user.toString() === userId) {
const newUser = {
...req.user._doc,
blogs: [...req.user._doc.blogs.filter((el) => el.toString() !== id)],
};
await User.findOneAndUpdate({ _id: userId }, newUser);
result = await Blog.findByIdAndDelete(id);
return res.json(result);
}
return res.end();
});
blogsRouter.put("/:id", (req, res) => {
const id = req.params.id;
Blog.findOneAndUpdate({ _id: id }, req.body).then((result) => {
res.json(result);
});
});
blogsRouter.post("", middleware.userExtractor, async (req, res) => {
const { title, url } = req.body;
const user = req.user;
const blog = new Blog({
title,
author: user.name,
url,
likes: 0,
user: user.id,
});
const savedBlog = await blog.save();
user.blogs = user.blogs.concat(savedBlog._id);
user.save();
res.json(savedBlog);
});
module.exports = blogsRouter;
+24
View File
@@ -0,0 +1,24 @@
const loginRouter = require("express").Router();
const jwt = require("jsonwebtoken");
const bcrypt = require("bcrypt");
const User = require("../models/user");
const config = require("../utils/config");
loginRouter.post("", async (req, res) => {
const { username, password } = req.body;
const user = await User.findOne({ username });
const passwordCorrect =
user === null ? false : await bcrypt.compare(password, user.password);
if (!(user && passwordCorrect))
return res.status(401).json({ error: "invalid username or passowrd" });
const userForToken = {
username: user.username,
id: user._id,
};
const token = jwt.sign(userForToken, config.SECRET);
res.status(200).send({ token, username: user.username, name: user.name });
});
module.exports = loginRouter;
+36
View File
@@ -0,0 +1,36 @@
const usersRouter = require("express").Router();
const User = require("../models/user");
const bcrypt = require("bcrypt");
usersRouter.get("", (request, response) => {
User.find({}).then((users) => {
response.json(users);
});
});
/*
usersRouter.delete("/:id", (request, response) => {
const id = request.params.id;
User.findByIdAndDelete(id).then((users) => response.json(users));
});
usersRouter.put("/:id", (request, response) => {
const id = request.params.id;
const data = { ...request.body };
User.findOneAndUpdate({ _id: id }, data).then((result) => {
response.json(result);
});
});
*/
usersRouter.post("", async (request, response) => {
const { username, password, name } = request.body;
const hashedPassword = await bcrypt.hash(password, 10);
const user = new User({ username, password: hashedPassword, name });
try {
const savedUser = await user.save();
response.status(201).json(savedUser);
} catch (err) {
response.status(400).send(err._message);
}
});
module.exports = usersRouter;
+25
View File
@@ -0,0 +1,25 @@
const mongoose = require("mongoose");
const blogSchema = new mongoose.Schema({
title: String,
author: String,
url: String,
likes: Number,
comments: [String],
user: {
type: mongoose.Schema.Types.ObjectId,
ref: "User",
},
});
blogSchema.set("toJSON", {
transform: (document, returnedObject) => {
returnedObject.id = returnedObject._id.toString();
delete returnedObject._id;
delete returnedObject.__v;
},
});
const Blog = mongoose.model("Blog", blogSchema);
module.exports = Blog;

Some files were not shown because too many files have changed in this diff Show More