3 Commits
main ... Lab_6

Author SHA1 Message Date
7f11d11240 Исправил отчет
Нового функционала в проекте не предусмотрено
2025-05-28 10:56:03 +04:00
39bdacaefc Doc_6 2025-05-24 16:57:21 +04:00
5e5955574e Lab_6 2025-05-24 14:47:43 +04:00
59 changed files with 19774 additions and 0 deletions

23
ИП6/111/.gitignore vendored Normal file
View File

@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# production
/build
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*

70
ИП6/111/README.md Normal file
View File

@@ -0,0 +1,70 @@
# Getting Started with Create React App
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## Available Scripts
In the project directory, you can run:
### `npm start`
Runs the app in the development mode.\
Open [http://localhost:3000](http://localhost:3000) to view it in your browser.
The page will reload when you make changes.\
You may also see any lint errors in the console.
### `npm test`
Launches the test runner in the interactive watch mode.\
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `npm run build`
Builds the app for production to the `build` folder.\
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.\
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `npm run eject`
**Note: this is a one-way operation. Once you `eject`, you can't go back!**
If you aren't satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you're on your own.
You don't have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn't feel obligated to use this feature. However we understand that this tool wouldn't be useful if you couldn't customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: [https://facebook.github.io/create-react-app/docs/code-splitting](https://facebook.github.io/create-react-app/docs/code-splitting)
### Analyzing the Bundle Size
This section has moved here: [https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size](https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size)
### Making a Progressive Web App
This section has moved here: [https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app](https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app)
### Advanced Configuration
This section has moved here: [https://facebook.github.io/create-react-app/docs/advanced-configuration](https://facebook.github.io/create-react-app/docs/advanced-configuration)
### Deployment
This section has moved here: [https://facebook.github.io/create-react-app/docs/deployment](https://facebook.github.io/create-react-app/docs/deployment)
### `npm run build` fails to minify
This section has moved here: [https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify](https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify)

18202
ИП6/111/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

45
ИП6/111/package.json Normal file
View File

@@ -0,0 +1,45 @@
{
"name": "111",
"version": "0.1.0",
"private": true,
"dependencies": {
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@testing-library/user-event": "^13.5.0",
"axios": "^1.9.0",
"bootstrap": "^5.3.6",
"bootstrap-icons": "^1.13.1",
"json-server": "^1.0.0-beta.3",
"react": "^19.1.0",
"react-dom": "^19.1.0",
"react-router-dom": "^7.6.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": "json-server --watch public/db.json --port 3001"
},
"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"
]
}
}

3
ИП6/111/public/db.json Normal file
View File

@@ -0,0 +1,3 @@
{
"posts": []
}

View File

@@ -0,0 +1,4 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.002 0H2.002C0.899001 0 0.00200081 0.897 0.00200081 2V6H2.002V2H16.002V16H2.002V12H0.00200081V16C0.00200081 17.103 0.899001 18 2.002 18H16.002C17.105 18 18.002 17.103 18.002 16V2C18.002 0.897 17.104 0 16.002 0Z" fill="white"/>
<path d="M8 13L13 9L8 5V8.001H0V10.001H8V13Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 403 B

View File

@@ -0,0 +1,3 @@
<svg width="48" height="47" viewBox="0 0 48 47" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23.9629 0.054492C23.753 0.0617304 23.5507 0.134847 23.3848 0.263476L0.384755 18.2107C0.175483 18.3739 0.0396014 18.6135 0.00700236 18.8769C-0.0255966 19.1402 0.0477576 19.4058 0.210928 19.615C0.374098 19.8243 0.613719 19.9602 0.877075 19.9928C1.14043 20.0254 1.40595 19.952 1.61522 19.7889L2.99999 18.7088V44.9998C3.00002 45.265 3.10538 45.5194 3.29291 45.7069C3.48044 45.8944 3.73478 45.9998 3.99999 45.9998H17.832C17.94 46.0177 18.0502 46.0177 18.1582 45.9998H29.832C29.94 46.0177 30.0502 46.0177 30.1582 45.9998H44C44.2652 45.9998 44.5195 45.8944 44.7071 45.7069C44.8946 45.5194 45 45.265 45 44.9998V18.7088L46.3848 19.7889C46.4884 19.8697 46.6069 19.9293 46.7336 19.9643C46.8602 19.9993 46.9925 20.009 47.1229 19.9928C47.2533 19.9767 47.3793 19.935 47.4936 19.8702C47.6079 19.8054 47.7083 19.7187 47.7891 19.6151C47.8699 19.5115 47.9295 19.3929 47.9645 19.2663C47.9995 19.1396 48.0092 19.0073 47.993 18.8769C47.9769 18.7465 47.9352 18.6205 47.8704 18.5062C47.8056 18.3919 47.7189 18.2915 47.6152 18.2107L40 12.2693V4.9998H34V7.58574L24.6152 0.263476C24.4292 0.119197 24.1981 0.0451914 23.9629 0.054492ZM24 2.32207L43 17.1482V43.9998H31V24.9998H17V43.9998H4.99999V17.1482L24 2.32207ZM36 6.9998H38V10.7088L36 9.14629V6.9998ZM19 26.9998H29V43.9998H19V26.9998Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

View File

@@ -0,0 +1,6 @@
<svg width="323" height="330" viewBox="0 0 323 330" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M166.19 69.5299L100.78 62.6699L29.04 131.77L66.49 169.75L166.19 69.5299Z" fill="#FCD116"/>
<path d="M99.6401 136.43L279.07 317.44L282.17 320.6C282.17 320.6 284.35 323.07 288.2 323.86C292.06 324.65 292.55 325.94 300.36 323.86C308.17 321.78 310.65 316.74 310.65 316.74C310.65 316.74 314.7 310.71 314.61 306.65C314.51 302.6 313.72 297.75 310.56 294.49C307.4 291.23 297.8 281.24 297.8 281.24L125.74 110.19L99.6401 136.43Z" fill="#BF1723"/>
<path d="M97.8098 232.52C97.8098 232.52 94.8398 228.96 91.2798 228.76C87.7198 228.56 85.3498 228.96 82.9698 230.64C80.5898 232.32 81.5898 234.3 81.5898 234.3H77.8298C77.8298 234.3 69.7198 236.48 68.3398 238.45C66.9598 240.43 62.7998 247.55 62.4098 250.32C62.0198 253.09 30.5598 271.88 30.5598 271.88C30.5598 271.88 14.1398 286.52 11.3698 291.66C8.59979 296.8 5.82979 304.32 7.21979 311.04C8.59979 317.77 13.7498 321.52 13.7498 321.52C13.7498 321.52 21.0698 325.67 26.7998 324.88C32.5298 324.09 34.9098 324.68 45.7898 315.78C56.6698 306.88 62.0098 297.98 62.0098 297.98L72.2998 281.56L78.4298 271.87C78.4298 271.87 81.1998 271.28 84.5598 269.69C87.9198 268.11 95.2398 264.55 96.6298 260.79C98.0098 257.03 97.8198 255.84 97.8198 255.84C97.8198 255.84 99.3998 255.84 101.38 250.89C103.36 245.94 97.8098 232.52 97.8098 232.52Z" fill="#BF1723"/>
<path d="M171.99 3.37012L190.48 14.7401L210.75 28.9801L231.82 45.6901L245.17 57.9501L255.26 68.6301L263.63 78.4201C263.63 78.4201 275.5 92.8601 278.93 99.9101C282.36 106.96 290.37 118.87 294.03 130.64C297.69 142.41 302.24 158.73 302.14 170.4C302.04 182.07 300.16 204.52 295.61 214.41C291.06 224.3 281.76 245.86 271.28 254.17C260.8 262.48 237.06 280.58 237.06 280.58C237.06 280.58 212.93 291.06 197.5 292.45C182.07 293.84 157.74 291.07 149.83 287.5C141.92 283.94 118.38 275.63 107.1 263.57C95.8299 251.5 88.1099 240.82 88.1099 240.82L107.1 222.62C107.1 222.62 120.15 237.46 134.59 242.6C149.03 247.74 164.26 253.28 184.04 251.3C203.82 249.32 224.19 239.63 224.19 239.63C224.19 239.63 244.76 226.58 253.46 206.79C262.16 187.01 262.95 161.3 255.24 135.98C247.53 110.66 234.87 88.1101 234.87 88.1101C234.87 88.1101 208.17 44.2001 203.42 40.8401C198.69 37.4901 171.99 3.37012 171.99 3.37012Z" fill="#FCD116"/>
</svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

View File

@@ -0,0 +1,6 @@
<svg width="669" height="608" viewBox="0 0 669 608" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M33.265 607.169C29.796 607.169 26.387 605.874 23.763 603.432C19.932 599.868 18.419 594.459 19.844 589.424L53.914 469.04C18.725 419.919 0.162003 363.025 0.162003 304.06C0.162003 262.963 9.06701 223.103 26.63 185.588C43.542 149.463 67.724 117.046 98.503 89.237C161.523 32.301 245.217 0.945007 334.168 0.945007C423.122 0.945007 506.818 32.301 569.839 89.237C600.618 117.046 624.801 149.463 641.713 185.588C659.276 223.103 668.181 262.963 668.181 304.06C668.181 345.155 659.276 385.014 641.713 422.528C624.801 458.653 600.618 491.069 569.839 518.877C506.818 575.813 423.122 607.169 334.168 607.169C272.121 607.169 211.813 591.697 159.3 562.364L38.017 606.334C36.467 606.896 34.859 607.169 33.265 607.169ZM160.612 533.107C163.057 533.107 165.487 533.75 167.648 535.012C217.214 563.97 274.796 579.277 334.167 579.277C416.199 579.277 493.255 550.477 551.139 498.181C608.627 446.243 640.287 377.304 640.287 304.061C640.287 230.815 608.627 161.873 551.139 109.936C493.255 57.64 416.2 28.839 334.167 28.839C252.138 28.839 175.084 57.64 117.201 109.936C59.714 161.874 28.054 230.816 28.054 304.061C28.054 359.198 46.133 412.396 80.337 457.905C82.954 461.386 83.794 465.891 82.608 470.082L54.093 570.837L155.86 533.942C157.401 533.383 159.01 533.107 160.612 533.107Z" fill="white"/>
<path d="M440.419 402.182H153.893C146.191 402.182 139.947 395.938 139.947 388.236C139.947 380.534 146.191 374.29 153.893 374.29H440.419C448.121 374.29 454.365 380.534 454.365 388.236C454.365 395.938 448.121 402.182 440.419 402.182Z" fill="white"/>
<path d="M514.448 318.003H153.893C146.191 318.003 139.947 311.759 139.947 304.057C139.947 296.355 146.191 290.111 153.893 290.111H514.448C522.15 290.111 528.394 296.355 528.394 304.057C528.394 311.759 522.15 318.003 514.448 318.003Z" fill="white"/>
<path d="M514.448 233.826H153.893C146.191 233.826 139.947 227.582 139.947 219.88C139.947 212.178 146.191 205.934 153.893 205.934H514.448C522.15 205.934 528.394 212.178 528.394 219.88C528.394 227.582 522.15 233.826 514.448 233.826Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 356 KiB

View File

@@ -0,0 +1,10 @@
<svg width="428" height="428" viewBox="0 0 428 428" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_3_100)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M199.5 1.03578C163.394 3.43679 127.681 15.3168 98 34.8018C84.295 43.7998 76.669 49.9688 64.63 61.7998C30.476 95.3648 9.58699 136.587 2.45399 184.5C0.201994 199.629 0.212996 227.823 2.478 243.5C7.987 281.635 23.311 317.238 47.026 347C55.453 357.575 75.042 376.781 85 384.231C114.449 406.264 147.76 420.093 184.5 425.538C199.308 427.733 228.803 427.738 243.5 425.547C280.235 420.073 313.627 406.207 343 384.231C352.958 376.781 372.547 357.575 380.974 347C404.616 317.33 419.695 282.336 425.573 243.5C427.791 228.843 427.78 199.441 425.55 184.5C420.85 153.009 409.639 123.097 393.055 97.7978C384.244 84.3568 378.038 76.6828 366.2 64.5908C322.341 19.7908 262.214 -3.13322 199.5 1.03578ZM229.699 23.0078C303.453 29.5368 365.275 75.5218 392.359 144C401.417 166.902 405.28 187.832 405.277 214C405.274 240.064 401.203 261.901 392.036 285.032C384.876 303.1 372.169 324.192 360.227 337.835L354.682 344.169L352.497 338.835C338.115 303.72 309.622 274.318 275.006 258.871C269.002 256.192 263.619 254 263.045 254C262.47 254 262 253.55 262 253C262 252.45 262.455 252 263.011 252C264.865 252 280.202 236.58 284.206 230.691C294.644 215.336 299.182 200.581 299.182 182C299.182 166.457 297.058 157.518 290.034 143.5C281.672 126.813 268.989 114.121 252.5 105.937C238.374 98.9258 229.474 96.8178 214 96.8178C198.457 96.8178 189.518 98.9418 175.5 105.966C153.687 116.897 137.129 137.499 130.869 161.5C127.953 172.676 127.976 191.296 130.919 202.5C133.458 212.167 139.441 224.98 144.784 232.194C149.052 237.957 163.388 252 165.003 252C167.922 252 165.162 253.949 158.75 256.416C122.293 270.443 90.705 301.717 75.503 338.835L73.318 344.169L67.773 337.835C55.831 324.192 43.124 303.1 35.964 285.032C22.115 250.088 18.83 211.588 26.53 174.457C42.729 96.3408 107.189 35.7338 186 24.5228C204.236 21.9278 213.766 21.5978 229.699 23.0078ZM230.539 120.552C254.543 126.804 272.639 147.171 276.797 172.616C278.179 181.068 278.177 182.942 276.779 191.494C272.202 219.505 251.505 240.202 223.494 244.779C214.942 246.177 213.068 246.179 204.616 244.797C185.349 241.649 168.746 230.529 159.241 214.408C144.475 189.366 148.503 157.592 169.048 137.048C185.179 120.916 208.213 114.737 230.539 120.552ZM235.619 269.546C281.127 277.466 318.697 309.167 334.407 352.901L337.066 360.301L334.824 362.687C330.891 366.874 309.862 380.423 299 385.77C280.495 394.878 262.6 400.459 241.585 403.676C226.794 405.941 201.177 405.936 186.346 403.666C162.687 400.045 137.287 391.18 117.956 379.797C108.563 374.266 92.822 363.139 91.606 361.171C91.263 360.617 92.169 356.865 93.617 352.832C107.023 315.514 136.007 286.96 173.055 274.576C178.86 272.636 187.185 270.403 191.555 269.614C202.39 267.658 224.575 267.623 235.619 269.546Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_3_100">
<rect width="428" height="428" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.1 KiB

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

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"
}

View File

@@ -0,0 +1,3 @@
# https://www.robotstxt.org/robotstxt.html
User-agent: *
Disallow:

38
ИП6/111/src/App.css Normal file
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);
}
}

27
ИП6/111/src/App.jsx Normal file
View File

@@ -0,0 +1,27 @@
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import FeedPage from './pages/FeedPage';
import MessagesPage from './pages/MessagesPage';
import ProfilePage from './pages/ProfilePage';
import LoginPage from './pages/LoginPage';
import SignupPage from './pages/SignupPage';
import NotFoundPage from './pages/NotFoundPage';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
function App() {
return (
<Router>
<Routes>
<Route path="/" element={<LoginPage />} />
<Route path="/signup" element={<SignupPage />} />
<Route path="/feed" element={<FeedPage />} />
<Route path="/messages" element={<MessagesPage />} />
<Route path="/profile" element={<ProfilePage />} />
<Route path="*" element={<NotFoundPage />} />
</Routes>
</Router>
);
}
export default App;

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();
});

View File

@@ -0,0 +1,11 @@
.bottombar{
bottom: 0;
border-top: 3px solid #BF1723;
border-top-right-radius: 25px;
border-top-left-radius: 25px;
background-color: #222222;
}
.bottombar > a > img {
width: 25px;
}

View File

@@ -0,0 +1,13 @@
import './Bottombar.css'
import { Link } from 'react-router-dom';
export default function Bottombar() {
return(
<div class="bottombar d-flex d-sm-none position-fixed w-100 justify-content-evenly py-2 px-0">
<Link to="/feed"><img src="../images/home-icon.svg" alt="" /></Link>
<Link to="/messages"><img src="../images/message-icon.svg" alt="" /></Link>
<Link to="/profile"><img src="../images/profile-icon.svg" alt="" /></Link>
<Link to="/"><img src="../images/exit-icon.svg" alt="" /></Link>
</div>
)
}

View File

@@ -0,0 +1,15 @@
.chat {
border-bottom: 0.5px solid rgba(128, 128, 128, 0.479);
}
.chat > .avatar > img {
border-radius: 25px;
}
.username {
color: white;
}
.message {
color: rgb(158, 158, 158);
}

View File

@@ -0,0 +1,16 @@
import './Chat.css'
export default function Chat({ username, message, avatarUrl }) {
return(
<div class="chat d-flex align-items-center mb-2 pb-2">
<div class="avatar">
<img src={avatarUrl} alt="" class="avatar" />
</div>
<div class="chat-content ms-2">
<h3 class="username m-0">{username}</h3>
<p class="message m-0">{message}</p>
</div>
</div>
)
}

View File

@@ -0,0 +1,16 @@
/* Шапка */
header .container-fluid {
display: flex;
justify-content: space-evenly;
border-bottom: 3px solid #BF1723;
border-bottom-right-radius: 25px;
border-bottom-left-radius: 25px;
}
.left-part{
display: flex;
}
.right-part > img {
border-radius: 25px;
}

View File

@@ -0,0 +1,17 @@
import './Header.css'
export default function Header() {
return(
<header>
<div class="container-fluid">
<div class="left-part">
<img src="../images/logo.svg" alt="Logo" width="50" />
</div>
<div class="right-part d-none d-sm-flex me-4 my-1">
<img src="../images/photo.jpg" alt="" class="account-image" />
</div>
</div>
</header>
)
}

View File

@@ -0,0 +1,16 @@
/* Шапка */
header .container-fluid {
border-bottom: 3px solid #BF1723;
border-bottom-right-radius: 25px;
border-bottom-left-radius: 25px;
}
.first-part {
color:#FCD116;
font-size: 1.4em;
}
.last-part {
color: #BF1723;
font-size: 1.5em;
}

View File

@@ -0,0 +1,27 @@
import './HeaderAuth.css'
import { Link } from 'react-router-dom';
export default function Header() {
return(
<header>
<div className="container-fluid d-flex justify-content-evenly">
<div className="left-part d-flex">
<img src="/images/logo.svg" alt="Logo" width="50" />
<div className="d-flex align-items-center pt-3">
<p className="first-part ms-3">СОЦИАЛ</p>
<p className="last-part">ьная сеть</p>
</div>
</div>
<div className="right-part d-none d-sm-flex me-4 pt-3">
<nav>
<ul className="d-flex list-unstyled p-0 m-0">
<li><Link className="d-block me-2 p-2" to="/feed">Войти</Link></li>
<li><Link className="d-block me-2 p-2" to="/signup">Зарегистрироваться</Link></li>
</ul>
</nav>
</div>
</div>
</header>
)
}

View File

@@ -0,0 +1,76 @@
.custom-link:link {
color: white;
text-decoration: none;
}
.custom-link:visited {
color: white;
}
.custom-link:hover {
color: #BF1723;
background-color: #2a2a2a;
}
.custom-link:active {
color: #FCD116;
}
.leftbar {
width: 10%;
background-color: #222222;
border-radius: 15px;
min-width: 120px;
}
.leftbar-content > .custom-link {
border-radius: 5px;
}
.leftbar-settings {
border-top: 1px solid rgba(128, 128, 128, 0.479);
}
.leftbar-settings > .custom-link{
border-radius: 5px;
}
.footer {
border-top: 1px solid rgba(128, 128, 128, 0.479);
}
.footer > span {
z-index: 1;
cursor: pointer;
color: white;
}
span:hover {
color: #BF1723;
}
.footer:hover .footer-menu {
display: flex;
flex-direction: column;
top: 150%;
left: -6%;
width: 110%;
position: absolute;
background-color: #222222;
border-radius: 10px;
padding: 10px;
min-width: 120px;
}
.footer-menu {
display: none;
}
.footer-menu > a {
border-radius: 5px;
}

View File

@@ -0,0 +1,30 @@
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.bundle.min';
import { Link } from 'react-router-dom';
import './Leftbar.css'
export default function Leftbar() {
return(
<div class="leftbar d-none h-100 m-1 d-sm-flex flex-column">
<div class="leftbar-content d-flex flex-column mt-2 mx-2 mb-1">
<Link className="custom-link mb-1 p-1" to="/profile">Профиль</Link>
<Link className="custom-link mb-1 p-1" to="/feed">Лента</Link>
<Link className="custom-link mb-1 p-1" to="/messages">Сообщения</Link>
</div>
<div class="leftbar-settings d-flex flex-column mt-2 mx-2 mb-0 pt-1">
<Link className="custom-link p-1" >Настройки</Link>
</div>
<div class="footer position-relative m-2 pt-1">
<span class="position-relative">Ещё &#9660;</span>
<div class="footer-menu">
<Link className="custom-link mb-1 p-1" href="#">Разработчикам</Link>
<Link className="custom-link mb-1 p-1" href="#">О нас</Link>
<Link className="custom-link mb-1 p-1" href="#">Правовая информация</Link>
<Link className="custom-link mb-1 p-1" href="#">Помощь</Link>
</div>
</div>
</div>
)
}

View File

@@ -0,0 +1,62 @@
export const Post = ({ post, onEdit, onDelete }) => {
const formatDate = (dateString) => {
const date = new Date(dateString);
const now = new Date();
const diffInHours = Math.floor((now - date) / (1000 * 60 * 60));
if (diffInHours < 24) {
return date.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
} else {
return date.toLocaleDateString([], { day: 'numeric', month: 'long' });
}
};
return (
<div className="post mb-3">
<div className="post-header mb-2 d-flex justify-content-between align-items-center">
<div>
<i className='bi bi-people'></i>
<label>{post.group}</label>
</div>
<div>
<button
className="btn btn-sm btn-outline-secondary me-1"
onClick={() => onEdit(post)}
>
<i className="bi bi-pencil"></i>
</button>
<button
className="btn btn-sm btn-outline-danger"
onClick={() => onDelete(post.id)}
>
<i className="bi bi-trash"></i>
</button>
</div>
</div>
{/* Блок с изображением */}
{post.image && (
<div className="image position-relative w-98 p-1 mb-2">
<img
src={post.image}
className="post-img w-100 h-100 object-fit-cover"
alt="Post content"
/>
</div>
)}
{/* Текст */}
{post.text && <div className="post-text mb-2 p-2">{post.text}</div>}
{/* Подвал */}
<div className="post-footer p-1">
<i className='bi bi-heart me-2'><span className="ms-1">{post.likes}</span></i>
<i className='bi bi-chat-left me-2'><span className="ms-1">{post.comments}</span></i>
<i className='bi bi-reply me-2'><span className="ms-1">{post.shares}</span></i>
</div>
<div className="mt-2">
{formatDate(post.createdAt)}
</div>
</div>
);
};

View File

@@ -0,0 +1,106 @@
import { useState, useRef } from 'react';
import 'bootstrap-icons/font/bootstrap-icons.css';
export const PostForm = ({ onSubmit, onCancel, initialData = {} }) => {
const [formData, setFormData] = useState({
text: initialData.text || '',
image: null,
imagePreview: initialData.image || ''
});
const fileInputRef = useRef(null);
const handleInputChange = (e) => {
setFormData({ ...formData, text: e.target.value });
};
const handleImageChange = (e) => {
const file = e.target.files[0];
if (file) {
const reader = new FileReader();
reader.onloadend = () => {
setFormData({
...formData,
image: file,
imagePreview: reader.result
});
};
reader.readAsDataURL(file);
}
};
const handleSubmit = (e) => {
e.preventDefault();
if (!formData.text && !formData.image) {
alert('Пост должен содержать текст или изображение');
return;
}
onSubmit(formData);
};
const triggerFileInput = () => {
fileInputRef.current.click();
};
return (
<div className="add-post-form mb-4 pb-3">
<h5>{initialData.id ? 'Редактировать пост' : 'Новый пост'}</h5>
<form onSubmit={handleSubmit}>
<div className="mb-3">
<textarea
className="form-control"
placeholder="Напишите что-нибудь..."
rows="3"
value={formData.text}
onChange={handleInputChange}
></textarea>
</div>
<div className="mb-3">
<button
type="button"
className="btn btn-outline-secondary"
onClick={triggerFileInput}
>
<i className="bi bi-image"></i> {formData.imagePreview ? 'Заменить изображение' : 'Выбрать изображение'}
</button>
<input
type="file"
ref={fileInputRef}
accept="image/*"
className="d-none"
onChange={handleImageChange}
/>
{formData.imagePreview && (
<div className="mt-2">
<img
src={formData.imagePreview}
className="img-thumbnail"
style={{ maxHeight: '200px' }}
alt="Превью"
/>
<button
type="button"
className="btn btn-sm btn-outline-danger ms-2"
onClick={() => setFormData({ ...formData, image: null, imagePreview: '' })}
>
<i className="bi bi-trash"></i>
</button>
</div>
)}
</div>
<div className="d-flex justify-content-between">
<button
type="button"
className="btn btn-outline-secondary"
onClick={onCancel}
>
Отмена
</button>
<button type="submit" className="btn btn-danger">
<i className="bi bi-send"></i> {initialData.id ? 'Обновить' : 'Опубликовать'}
</button>
</div>
</form>
</div>
);
};

View File

@@ -0,0 +1,27 @@
.custom-link:link {
color: white;
text-decoration: none;
}
.custom-link:visited {
color: white;
}
.custom-link:hover {
color: #BF1723;
background-color: #2a2a2a;
}
.custom-link:active {
color: #FCD116;
}
.rightbar {
height: 100%;
width: 10%;
background-color: #222222;
border-radius: 15px;
min-width: 150px;
}
.rightbar-content > a {
border-radius: 5px;
}

View File

@@ -0,0 +1,16 @@
import './Rightbar.css'
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap/dist/js/bootstrap.bundle.min';
import { Link } from 'react-router-dom';
export default function Rightbar() {
return(
<div class="rightbar d-none d-sm-flex m-1">
<div class="rightbar-content d-flex flex-column m-2">
<Link className="custom-link mb-1 p-1">Все</Link>
<Link className="custom-link mb-1 p-1">Непрочитанные</Link>
<Link className="custom-link mb-1 p-1">Архив</Link>
</div>
</div>
)
}

View File

@@ -0,0 +1,44 @@
import { useState, useEffect } from 'react';
import axios from 'axios';
const API_URL = 'http://localhost:3000/posts';
export default function usePosts() {
const [posts, setPosts] = useState([]);
const fetchPosts = async () => {
try {
const res = await axios.get(API_URL);
setPosts(res.data.sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)));
} catch (error) {
console.error('Ошибка при загрузке постов:', error);
}
};
const createPost = async (post) => {
await axios.post(API_URL, post);
fetchPosts();
};
const updatePost = async (id, data) => {
await axios.put(`${API_URL}/${id}`, data);
fetchPosts();
};
const deletePost = async (id) => {
await axios.delete(`${API_URL}/${id}`);
fetchPosts();
};
const likePost = async (id) => {
const post = posts.find(p => p.id === id);
await axios.put(`${API_URL}/${id}`, { ...post, likes: post.likes + 1 });
fetchPosts();
};
useEffect(() => {
fetchPosts();
}, []);
return { posts, createPost, updatePost, deletePost, likePost };
}

13
ИП6/111/src/index.css Normal file
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
ИП6/111/src/index.js Normal file
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
ИП6/111/src/logo.svg Normal file
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

View File

@@ -0,0 +1,113 @@
import React, { useState, useEffect } from 'react';
import { PostService } from '../services/PostService';
import { PostForm } from '../components/PostForm';
import { Post } from '../components/Post';
import Header from '../components/Header/Header';
import Leftbar from '../components/Leftbar/Leftbar';
import Rightbar from '../components/Rightbar/Rightbar';
import Bottombar from '../components/Bottombar/Bottombar';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
import './css/FeedPage.css';
const FeedPage = () => {const [posts, setPosts] = useState([]);
const [showForm, setShowForm] = useState(false);
const [editingPost, setEditingPost] = useState(null);
useEffect(() => {
const savedPosts = PostService.getPosts();
setPosts(savedPosts || PostService.getInitialPosts());
}, []);
useEffect(() => {
if (posts.length > 0) {
PostService.savePosts(posts);
}
}, [posts]);
const handleShowForm = () => {
setShowForm(true);
setEditingPost(null);
};
const handleSubmit = (formData) => {
const newPost = {
id: editingPost ? editingPost.id : Date.now(),
text: formData.text,
image: formData.image ? URL.createObjectURL(formData.image) : formData.imagePreview,
group: 'Моя группа',
likes: editingPost ? editingPost.likes : 0,
comments: editingPost ? editingPost.comments : 0,
shares: editingPost ? editingPost.shares : 0,
createdAt: editingPost ? editingPost.createdAt : new Date().toISOString()
};
if (editingPost) {
setPosts(posts.map(post => post.id === editingPost.id ? newPost : post));
} else {
setPosts([newPost, ...posts]);
}
setShowForm(false);
setEditingPost(null);
};
const handleEdit = (post) => {
setEditingPost(post);
setShowForm(true);
};
const handleDelete = (postId) => {
if (window.confirm('Вы уверены, что хотите удалить этот пост?')) {
setPosts(posts.filter(post => post.id !== postId));
}
};
return (
<div>
<header><Header /></header>
<main>
<section className='w-100'>
<div className="page d-flex justify-content-center mt-3">
<Leftbar />
<div className="content h-100 w-25 m-1 p-2 mb-5 d-flex flex-column justify-content-center">
<button
className="btn btn-danger add-post-btn m-3"
onClick={handleShowForm}
>
<i className="bi bi-plus-circle"></i> Добавить пост
</button>
{showForm && (
<PostForm
onSubmit={handleSubmit}
onCancel={() => setShowForm(false)}
initialData={editingPost || {}}
/>
)}
{posts.map(post => (
<Post
key={post.id}
post={post}
onEdit={handleEdit}
onDelete={handleDelete}
/>
))}
</div>
<Rightbar />
</div>
<Bottombar />
</section>
</main>
</div>
);
};
export default FeedPage;

View File

@@ -0,0 +1,58 @@
import React from 'react';
import { Link, useNavigate } from 'react-router-dom';
import HeaderAuth from '../components/HeaderAuth/HeaderAuth';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
import './css/LoginPage.css';
const LoginPage = () => {
return (
<div>
<header>
<HeaderAuth />
</header>
<section>
<div
className="container-fluid d-flex justify-content-center align-items-center"
style={{ height: 'calc(100vh - 200px)' }}
>
<div
className="login-page"
style={{ minWidth: 300, maxWidth: 400, width: '100%' }}
>
<form className="px-3">
<h1 className="text-center">Авторизация</h1>
<div className="input-div d-flex flex-column align-items-center mb-2">
<div className="input-box my-1">
<input type="text" placeholder="Логин" required />
<i className="bi bi-person"></i>
</div>
<div className="input-box my-1">
<input type="password" placeholder="Пароль" required />
<i className="bi bi-shield-lock"></i>
</div>
</div>
<div className="remember-forgot d-flex justify-content-evenly mb-2 px-2">
<label><input type="checkbox" /> Запомнить меня</label>
<a href="#">Забыли пароль?</a>
</div>
<button type="submit" className="btn w-100">Войти</button>
<div className="register-link d-flex justify-content-evenly align-items-center">
<p className="pt-3">У меня нет аккаунта</p>
<Link to="/signup">Зарегистрироваться</Link>
</div>
</form>
</div>
</div>
</section>
</div>
);
};
export default LoginPage;

View File

@@ -0,0 +1,42 @@
import React from 'react';
import Header from '../components/Header/Header';
import Leftbar from '../components/Leftbar/Leftbar';
import Rightbar from '../components/Rightbar/Rightbar';
import Bottombar from '../components/Bottombar/Bottombar';
import Chat from '../components/Chat/Chat';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
import './css/MessagePage.css';
import chatData from './chatData.json';
const MessagesPage = () => {
return (
<div>
<header><Header /></header>
<section>
<div class="page d-flex justify-content-center mt-3">
<Leftbar />
<div class="content h-100 w-25 m-1 p-2">
{chatData.map((chat, index) => (
<Chat
key={index}
username={chat.username}
message={chat.message}
avatarUrl={chat.avatarUrl}
/>
))}
</div>
<Rightbar />
</div>
<Bottombar />
</section>
</div>
);
};
export default MessagesPage;

View File

@@ -0,0 +1,12 @@
const NotFoundPage = () => {
return (
<div>
<p>404</p>
<p>Страница не найдена</p>
<p>Something went wrong</p>
</div>
);
};
export default NotFoundPage;

View File

@@ -0,0 +1,50 @@
import React from 'react';
import Header from '../components/Header/Header';
import Leftbar from '../components/Leftbar/Leftbar';
import Rightbar from '../components/Rightbar/Rightbar';
import Bottombar from '../components/Bottombar/Bottombar';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
import './css/ProfilePage.css';
const ProfilePage = () => {
return (
<div>
<header><Header /></header>
<section>
<div class="page d-flex justify-content-center mt-3">
<Leftbar />
<div class="profile-card d-flex flex-column align-items-center p-4">
<div class="imagep position-relative p-1 mb-2">
<img src="../images/photo.jpg" alt="" class="profile-img w-100 h-100 object-fit-cover" />
</div>
<div class="text-data d-flex flex-column align-items-center">
<span class="name">Павел Ладягин</span>
<span class="about">Краткая информация о себе</span>
</div>
<div class="more-info d-flex justify-content-between">
<div class="location">
<i class="bi bi-geo-alt"></i>
<label>Ульяновск</label>
</div>
<div class="education">
<i class="bi bi-buildings"></i>
<label>УлГТУ</label>
</div>
</div>
</div>
<Rightbar />
</div>
<Bottombar />
</section>
</div>
);
};
export default ProfilePage;

View File

@@ -0,0 +1,59 @@
import { Link, useNavigate } from 'react-router-dom';
import HeaderAuth from '../components/HeaderAuth/HeaderAuth';
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-icons/font/bootstrap-icons.css';
import './css/SignupPage.css';
const SignupPage = () => {
return (
<div>
<header>
<HeaderAuth />
</header>
<section>
<div className="container-fluid d-flex justify-content-center align-items-center" style={{ height: 'calc(100vh - 200px)' }}>
<div className="login-page" style={{ minWidth: 300, maxWidth: 400, width: '100%' }}>
<form className="px-3">
<h1 className="text-center">Авторизация</h1>
<div className="input-div d-flex flex-column align-items-center mb-2">
<div className="input-box my-1">
<input type="text" placeholder="Логин" />
<i className="bi bi-person"></i>
</div>
<div className="input-box my-1">
<input type="password" placeholder="Пароль" />
<i className="bi bi-shield-lock"></i>
</div>
<div className="input-box my-1">
<input type="password" placeholder="Подтвердите пароль" />
<i className="bi bi-shield-lock"></i>
</div>
<div className="input-box my-1">
<input type="text" placeholder="Почта" />
<i className="bi bi-envelope"></i>
</div>
</div>
<div className="remember-forgot d-flex justify-content-evenly mb-2 px-2">
<label><input type="checkbox" /> Запомнить меня</label>
<a href="#">Забыли пароль?</a>
</div>
<button type="submit" className="btn w-100">Войти</button>
<div className="register-link d-flex justify-content-evenly align-items-center">
<p className="pt-3">У меня есть аккаунт</p>
<Link to="/">Войти</Link>
</div>
</form>
</div>
</div>
</section>
</div>
);
};
export default SignupPage;

View File

@@ -0,0 +1,29 @@
[
{
"username": "Иван Иванов",
"message": "Сделал вторую лабу",
"avatarUrl": "../images/photo.jpg"
},
{
"username": "Мария Петрова",
"message": "Привет, как дела?",
"avatarUrl": "../images/meme1.jpg"
},
{
"username": "Алексей Смирнов",
"message": "Готовлюсь к экзамену",
"avatarUrl": "../images/meme2.jpg"
},
{
"username": "Елена Васильева",
"message": "Жду feedback по проекту",
"avatarUrl": "../images/logo.svg"
},
{
"username": "Елена Васильева11111",
"message": "Жду feedback по проекту",
"avatarUrl": "../images/profile-icon.svg"
}
]

View File

@@ -0,0 +1,90 @@
body {
color: #c5c6c7;
background-color: #141414;
}
img {
width: 50px;
}
li {
list-style: none;
}
.content {
background-color: #222222;
border-radius: 15px;
border: 0.1px solid #BF1723;
min-width: 250px;
}
.post-header {
color: #fff;
border-top: 0.5px solid #BF1723;
padding-top: 3%;
}
.image .post-img {
border-radius: 2%;
}
.post-footer {
color: #fff;
}
/*Форма для добавления*/
.formContainer{
border: 1px solid #ccc;
border-radius: 5px;
background-color: #f9f9f9;
max-width: 300px;
}
/* Обновлённые стили для кнопок управления постом */
.post-header {
display: flex;
align-items: center;
gap: 8px;
}
.post-actions {
margin-left: auto;
display: flex;
gap: 5px;
}
.post-actions button {
font-size: 0.8rem;
padding: 0.1rem 0.4rem;
}
/* Стили для изображений */
.image-preview {
max-width: 100%;
max-height: 200px;
margin-top: 10px;
display: none;
border-radius: 8px;
}
.post-img {
border-radius: 8px;
object-fit: cover;
}
.like-btn {
cursor: pointer;
transition: color 0.2s;
}
.like-btn.text-danger {
color: #dc3545 !important;
}

View File

@@ -0,0 +1,73 @@
body {
color: #c5c6c7;
background-color: #0b0c10;
}
/* Шапка */
header .container-fluid {
border-bottom: 3px solid #BF1723;
border-bottom-right-radius: 25px;
border-bottom-left-radius: 25px;
}
.first-part {
color:#FCD116;
font-size: 1.4em;
}
.last-part {
color: #BF1723;
font-size: 1.5em;
}
.right-part > nav > ul > li > a {
border: 0.5px solid #FFF;
border-radius: 10px;
}
/* Блок регистрации */
.login-page {
background-color: #222222;
border-radius: 15%;
border: 0.5px solid #BF1723;
color: #FFF;
}
.remember-forgot label input {
accent-color: #BF1723;
}
.login-page .btn {
background-color: #BF1723;
border-radius: 10px;
color: #fff;
}
.input-box input {
border-radius: 4px;
}
.input-box input:focus {
border-color: #BF1723;
outline: none;
}
/* Ссылки */
a {
outline: none;
text-decoration: none;
}
a:link{
color: #FCD116;
}
a:visited{
color: #FCD116;
}
a:hover{
color: #c5c6c7;
}

View File

@@ -0,0 +1,23 @@
body {
color: #c5c6c7;
background-color: #141414;
}
img {
width: 50px;
}
li {
list-style: none;
}
.content {
background-color: #222222;
border-radius: 15px;
border: 0.1px solid #BF1723;
min-width: 250px;
}

View File

@@ -0,0 +1,54 @@
* {
box-sizing: border-box;
}
body {
color: #c5c6c7;
background-color: #141414;
margin: 0px;
}
img {
width: 50px;
}
li {
list-style: none;
}
.profile-card {
max-width: 250px;
width: 100%;
background-color: #222222;
border-radius: 25px;
}
.imagep {
width: 150px;
height: 150px;
border-radius: 50%;
background-color: #FCD116;
}
.imagep .profile-img {
border-radius: 50%;
border: 3px solid #FFF;
}
.text-data .name {
font-size: 22px;
font-weight: 500;
color: #fff;
}
.text-data .about {
font-size: 15px;
font-weight: 400;
color: #fff;
margin-bottom: 10px;
}
.profile-card .more-info {
width: 90%;
}

View File

@@ -0,0 +1,73 @@
body {
color: #c5c6c7;
background-color: #0b0c10;
}
/* Шапка */
header .container-fluid {
border-bottom: 3px solid #BF1723;
border-bottom-right-radius: 25px;
border-bottom-left-radius: 25px;
}
.first-part {
color:#FCD116;
font-size: 1.4em;
}
.last-part {
color: #BF1723;
font-size: 1.5em;
}
.right-part > nav > ul > li > a {
border: 0.5px solid #FFF;
border-radius: 10px;
}
/* Блок регистрации */
.login-page {
background-color: #222222;
border-radius: 15%;
border: 0.5px solid #BF1723;
color: #FFF;
}
.remember-forgot label input {
accent-color: #BF1723;
}
.login-page .btn {
background-color: #BF1723;
border-radius: 10px;
color: #fff;
}
.input-box input {
border-radius: 4px;
}
.input-box input:focus {
border-color: #BF1723;
outline: none;
}
/* Ссылки */
a {
outline: none;
text-decoration: none;
}
a:link{
color: #FCD116;
}
a:visited{
color: #FCD116;
}
a:hover{
color: #c5c6c7;
}

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;

View File

@@ -0,0 +1,38 @@
export class PostService {
static STORAGE_KEY = 'posts';
static getPosts() {
const savedPosts = localStorage.getItem(this.STORAGE_KEY);
return savedPosts ? JSON.parse(savedPosts) : null;
}
static savePosts(posts) {
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(posts));
}
static getInitialPosts() {
const now = Date.now();
return [
{
id: 1,
text: '',
image: 'source/meme1.jpg',
group: 'Какая-то группа 1',
likes: 8,
comments: 2,
shares: 1,
createdAt: new Date(now - 86400000 * 2).toISOString()
},
{
id: 2,
text: '',
image: 'src/assets/meme2.jpg',
group: 'Какая-то группа 2',
likes: 785,
comments: 102,
shares: 14,
createdAt: new Date(now - 86400000 * 2).toISOString()
}
];
}
}

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';

BIN
ИП6/Отчет_6.docx Normal file

Binary file not shown.