Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 351c7059d2 | |||
| e41837a562 | |||
| 24c99f755e | |||
| f33c05ad5e | |||
| caeac1915e | |||
| abb300df17 | |||
| fe7f5d1791 | |||
| 42c03b50d8 | |||
| 000d7a9f67 | |||
| 8b911b537a | |||
| a96c3a9400 | |||
| bf17f58884 | |||
| 681580cd60 |
17
.eslintrc.json
Normal file
17
.eslintrc.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended"
|
||||||
|
],
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaVersion": "latest",
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"rules": {
|
||||||
|
"no-unused-vars": "warn",
|
||||||
|
"no-console": "warn"
|
||||||
|
}
|
||||||
|
}
|
||||||
34
.gitignore
vendored
34
.gitignore
vendored
@@ -1,14 +1,24 @@
|
|||||||
# ---> VisualStudioCode
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
.vscode/*
|
.vscode/*
|
||||||
!.vscode/settings.json
|
|
||||||
!.vscode/tasks.json
|
|
||||||
!.vscode/launch.json
|
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
!.vscode/*.code-snippets
|
.idea
|
||||||
|
.DS_Store
|
||||||
# Local History for Visual Studio Code
|
*.suo
|
||||||
.history/
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
# Built Visual Studio Code Extensions
|
*.sln
|
||||||
*.vsix
|
*.sw?
|
||||||
|
|
||||||
|
|||||||
7
.prettierrc
Normal file
7
.prettierrc
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"printWidth": 100
|
||||||
|
}
|
||||||
41
db.json
Normal file
41
db.json
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"events": [
|
||||||
|
{
|
||||||
|
"title": "New World VR",
|
||||||
|
"description": "Абсолютно новый формат шоу! Погружение в совершенно новый мир.",
|
||||||
|
"imageUrl": "https://imagesbase.ru/uploads/posts/2019-12/1576879346_imagesbase.ru.png",
|
||||||
|
"categoryId": 1,
|
||||||
|
"typeId": 1,
|
||||||
|
"id": 1
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"categories": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Музыка"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Киберспорт"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "Искусство"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Концерт"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Стрим"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "Фестиваль"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
13
index.html
Normal file
13
index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
3938
package-lock.json
generated
Normal file
3938
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
package.json
Normal file
26
package.json
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "streamcore",
|
||||||
|
"private": true,
|
||||||
|
"version": "1.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview",
|
||||||
|
"lint": "eslint . --ext .js,.html --fix",
|
||||||
|
"format": "prettier --write .",
|
||||||
|
"server": "json-server --watch db.json --port 3001",
|
||||||
|
"dev:full": "concurrently \"npm run server\" \"npm run dev\""
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"concurrently": "^8.2.0",
|
||||||
|
"eslint": "^8.0.0",
|
||||||
|
"json-server": "^0.17.4",
|
||||||
|
"prettier": "^3.0.0",
|
||||||
|
"vite": "^7.1.9"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^5.3.0",
|
||||||
|
"bootstrap-icons": "^1.11.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
public/vite.svg
Normal file
1
public/vite.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
9
src/counter.js
Normal file
9
src/counter.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export function setupCounter(element) {
|
||||||
|
let counter = 0
|
||||||
|
const setCounter = (count) => {
|
||||||
|
counter = count
|
||||||
|
element.innerHTML = `count is ${counter}`
|
||||||
|
}
|
||||||
|
element.addEventListener('click', () => setCounter(counter + 1))
|
||||||
|
setCounter(0)
|
||||||
|
}
|
||||||
746
src/css/custom.css
Normal file
746
src/css/custom.css
Normal file
@@ -0,0 +1,746 @@
|
|||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Orbitron', sans-serif;
|
||||||
|
background-color: #0d0d0d;
|
||||||
|
color: #ddd;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
background: #000000;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
border-bottom: 2px solid #ff00ff;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 2000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
color: #00ffff;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-nav {
|
||||||
|
list-style: none;
|
||||||
|
display: flex;
|
||||||
|
gap: 2rem;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-nav .nav-link {
|
||||||
|
color: #ff00ff;
|
||||||
|
text-decoration: none;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
user-select: none;
|
||||||
|
text-shadow: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-nav .nav-link:hover,
|
||||||
|
.navbar-nav .nav-link:focus {
|
||||||
|
color: #00ffff;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
padding: 4rem 2rem;
|
||||||
|
border-bottom: 1px solid #222;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page h1,
|
||||||
|
.page h2 {
|
||||||
|
color: #ff00ff;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page p {
|
||||||
|
max-width: 800px;
|
||||||
|
line-height: 1.6;
|
||||||
|
color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.features-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
margin-top: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item {
|
||||||
|
background: #111;
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 0 8px #ff00ff;
|
||||||
|
transition: box-shadow 0.3s ease;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item:hover {
|
||||||
|
box-shadow: 0 0 15px #ff00ff, 0 0 25px #00fff7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #ff00ff;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item p {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
color: #ccc;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item button {
|
||||||
|
background: #ff00ff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px 18px;
|
||||||
|
color: #111;
|
||||||
|
font-weight: 600;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 0 10px #ff00ff;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: auto;
|
||||||
|
text-align: center;
|
||||||
|
min-height: 42px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.feature-item button:hover {
|
||||||
|
background: #00ffff;
|
||||||
|
box-shadow: 0 0 15px #00ffff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
background: #111;
|
||||||
|
border-top: 3px solid #00ffff;
|
||||||
|
padding: 2rem 1rem;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
text-align: center;
|
||||||
|
color: #00ffff;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer-info p {
|
||||||
|
margin: 0.4rem 0;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-icons {
|
||||||
|
margin-top: 1rem;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.social-icons a i {
|
||||||
|
color: #ff00ff;
|
||||||
|
transition: color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* КАТАЛОГ - ОСНОВНЫЕ СТИЛИ */
|
||||||
|
.catalog-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-item {
|
||||||
|
width: 100%;
|
||||||
|
background: #111;
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 20px;
|
||||||
|
box-shadow: 0 0 12px #ff00ff88;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 20px;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-item img {
|
||||||
|
width: 200px;
|
||||||
|
height: 120px;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 5px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-item-content {
|
||||||
|
flex-grow: 1;
|
||||||
|
padding-right: 140px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ИСПРАВЛЕННЫЕ СТИЛИ ДЛЯ КНОПКИ "СМОТРЕТЬ" */
|
||||||
|
.catalog-item .catalog-btn {
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
bottom: 20px;
|
||||||
|
background-color: #ff00ff;
|
||||||
|
border: none;
|
||||||
|
padding: 12px 30px;
|
||||||
|
color: #111;
|
||||||
|
font-weight: 600;
|
||||||
|
font-size: 1.1em;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
min-width: 120px;
|
||||||
|
text-align: center;
|
||||||
|
box-shadow: 0 0 12px #ff00ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-item .catalog-btn:hover {
|
||||||
|
background-color: #00ffff;
|
||||||
|
transform: scale(1.05);
|
||||||
|
box-shadow: 0 0 15px #00ffff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* КНОПКИ УПРАВЛЕНИЯ MVC КОМПОНЕНТА */
|
||||||
|
.event-actions {
|
||||||
|
position: absolute;
|
||||||
|
right: 20px;
|
||||||
|
top: 20px;
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-edit, .btn-delete {
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
color: #ff00ff;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 14px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-edit:hover {
|
||||||
|
background: #ff00ff;
|
||||||
|
color: #000;
|
||||||
|
box-shadow: 0 0 10px #ff00ff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-delete:hover {
|
||||||
|
background: #ff4444;
|
||||||
|
border-color: #ff4444;
|
||||||
|
color: #000;
|
||||||
|
box-shadow: 0 0 10px #ff4444;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Кнопка добавления события */
|
||||||
|
.btn-neon {
|
||||||
|
background-color: #ff00ff;
|
||||||
|
border: none;
|
||||||
|
color: #111;
|
||||||
|
font-weight: 700;
|
||||||
|
padding: 12px 24px;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 0 10px #ff00ff;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
font-size: 16px;
|
||||||
|
display: inline-block;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-neon:hover {
|
||||||
|
background-color: #00ffff;
|
||||||
|
box-shadow: 0 0 14px #00ffff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Форма добавления события */
|
||||||
|
.add-form {
|
||||||
|
background: #111;
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 2rem;
|
||||||
|
box-shadow: 0 0 12px #ff00ff88;
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.add-form h3 {
|
||||||
|
color: #00ffff;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
background: #222;
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
color: #eee;
|
||||||
|
box-shadow: 0 0 10px #ff00ff88 inset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control:focus {
|
||||||
|
background: #222;
|
||||||
|
border-color: #00ffff;
|
||||||
|
box-shadow: 0 0 10px #00ffff88 inset;
|
||||||
|
color: #eee;
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control::placeholder {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-select option:first-child {
|
||||||
|
color: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Модальное окно формы */
|
||||||
|
.event-form-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 3000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-form-modal {
|
||||||
|
background: #111;
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 2rem;
|
||||||
|
width: 90%;
|
||||||
|
max-width: 600px;
|
||||||
|
box-shadow: 0 0 20px #ff00ff88;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-form-modal h3 {
|
||||||
|
color: #00ffff;
|
||||||
|
margin-bottom: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-group label {
|
||||||
|
color: #ff00ff;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-actions {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
justify-content: flex-end;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ОДНОТОННАЯ КНОПКА СОХРАНИТЬ */
|
||||||
|
.btn-primary {
|
||||||
|
background: #ff00ff;
|
||||||
|
border: none;
|
||||||
|
color: #000;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background: #e000e0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary {
|
||||||
|
background: #333;
|
||||||
|
border: 1px solid #666;
|
||||||
|
color: #ddd;
|
||||||
|
padding: 10px 20px;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-secondary:hover {
|
||||||
|
background: #444;
|
||||||
|
border-color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Стили для модального окна просмотра изображения */
|
||||||
|
.image-modal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(0, 0, 0, 0.9);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 4000;
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-modal {
|
||||||
|
position: relative;
|
||||||
|
background: #111;
|
||||||
|
border: 3px solid #ff00ff;
|
||||||
|
border-radius: 15px;
|
||||||
|
max-width: 90vw;
|
||||||
|
max-height: 90vh;
|
||||||
|
box-shadow: 0 0 30px #ff00ff88;
|
||||||
|
animation: modalAppear 0.3s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes modalAppear {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0.8);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-modal-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 15px;
|
||||||
|
right: 15px;
|
||||||
|
background: rgba(0, 0, 0, 0.8);
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
color: #ff00ff;
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
border-radius: 50%;
|
||||||
|
cursor: pointer;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 18px;
|
||||||
|
z-index: 10;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-modal-close:hover {
|
||||||
|
background: #ff00ff;
|
||||||
|
color: #000;
|
||||||
|
box-shadow: 0 0 15px #ff00ff;
|
||||||
|
transform: scale(1.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-modal-content {
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
max-height: 80vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-modal-content img {
|
||||||
|
max-width: 100%;
|
||||||
|
max-height: 70vh;
|
||||||
|
object-fit: contain;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 20px rgba(255, 0, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-modal-caption {
|
||||||
|
margin-top: 15px;
|
||||||
|
color: #00ffff;
|
||||||
|
font-weight: 600;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.1em;
|
||||||
|
text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Стили для остальных страниц */
|
||||||
|
.streams-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
|
||||||
|
gap: 2rem;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-item {
|
||||||
|
background: #111;
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 1rem;
|
||||||
|
box-shadow: 0 0 12px #ff00ff88;
|
||||||
|
transition: box-shadow 0.3s ease;
|
||||||
|
user-select: none;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-item:hover {
|
||||||
|
box-shadow: 0 0 20px #00ffffdd;
|
||||||
|
border-color: #00ffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-item img {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
box-shadow: 0 0 8px #ff00ffaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-item h3 {
|
||||||
|
margin: 0 0 0.5rem;
|
||||||
|
color: #ff00ff;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-item p {
|
||||||
|
color: #aaa;
|
||||||
|
font-size: 0.95rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-item button {
|
||||||
|
background-color: #ff00ff;
|
||||||
|
border: none;
|
||||||
|
padding: 0.5rem 1.2rem;
|
||||||
|
color: #111;
|
||||||
|
font-weight: 700;
|
||||||
|
border-radius: 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 0 10px #ff00ff;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
margin-top: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stream-item button:hover {
|
||||||
|
background-color: #00ffff;
|
||||||
|
box-shadow: 0 0 14px #00ffff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-container {
|
||||||
|
background: #111;
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 2rem;
|
||||||
|
box-shadow: 0 0 12px #ff00ff88;
|
||||||
|
transition: box-shadow 0.3s ease;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-avatar img {
|
||||||
|
border-radius: 50%;
|
||||||
|
border: 3px solid #00ffff;
|
||||||
|
width: 150px;
|
||||||
|
height: 150px;
|
||||||
|
object-fit: cover;
|
||||||
|
box-shadow: 0 0 12px #00ffffaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-info {
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-info h2 span {
|
||||||
|
color: #ff00ff;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-info p {
|
||||||
|
font-size: 1.1rem;
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-edit-profile {
|
||||||
|
margin-top: 1rem;
|
||||||
|
background-color: #ff00ff;
|
||||||
|
border: none;
|
||||||
|
padding: 0.7rem 1.4rem;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #111;
|
||||||
|
border-radius: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
box-shadow: 0 0 12px #ff00ff;
|
||||||
|
transition: background-color 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-edit-profile:hover {
|
||||||
|
background-color: #00ffff;
|
||||||
|
box-shadow: 0 0 16px #00ffff;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-page {
|
||||||
|
max-width: 900px;
|
||||||
|
margin: 3rem auto;
|
||||||
|
padding: 0 1rem;
|
||||||
|
color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-page h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
color: #ff00ff;
|
||||||
|
text-align: center;
|
||||||
|
text-shadow: none;
|
||||||
|
margin-bottom: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-section {
|
||||||
|
background: #111;
|
||||||
|
border: 2px solid #ff00ff;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 2rem;
|
||||||
|
box-shadow: 0 0 12px #ff00ff88;
|
||||||
|
transition: box-shadow 0.3s ease;
|
||||||
|
user-select: none;
|
||||||
|
margin: 2rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-section h2 {
|
||||||
|
font-size: 2rem;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
color: #00ffff;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-section p,
|
||||||
|
.about-section ul {
|
||||||
|
font-size: 1.15rem;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-section ul {
|
||||||
|
padding-left: 1.3rem;
|
||||||
|
list-style-type: square;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-section ul li {
|
||||||
|
margin-bottom: 0.7rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* АДАПТИВНОСТЬ */
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.navbar-nav {
|
||||||
|
position: fixed;
|
||||||
|
top: 60px;
|
||||||
|
right: 0;
|
||||||
|
background: #111;
|
||||||
|
width: 100%;
|
||||||
|
max-height: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
flex-direction: column;
|
||||||
|
padding: 0 2rem;
|
||||||
|
transition: max-height 0.35s ease;
|
||||||
|
box-shadow: 0 10px 30px #ff00ffaa;
|
||||||
|
border-bottom: 2px solid #ff00ff;
|
||||||
|
z-index: 2000;
|
||||||
|
user-select: none;
|
||||||
|
border-radius: 0 0 10px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-collapse.show .navbar-nav {
|
||||||
|
max-height: 300px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-nav .nav-link {
|
||||||
|
color: #ff66ff;
|
||||||
|
padding: 1rem 0;
|
||||||
|
border-bottom: 1px solid #ff00ff33;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-nav .nav-link:hover,
|
||||||
|
.navbar-nav .nav-link:focus {
|
||||||
|
color: #33ffff;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 600px) {
|
||||||
|
.catalog-item {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding-bottom: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-item img {
|
||||||
|
width: 100%;
|
||||||
|
height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-item-content {
|
||||||
|
padding-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.catalog-item .catalog-btn {
|
||||||
|
right: 20px;
|
||||||
|
bottom: 20px;
|
||||||
|
left: 20px;
|
||||||
|
width: auto;
|
||||||
|
padding: 14px 30px;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-actions {
|
||||||
|
right: 15px;
|
||||||
|
top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-container {
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-info {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-page {
|
||||||
|
margin: 1.5rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-page h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about-section h2 {
|
||||||
|
font-size: 1.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.image-modal {
|
||||||
|
max-width: 95vw;
|
||||||
|
max-height: 95vh;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/javascript.svg
Normal file
1
src/javascript.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#F7DF1E" d="M0 0h256v256H0V0Z"></path><path d="m67.312 213.932l19.59-11.856c3.78 6.701 7.218 12.371 15.465 12.371c7.905 0 12.89-3.092 12.89-15.12v-81.798h24.057v82.138c0 24.917-14.606 36.259-35.916 36.259c-19.245 0-30.416-9.967-36.087-21.996m85.07-2.576l19.588-11.341c5.157 8.421 11.859 14.607 23.715 14.607c9.969 0 16.325-4.984 16.325-11.858c0-8.248-6.53-11.17-17.528-15.98l-6.013-2.58c-17.357-7.387-28.87-16.667-28.87-36.257c0-18.044 13.747-31.792 35.228-31.792c15.294 0 26.292 5.328 34.196 19.247l-18.732 12.03c-4.125-7.389-8.591-10.31-15.465-10.31c-7.046 0-11.514 4.468-11.514 10.31c0 7.217 4.468 10.14 14.778 14.608l6.014 2.577c20.45 8.765 31.963 17.7 31.963 37.804c0 21.654-17.012 33.51-39.867 33.51c-22.339 0-36.774-10.654-43.819-24.574"></path></svg>
|
||||||
|
After Width: | Height: | Size: 995 B |
482
src/js/catalog-mvc-bundle.js
Normal file
482
src/js/catalog-mvc-bundle.js
Normal file
@@ -0,0 +1,482 @@
|
|||||||
|
console.log('🔧 catalog-mvc-bundle.js загружен');
|
||||||
|
|
||||||
|
// EventModel
|
||||||
|
class EventModel {
|
||||||
|
constructor() {
|
||||||
|
this.apiUrl = 'http://localhost:3001';
|
||||||
|
console.log('📊 Model создана');
|
||||||
|
}
|
||||||
|
|
||||||
|
async getAllEvents() {
|
||||||
|
try {
|
||||||
|
console.log('📊 Запрос событий к API...');
|
||||||
|
const response = await fetch(`${this.apiUrl}/events`);
|
||||||
|
const events = await response.json();
|
||||||
|
console.log('✅ События получены:', events.length);
|
||||||
|
return events;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Ошибка получения событий:', error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getEventById(id) {
|
||||||
|
try {
|
||||||
|
console.log('📊 Запрос события по ID:', id);
|
||||||
|
const response = await fetch(`${this.apiUrl}/events/${id}`);
|
||||||
|
const event = await response.json();
|
||||||
|
console.log('✅ Событие получено:', event);
|
||||||
|
return event;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Ошибка получения события:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createEvent(eventData) {
|
||||||
|
try {
|
||||||
|
console.log('📤 Создание события:', eventData);
|
||||||
|
const response = await fetch(`${this.apiUrl}/events`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(eventData)
|
||||||
|
});
|
||||||
|
const newEvent = await response.json();
|
||||||
|
console.log('✅ Событие создано:', newEvent);
|
||||||
|
return newEvent;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Ошибка создания события:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateEvent(id, eventData) {
|
||||||
|
try {
|
||||||
|
console.log('📝 Обновление события:', id, eventData);
|
||||||
|
const response = await fetch(`${this.apiUrl}/events/${id}`, {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(eventData)
|
||||||
|
});
|
||||||
|
const updatedEvent = await response.json();
|
||||||
|
console.log('✅ Событие обновлено:', updatedEvent);
|
||||||
|
return updatedEvent;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Ошибка обновления события:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteEvent(id) {
|
||||||
|
try {
|
||||||
|
console.log('🗑️ Удаление события:', id);
|
||||||
|
const response = await fetch(`${this.apiUrl}/events/${id}`, {
|
||||||
|
method: 'DELETE'
|
||||||
|
});
|
||||||
|
console.log('✅ Событие удалено');
|
||||||
|
return response.ok;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Ошибка удаления:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// EventView
|
||||||
|
class EventView {
|
||||||
|
constructor() {
|
||||||
|
this.container = null;
|
||||||
|
console.log('🎨 View создана');
|
||||||
|
}
|
||||||
|
|
||||||
|
initialize(containerId) {
|
||||||
|
this.container = document.getElementById(containerId);
|
||||||
|
if (!this.container) {
|
||||||
|
console.error('❌ Контейнер не найден:', containerId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
console.log('✅ View инициализирована с контейнером:', containerId);
|
||||||
|
|
||||||
|
this.addControlsToExistingCards();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Добавляем метод для привязки события просмотра изображения
|
||||||
|
bindViewImageEvent() {
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
// Обрабатываем клик по кнопке "Смотреть" или "catalog-btn"
|
||||||
|
if (e.target.closest('.catalog-btn') ||
|
||||||
|
(e.target.textContent === 'Смотреть' && e.target.classList.contains('btn'))) {
|
||||||
|
|
||||||
|
const card = e.target.closest('.catalog-item');
|
||||||
|
if (card) {
|
||||||
|
const img = card.querySelector('img');
|
||||||
|
if (img && img.src) {
|
||||||
|
console.log('👁️ Просмотр изображения:', img.src);
|
||||||
|
this.showImageModal(img.src, img.alt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Метод для показа модального окна с изображением
|
||||||
|
showImageModal(imageSrc, imageAlt) {
|
||||||
|
const modalHTML = `
|
||||||
|
<div class="image-modal-overlay">
|
||||||
|
<div class="image-modal">
|
||||||
|
<button class="image-modal-close">
|
||||||
|
<i class="bi bi-x-lg"></i>
|
||||||
|
</button>
|
||||||
|
<div class="image-modal-content">
|
||||||
|
<img src="${imageSrc}" alt="${imageAlt}" />
|
||||||
|
<div class="image-modal-caption">${imageAlt}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.insertAdjacentHTML('beforeend', modalHTML);
|
||||||
|
|
||||||
|
// Добавляем обработчики событий для закрытия
|
||||||
|
const overlay = document.querySelector('.image-modal-overlay');
|
||||||
|
const closeBtn = document.querySelector('.image-modal-close');
|
||||||
|
|
||||||
|
const closeModal = () => {
|
||||||
|
overlay.remove();
|
||||||
|
document.removeEventListener('keydown', handleEscape);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEscape = (e) => {
|
||||||
|
if (e.key === 'Escape') {
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
overlay.addEventListener('click', (e) => {
|
||||||
|
if (e.target === overlay) {
|
||||||
|
closeModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
closeBtn.addEventListener('click', closeModal);
|
||||||
|
document.addEventListener('keydown', handleEscape);
|
||||||
|
|
||||||
|
// Фокусируем на кнопке закрытия для доступности
|
||||||
|
closeBtn.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
addControlsToExistingCards() {
|
||||||
|
const existingCards = this.container.querySelectorAll('.catalog-item');
|
||||||
|
console.log('🎯 Найдено карточек для добавления кнопок:', existingCards.length);
|
||||||
|
|
||||||
|
existingCards.forEach((card, index) => {
|
||||||
|
const oldActions = card.querySelector('.event-actions');
|
||||||
|
if (oldActions) oldActions.remove();
|
||||||
|
|
||||||
|
const actionsDiv = document.createElement('div');
|
||||||
|
actionsDiv.className = 'event-actions';
|
||||||
|
actionsDiv.innerHTML = `
|
||||||
|
<button class="btn-edit" data-id="static-${index + 1}">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn-delete" data-id="static-${index + 1}">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
card.appendChild(actionsDiv);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEventList(events) {
|
||||||
|
console.log('🎨 Отрисовываем события из API:', events.length);
|
||||||
|
|
||||||
|
// Очищаем только динамически добавленные события
|
||||||
|
const dynamicEvents = this.container.querySelectorAll('.catalog-item[data-id]:not([data-id^="static-"])');
|
||||||
|
dynamicEvents.forEach(event => event.remove());
|
||||||
|
|
||||||
|
events.forEach(event => {
|
||||||
|
const eventElement = this.createEventElement(event);
|
||||||
|
this.container.appendChild(eventElement);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createEventElement(event) {
|
||||||
|
const eventDiv = document.createElement('article');
|
||||||
|
eventDiv.className = 'catalog-item';
|
||||||
|
eventDiv.dataset.id = event.id;
|
||||||
|
|
||||||
|
eventDiv.innerHTML = `
|
||||||
|
<img src="${event.imageUrl}" alt="${event.title}" />
|
||||||
|
<div class="catalog-item-content">
|
||||||
|
<h3>${event.title}</h3>
|
||||||
|
<p>${event.description}</p>
|
||||||
|
<small class="text-muted">ID: ${event.id}</small>
|
||||||
|
</div>
|
||||||
|
<button class="catalog-btn">Смотреть</button>
|
||||||
|
<div class="event-actions">
|
||||||
|
<button class="btn-edit" data-id="${event.id}">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn-delete" data-id="${event.id}">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
return eventDiv;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderEventForm(event = null) {
|
||||||
|
console.log('📋 Рендерим форму события:', event ? 'редактирование' : 'создание');
|
||||||
|
|
||||||
|
const isEdit = !!event;
|
||||||
|
const formTitle = isEdit ? 'Редактировать событие' : 'Добавить событие';
|
||||||
|
const submitText = isEdit ? 'Сохранить' : 'Создать';
|
||||||
|
|
||||||
|
const formHTML = `
|
||||||
|
<div class="event-form-overlay">
|
||||||
|
<div class="event-form-modal">
|
||||||
|
<h3>${formTitle}</h3>
|
||||||
|
<form id="eventForm" data-event-id="${event ? event.id : ''}">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="eventTitle">Название события</label>
|
||||||
|
<input type="text" id="eventTitle" class="form-control"
|
||||||
|
placeholder="Введите название" minlength="1" maxlength="50"
|
||||||
|
value="${event ? event.title : ''}" required>
|
||||||
|
<small class="text-muted">От 1 до 50 символов</small>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="eventDescription">Описание</label>
|
||||||
|
<textarea id="eventDescription" class="form-control" rows="3"
|
||||||
|
placeholder="Введите описание" required>${event ? event.description : ''}</textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="eventImage">Ссылка на изображение</label>
|
||||||
|
<input type="url" id="eventImage" class="form-control"
|
||||||
|
placeholder="https://example.com/image.jpg"
|
||||||
|
value="${event ? event.imageUrl : ''}" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-actions">
|
||||||
|
<button type="button" class="btn btn-secondary" id="cancelBtn">Отмена</button>
|
||||||
|
<button type="submit" class="btn btn-primary">${submitText}</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
document.body.insertAdjacentHTML('beforeend', formHTML);
|
||||||
|
return document.getElementById('eventForm');
|
||||||
|
}
|
||||||
|
|
||||||
|
removeEventForm() {
|
||||||
|
const overlay = document.querySelector('.event-form-overlay');
|
||||||
|
if (overlay) overlay.remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
bindEditEvent(handler) {
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (e.target.closest('.btn-edit')) {
|
||||||
|
const id = e.target.closest('.btn-edit').dataset.id;
|
||||||
|
console.log('✏️ Редактирование:', id);
|
||||||
|
handler(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bindDeleteEvent(handler) {
|
||||||
|
document.addEventListener('click', (e) => {
|
||||||
|
if (e.target.closest('.btn-delete')) {
|
||||||
|
const id = e.target.closest('.btn-delete').dataset.id;
|
||||||
|
console.log('🗑️ Удаление:', id);
|
||||||
|
handler(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class EventController {
|
||||||
|
constructor(containerId) {
|
||||||
|
this.model = new EventModel();
|
||||||
|
this.view = new EventView();
|
||||||
|
this.containerId = containerId;
|
||||||
|
console.log('🎯 Controller создан');
|
||||||
|
}
|
||||||
|
|
||||||
|
async initialize() {
|
||||||
|
console.log('🎯 Инициализация MVC компонента...');
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.view.initialize(this.containerId);
|
||||||
|
console.log('✅ View инициализирована');
|
||||||
|
|
||||||
|
await this.loadEvents();
|
||||||
|
console.log('✅ События загружены');
|
||||||
|
|
||||||
|
this.bindEvents();
|
||||||
|
console.log('✅ Обработчики настроены');
|
||||||
|
|
||||||
|
console.log('🎉 MVC компонент полностью инициализирован');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('💥 Ошибка инициализации:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadEvents() {
|
||||||
|
const events = await this.model.getAllEvents();
|
||||||
|
this.view.renderEventList(events);
|
||||||
|
}
|
||||||
|
|
||||||
|
bindEvents() {
|
||||||
|
const addBtn = document.getElementById('addEventBtn');
|
||||||
|
console.log('🔍 Кнопка добавления:', !!addBtn);
|
||||||
|
|
||||||
|
if (addBtn) {
|
||||||
|
addBtn.addEventListener('click', () => {
|
||||||
|
console.log('🎯 Кнопка "Добавить событие" нажата!');
|
||||||
|
this.showEventForm();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.view.bindEditEvent((id) => {
|
||||||
|
if (id.startsWith('static-')) {
|
||||||
|
this.showStaticEditForm(id);
|
||||||
|
} else {
|
||||||
|
this.showEditForm(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.view.bindDeleteEvent((id) => {
|
||||||
|
if (id.startsWith('static-')) {
|
||||||
|
if (confirm(`Удалить статическое событие ${id}?`)) {
|
||||||
|
alert(`Статическое событие ${id} удалено (заглушка)`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (confirm(`Удалить событие ${id}?`)) {
|
||||||
|
this.deleteEvent(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async showEventForm() {
|
||||||
|
const form = this.view.renderEventForm();
|
||||||
|
this.bindFormEvents(form, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
async showEditForm(id) {
|
||||||
|
try {
|
||||||
|
console.log('📝 Загружаем данные события для редактирования:', id);
|
||||||
|
const event = await this.model.getEventById(id);
|
||||||
|
const form = this.view.renderEventForm(event);
|
||||||
|
this.bindFormEvents(form, true);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('❌ Ошибка загрузки события:', error);
|
||||||
|
alert('Ошибка загрузки события для редактирования');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
showStaticEditForm(id) {
|
||||||
|
// Для статических событий создаем форму с примерными данными
|
||||||
|
const staticEvent = {
|
||||||
|
id: id,
|
||||||
|
title: 'Статическое событие ' + id.replace('static-', ''),
|
||||||
|
description: 'Это статическое событие из HTML разметки',
|
||||||
|
imageUrl: 'https://example.com/static-image.jpg'
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = this.view.renderEventForm(staticEvent);
|
||||||
|
this.bindFormEvents(form, true);
|
||||||
|
|
||||||
|
// Показываем сообщение, что это демо
|
||||||
|
setTimeout(() => {
|
||||||
|
alert('Это демо-режим редактирования для статического события. В реальном приложении данные будут загружены с сервера.');
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
bindFormEvents(form, isEdit) {
|
||||||
|
document.getElementById('cancelBtn').addEventListener('click', () => {
|
||||||
|
this.view.removeEventForm();
|
||||||
|
});
|
||||||
|
|
||||||
|
form.addEventListener('submit', async (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
await this.handleFormSubmit(isEdit);
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelector('.event-form-overlay').addEventListener('click', (e) => {
|
||||||
|
if (e.target === e.currentTarget) {
|
||||||
|
this.view.removeEventForm();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleFormSubmit(isEdit) {
|
||||||
|
const form = document.getElementById('eventForm');
|
||||||
|
const eventId = form.dataset.eventId;
|
||||||
|
|
||||||
|
const formData = {
|
||||||
|
title: document.getElementById('eventTitle').value,
|
||||||
|
description: document.getElementById('eventDescription').value,
|
||||||
|
imageUrl: document.getElementById('eventImage').value,
|
||||||
|
categoryId: 1,
|
||||||
|
typeId: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('📤 Отправляем данные:', formData, isEdit ? `для события ${eventId}` : 'новое событие');
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (isEdit && !eventId.startsWith('static-')) {
|
||||||
|
await this.model.updateEvent(eventId, formData);
|
||||||
|
alert('Событие успешно обновлено!');
|
||||||
|
} else if (isEdit && eventId.startsWith('static-')) {
|
||||||
|
// Для статических событий просто показываем сообщение
|
||||||
|
alert(`Событие ${eventId} обновлено (демо-режим)`);
|
||||||
|
} else {
|
||||||
|
await this.model.createEvent(formData);
|
||||||
|
alert('Событие успешно создано!');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.view.removeEventForm();
|
||||||
|
await this.loadEvents();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка сохранения:', error);
|
||||||
|
alert('Ошибка при сохранении события');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteEvent(id) {
|
||||||
|
try {
|
||||||
|
await this.model.deleteEvent(id);
|
||||||
|
alert('Событие успешно удалено!');
|
||||||
|
await this.loadEvents();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Ошибка удаления:', error);
|
||||||
|
alert('Ошибка при удалении события');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', async () => {
|
||||||
|
console.log('✅ DOM загружен');
|
||||||
|
|
||||||
|
try {
|
||||||
|
console.log('🚀 Запускаем EventController...');
|
||||||
|
const controller = new EventController('eventsContainer');
|
||||||
|
await controller.initialize();
|
||||||
|
console.log('🎉 MVC компонент успешно инициализирован');
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('💥 Ошибка инициализации MVC компонента:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
38
src/js/catalog.js
Normal file
38
src/js/catalog.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
function addCatalogItem(title, description, imageUrl, type) {
|
||||||
|
const container = document.getElementById('catalogContainer');
|
||||||
|
|
||||||
|
const newItem = document.createElement('article');
|
||||||
|
newItem.className = 'catalog-item';
|
||||||
|
newItem.innerHTML = `
|
||||||
|
<img src="${imageUrl}" alt="${title}" />
|
||||||
|
<div class="catalog-item-content">
|
||||||
|
<h3>${title}</h3>
|
||||||
|
<p>${description}</p>
|
||||||
|
</div>
|
||||||
|
<button>Узнать больше</button>
|
||||||
|
`;
|
||||||
|
|
||||||
|
container.appendChild(newItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
const form = document.getElementById('addCatalogForm');
|
||||||
|
|
||||||
|
if (form) {
|
||||||
|
form.addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
|
||||||
|
const inputs = this.querySelectorAll('input, select');
|
||||||
|
const title = inputs[0].value;
|
||||||
|
const description = inputs[1].value;
|
||||||
|
const imageUrl = inputs[2].value;
|
||||||
|
const type = inputs[3].value;
|
||||||
|
|
||||||
|
if (title && description && imageUrl && type) {
|
||||||
|
addCatalogItem(title, description, imageUrl, type);
|
||||||
|
this.reset();
|
||||||
|
alert('Событие добавлено в каталог!');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
85
src/pages/about.html
Normal file
85
src/pages/about.html
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>О сервисе | StreamCore</title>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="header">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<div class="logo">🎮 StreamCore</div>
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg p-0">
|
||||||
|
<button class="navbar-toggler d-lg-none" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item"><a class="nav-link" href="index.html">Главная</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="catalog.html">Каталог</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="streams.html">Трансляции</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.html">Профиль</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="about.html">О нас</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="page about-page">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h1>О сервисе StreamCore</h1>
|
||||||
|
|
||||||
|
<section class="about-section">
|
||||||
|
<h2><i class="bi bi-rocket-takeoff me-2"></i>Наша миссия</h2>
|
||||||
|
<p>
|
||||||
|
StreamCore — это инновационная платформа для стриминга, которая объединяет лучшие элементы киберпанка и современных технологий.
|
||||||
|
Мы стремимся предоставить уникальный опыт для зрителей и стримеров, создавая атмосферу неона и цифрового будущего.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="about-section">
|
||||||
|
<h2><i class="bi bi-gift me-2"></i>Что мы предлагаем</h2>
|
||||||
|
<ul>
|
||||||
|
<li>Множество трансляций в режиме реального времени с профессиональными и начинающими стримерами.</li>
|
||||||
|
<li>Каталог эксклюзивных цифровых товаров и мерча в стиле киберпанк.</li>
|
||||||
|
<li>Интерактивное сообщество с возможностями для общения и обмена опытом.</li>
|
||||||
|
<li>Продвинутые настройки профиля и персонализация интерфейса.</li>
|
||||||
|
<li>Стабильную работу и удобный дизайн на всех устройствах.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="about-section">
|
||||||
|
<h2><i class="bi bi-people me-2"></i>Команда</h2>
|
||||||
|
<p>
|
||||||
|
Наша команда состоит из энтузиастов и профессионалов в области технологий, дизайна и цифрового искусства, объединённых идеей создания лучшего стримингового сервиса в киберпанковской эстетике.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="footer-info">
|
||||||
|
<p>Контакты: info@streamcore.com | +7 (999) 123-45-67</p>
|
||||||
|
<p>Часы работы: Пн–Вс, 10:00–22:00</p>
|
||||||
|
<p>Адрес: Неон-сити, ул. Цифровая, д.42</p>
|
||||||
|
</div>
|
||||||
|
<div class="social-icons">
|
||||||
|
<a href="#" aria-label="Facebook"><i class="fab fa-facebook-f fa-lg"></i></a>
|
||||||
|
<a href="#" aria-label="ВКонтакте"><i class="fab fa-vk fa-lg"></i></a>
|
||||||
|
<a href="#" aria-label="Telegram"><i class="fab fa-telegram-plane fa-lg"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
142
src/pages/catalog.html
Normal file
142
src/pages/catalog.html
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Каталог | StreamCore</title>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="header">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<div class="logo">🎮 StreamCore</div>
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg p-0">
|
||||||
|
<button class="navbar-toggler d-lg-none" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item"><a class="nav-link" href="index.html">Главная</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="catalog.html">Каталог</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="streams.html">Трансляции</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.html">Профиль</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="about.html">О нас</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="page">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h1>Каталог стримов и событий</h1>
|
||||||
|
<p>Выбирай из нашего ассортимента уникальных стримов, концертов и кибермероприятий.</p>
|
||||||
|
|
||||||
|
<section class="catalog-grid" id="catalogContainer">
|
||||||
|
<article class="catalog-item">
|
||||||
|
<img src="https://i.redd.it/33a9wbkwxzmd1.jpeg" alt="Стрим 1" />
|
||||||
|
<div class="catalog-item-content">
|
||||||
|
<h3>Neon Beats Live</h3>
|
||||||
|
<p>Погружение в атмосферу неоновых ритмов с лучшими диджеями.</p>
|
||||||
|
</div>
|
||||||
|
<button class="catalog-btn">Смотреть</button>
|
||||||
|
<div class="event-actions">
|
||||||
|
<button class="btn-edit" data-id="static-1">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn-delete" data-id="static-1">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="catalog-item">
|
||||||
|
<img src="https://bogatyr.club/uploads/posts/2023-03/12827/thumbs/1677966670_bogatyr-club-p-kiberpank-komnata-foni-instagram-8.jpg" alt="Cyberpunk Festival" />
|
||||||
|
<div class="catalog-item-content">
|
||||||
|
<h3>Cyberpunk Festival</h3>
|
||||||
|
<p>Грандиозный фестиваль с музыкой и цифровыми шоу.</p>
|
||||||
|
</div>
|
||||||
|
<button class="catalog-btn">Смотреть</button>
|
||||||
|
<div class="event-actions">
|
||||||
|
<button class="btn-edit" data-id="static-2">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn-delete" data-id="static-2">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="catalog-item">
|
||||||
|
<img src="https://kartinki.pics/uploads/posts/2021-07/thumbs/1625655487_35-kartinkin-com-p-kiberpank-oboi-krasivie-38.jpg" alt="VR Rave Party" />
|
||||||
|
<div class="catalog-item-content">
|
||||||
|
<h3>VR Rave Party</h3>
|
||||||
|
<p>Погрузись в виртуальную реальность с нашими эксклюзивными стримами.</p>
|
||||||
|
</div>
|
||||||
|
<button class="catalog-btn">Смотреть</button>
|
||||||
|
<div class="event-actions">
|
||||||
|
<button class="btn-edit" data-id="static-3">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn-delete" data-id="static-3">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="catalog-item">
|
||||||
|
<img src="https://kartinki.pics/pics/uploads/posts/2022-08/1660474027_1-kartinkin-net-p-kiberpank-oboi-krasivo-1.jpg" alt="Hologram Show" />
|
||||||
|
<div class="catalog-item-content">
|
||||||
|
<h3>Hologram Show</h3>
|
||||||
|
<p>Уникальное цифровое шоу с голографическими эффектами.</p>
|
||||||
|
</div>
|
||||||
|
<button class="catalog-btn">Смотреть</button>
|
||||||
|
<div class="event-actions">
|
||||||
|
<button class="btn-edit" data-id="static-4">
|
||||||
|
<i class="bi bi-pencil"></i>
|
||||||
|
</button>
|
||||||
|
<button class="btn-delete" data-id="static-4">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="catalog-grid" id="eventsContainer">
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div class="text-center mt-4">
|
||||||
|
<button id="addEventBtn" class="btn btn-neon btn-lg">
|
||||||
|
<i class="bi bi-plus-circle me-2"></i>Добавить новое событие
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="footer-info">
|
||||||
|
<p>Контакты: info@streamcore.com | +7 (999) 123-45-67</p>
|
||||||
|
<p>Часы работы: Пн–Вс, 10:00–22:00</p>
|
||||||
|
<p>Адрес: Неон-сити, ул. Цифровая, д.42</p>
|
||||||
|
</div>
|
||||||
|
<div class="social-icons">
|
||||||
|
<a href="#" aria-label="Facebook"><i class="fab fa-facebook-f fa-lg"></i></a>
|
||||||
|
<a href="#" aria-label="ВКонтакте"><i class="fab fa-vk fa-lg"></i></a>
|
||||||
|
<a href="#" aria-label="Telegram"><i class="fab fa-telegram-plane fa-lg"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<script type='module' src="/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/js/catalog-mvc-bundle.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
89
src/pages/index.html
Normal file
89
src/pages/index.html
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Главная | StreamCore</title>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="header">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<div class="logo">🎮 StreamCore</div>
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg p-0">
|
||||||
|
<button class="navbar-toggler d-lg-none" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="index.html">Главная</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="catalog.html">Каталог</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="streams.html">Трансляции</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="profile.html">Профиль</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="about.html">О нас</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="page">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h1>Добро пожаловать в StreamCore</h1>
|
||||||
|
<p>Твой портал в мир киберспорта, электронной музыки и цифрового искусства. Следи за новыми трансляциями, знакомься с артистами и участвуй в событиях!</p>
|
||||||
|
|
||||||
|
<section class="features-grid" id="featuresContainer">
|
||||||
|
<article class="feature-item">
|
||||||
|
<h3><i class="bi bi-trophy me-2"></i>Киберспорт</h3>
|
||||||
|
<p>Самые масштабные турниры и захватывающие матчи в прямом эфире.</p>
|
||||||
|
<button onclick="location.href='streams.html'">Смотреть трансляции</button>
|
||||||
|
</article>
|
||||||
|
<article class="feature-item">
|
||||||
|
<h3><i class="bi bi-music-note-beamed me-2"></i>Электронная музыка</h3>
|
||||||
|
<p>Эксклюзивные лайв-сеты от лучших диджеев и музыкантов.</p>
|
||||||
|
<button onclick="location.href='catalog.html#music'">Открыть каталог</button>
|
||||||
|
</article>
|
||||||
|
<article class="feature-item">
|
||||||
|
<h3><i class="bi bi-palette me-2"></i>Цифровое искусство</h3>
|
||||||
|
<p>Выставки, NFT-галереи и творческие проекты от художников.</p>
|
||||||
|
<button onclick="location.href='catalog.html#art'">Посмотреть работы</button>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="footer-info">
|
||||||
|
<p>Контакты: info@streamcore.com | +7 (999) 123-45-67</p>
|
||||||
|
<p>Часы работы: Пн–Вс, 10:00–22:00</p>
|
||||||
|
<p>Адрес: Неон-сити, ул. Цифровая, д.42</p>
|
||||||
|
</div>
|
||||||
|
<div class="social-icons">
|
||||||
|
<a href="#" aria-label="Facebook"><i class="fab fa-facebook-f"></i></a>
|
||||||
|
<a href="#" aria-label="ВКонтакте"><i class="fab fa-vk"></i></a>
|
||||||
|
<a href="#" aria-label="Telegram"><i class="fab fa-telegram-plane"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
76
src/pages/profile.html
Normal file
76
src/pages/profile.html
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Профиль | StreamCore</title>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="header">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<div class="logo">🎮 StreamCore</div>
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg p-0">
|
||||||
|
<button class="navbar-toggler d-lg-none" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item"><a class="nav-link" href="index.html">Главная</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="catalog.html">Каталог</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="streams.html">Трансляции</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.html">Профиль</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="about.html">О нас</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="page">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h1>Профиль пользователя</h1>
|
||||||
|
|
||||||
|
<section class="profile-container">
|
||||||
|
<div class="d-flex flex-column flex-md-row align-items-center gap-4">
|
||||||
|
<div class="profile-avatar">
|
||||||
|
<img src="https://abrakadabra.fun/uploads/posts/2021-12/1640161252_2-abrakadabra-fun-p-devushki-v-stile-kiberpank-2.jpg" alt="Аватар пользователя" />
|
||||||
|
</div>
|
||||||
|
<div class="profile-info">
|
||||||
|
<h2>Имя пользователя: <span>NeonGamer</span></h2>
|
||||||
|
<p><strong>Email:</strong> neongamer@example.com</p>
|
||||||
|
<p><strong>Подписка:</strong> Pro</p>
|
||||||
|
<p><strong>Дата регистрации:</strong> 12.04.2024</p>
|
||||||
|
<p><strong>Последний вход:</strong> Сегодня, 14:35</p>
|
||||||
|
<button class="btn-edit-profile">Редактировать профиль</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="footer-info">
|
||||||
|
<p>Контакты: info@streamcore.com | +7 (999) 123-45-67</p>
|
||||||
|
<p>Часы работы: Пн–Вс, 10:00–22:00</p>
|
||||||
|
<p>Адрес: Неон-сити, ул. Цифровая, д.42</p>
|
||||||
|
</div>
|
||||||
|
<div class="social-icons">
|
||||||
|
<a href="#" aria-label="Facebook"><i class="fab fa-facebook-f fa-lg"></i></a>
|
||||||
|
<a href="#" aria-label="ВКонтакте"><i class="fab fa-vk fa-lg"></i></a>
|
||||||
|
<a href="#" aria-label="Telegram"><i class="fab fa-telegram-plane fa-lg"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
91
src/pages/streams.html
Normal file
91
src/pages/streams.html
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>Трансляции | StreamCore</title>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css" rel="stylesheet">
|
||||||
|
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;700&display=swap" rel="stylesheet">
|
||||||
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
|
||||||
|
<link rel="stylesheet" href="/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/css/custom.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header class="header">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<div class="logo">🎮 StreamCore</div>
|
||||||
|
|
||||||
|
<nav class="navbar navbar-expand-lg p-0">
|
||||||
|
<button class="navbar-toggler d-lg-none" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav">
|
||||||
|
<li class="nav-item"><a class="nav-link" href="index.html">Главная</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="catalog.html">Каталог</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="streams.html">Трансляции</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="profile.html">Профиль</a></li>
|
||||||
|
<li class="nav-item"><a class="nav-link" href="about.html">О нас</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main class="page">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<h1>Текущие и предстоящие трансляции</h1>
|
||||||
|
<p>Выбирай любимые трансляции и присоединяйся к просмотру в реальном времени!</p>
|
||||||
|
|
||||||
|
<section class="streams-grid" id="streamsContainer">
|
||||||
|
<article class="stream-item">
|
||||||
|
<img src="https://kartinki.pics/uploads/posts/2021-07/thumbs/1625655522_52-kartinkin-com-p-kiberpank-oboi-krasivie-57.jpg" alt="Трансляция 1" />
|
||||||
|
<h3>Neon Cyber Show</h3>
|
||||||
|
<p>В прямом эфире: DJ Neonmix с уникальными сетами и визуалами.</p>
|
||||||
|
<button>Смотреть сейчас</button>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="stream-item">
|
||||||
|
<img src="https://img3.akspic.ru/previews/6/6/1/2/7/172166/172166-kiberpank_2077-kiberpank-bridzhit-svet-purpur-550x310.jpg" alt="Трансляция 2" />
|
||||||
|
<h3>Киберспорт Матч</h3>
|
||||||
|
<p>Прямой эфир крупнейшего турнира по киберспорту.</p>
|
||||||
|
<button>Присоединиться</button>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="stream-item">
|
||||||
|
<img src="https://img3.akspic.ru/previews/4/6/0/4/6/164064/164064-goroda_kiberpank-kiberpank_2077-kiberpank-nauchnaya_fantastika-cifrovoe_iskusstvo-550x310.jpg" alt="Трансляция 3" />
|
||||||
|
<h3>VR Adventure Live</h3>
|
||||||
|
<p>Эксклюзивный VR стрим с комментариями и интерактивом.</p>
|
||||||
|
<button>Смотреть сейчас</button>
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<article class="stream-item">
|
||||||
|
<img src="https://kartinki.pics/pics/uploads/posts/2022-08/thumbs/1660474007_21-kartinkin-net-p-kiberpank-oboi-krasivo-26.jpg" alt="Трансляция 4" />
|
||||||
|
<h3>Цифровой Концерт</h3>
|
||||||
|
<p>Виртуальный концерт с неоновыми спецэффектами и лайв-сетами.</p>
|
||||||
|
<button>Присоединиться</button>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="footer">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="footer-info">
|
||||||
|
<p>Контакты: info@streamcore.com | +7 (999) 123-45-67</p>
|
||||||
|
<p>Часы работы: Пн–Вс, 10:00–22:00</p>
|
||||||
|
<p>Адрес: Неон-сити, ул. Цифровая, д.42</p>
|
||||||
|
</div>
|
||||||
|
<div class="social-icons">
|
||||||
|
<a href="#" aria-label="Facebook"><i class="fab fa-facebook-f fa-lg"></i></a>
|
||||||
|
<a href="#" aria-label="ВКонтакте"><i class="fab fa-vk fa-lg"></i></a>
|
||||||
|
<a href="#" aria-label="Telegram"><i class="fab fa-telegram-plane fa-lg"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
streamcore-bootstrap/streamcore-bootstrap/.gitignore
vendored
Normal file
24
streamcore-bootstrap/streamcore-bootstrap/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
13
streamcore-bootstrap/streamcore-bootstrap/index.html
Normal file
13
streamcore-bootstrap/streamcore-bootstrap/index.html
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
24
streamcore-bootstrap/streamcore-bootstrap/my-bootstrap-site/.gitignore
vendored
Normal file
24
streamcore-bootstrap/streamcore-bootstrap/my-bootstrap-site/.gitignore
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
*.local
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
import js from "@eslint/js";
|
||||||
|
import globals from "globals";
|
||||||
|
import pluginReact from "eslint-plugin-react";
|
||||||
|
import { defineConfig } from "eslint/config";
|
||||||
|
|
||||||
|
|
||||||
|
export default defineConfig([
|
||||||
|
{ files: ["**/*.{js,mjs,cjs,jsx}"], plugins: { js }, extends: ["js/recommended"] },
|
||||||
|
{ files: ["**/*.{js,mjs,cjs,jsx}"], languageOptions: { globals: globals.browser } },
|
||||||
|
pluginReact.configs.flat.recommended,
|
||||||
|
]);
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Vite App</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="app"></div>
|
||||||
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
4046
streamcore-bootstrap/streamcore-bootstrap/my-bootstrap-site/package-lock.json
generated
Normal file
4046
streamcore-bootstrap/streamcore-bootstrap/my-bootstrap-site/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "my-bootstrap-site",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@eslint/js": "^9.27.0",
|
||||||
|
"eslint": "^9.27.0",
|
||||||
|
"eslint-plugin-react": "^7.37.5",
|
||||||
|
"globals": "^16.1.0",
|
||||||
|
"vite": "^6.3.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^5.3.6",
|
||||||
|
"bootstrap-icons": "^1.13.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,9 @@
|
|||||||
|
export function setupCounter(element) {
|
||||||
|
let counter = 0
|
||||||
|
const setCounter = (count) => {
|
||||||
|
counter = count
|
||||||
|
element.innerHTML = `count is ${counter}`
|
||||||
|
}
|
||||||
|
element.addEventListener('click', () => setCounter(counter + 1))
|
||||||
|
setCounter(0)
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#F7DF1E" d="M0 0h256v256H0V0Z"></path><path d="m67.312 213.932l19.59-11.856c3.78 6.701 7.218 12.371 15.465 12.371c7.905 0 12.89-3.092 12.89-15.12v-81.798h24.057v82.138c0 24.917-14.606 36.259-35.916 36.259c-19.245 0-30.416-9.967-36.087-21.996m85.07-2.576l19.588-11.341c5.157 8.421 11.859 14.607 23.715 14.607c9.969 0 16.325-4.984 16.325-11.858c0-8.248-6.53-11.17-17.528-15.98l-6.013-2.58c-17.357-7.387-28.87-16.667-28.87-36.257c0-18.044 13.747-31.792 35.228-31.792c15.294 0 26.292 5.328 34.196 19.247l-18.732 12.03c-4.125-7.389-8.591-10.31-15.465-10.31c-7.046 0-11.514 4.468-11.514 10.31c0 7.217 4.468 10.14 14.778 14.608l6.014 2.577c20.45 8.765 31.963 17.7 31.963 37.804c0 21.654-17.012 33.51-39.867 33.51c-22.339 0-36.774-10.654-43.819-24.574"></path></svg>
|
||||||
|
After Width: | Height: | Size: 995 B |
@@ -0,0 +1,24 @@
|
|||||||
|
import './style.css'
|
||||||
|
import javascriptLogo from './javascript.svg'
|
||||||
|
import viteLogo from '/vite.svg'
|
||||||
|
import { setupCounter } from './counter.js'
|
||||||
|
|
||||||
|
document.querySelector('#app').innerHTML = `
|
||||||
|
<div>
|
||||||
|
<a href="https://vite.dev" target="_blank">
|
||||||
|
<img src="${viteLogo}" class="logo" alt="Vite logo" />
|
||||||
|
</a>
|
||||||
|
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank">
|
||||||
|
<img src="${javascriptLogo}" class="logo vanilla" alt="JavaScript logo" />
|
||||||
|
</a>
|
||||||
|
<h1>Hello Vite!</h1>
|
||||||
|
<div class="card">
|
||||||
|
<button id="counter" type="button"></button>
|
||||||
|
</div>
|
||||||
|
<p class="read-the-docs">
|
||||||
|
Click on the Vite logo to learn more
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
|
||||||
|
setupCounter(document.querySelector('#counter'))
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
:root {
|
||||||
|
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
color-scheme: light dark;
|
||||||
|
color: rgba(255, 255, 255, 0.87);
|
||||||
|
background-color: #242424;
|
||||||
|
|
||||||
|
font-synthesis: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #646cff;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #535bf2;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
place-items: center;
|
||||||
|
min-width: 320px;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3.2em;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
max-width: 1280px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height: 6em;
|
||||||
|
padding: 1.5em;
|
||||||
|
will-change: filter;
|
||||||
|
transition: filter 300ms;
|
||||||
|
}
|
||||||
|
.logo:hover {
|
||||||
|
filter: drop-shadow(0 0 2em #646cffaa);
|
||||||
|
}
|
||||||
|
.logo.vanilla:hover {
|
||||||
|
filter: drop-shadow(0 0 2em #f7df1eaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-the-docs {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
padding: 0.6em 1.2em;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 500;
|
||||||
|
font-family: inherit;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color 0.25s;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
border-color: #646cff;
|
||||||
|
}
|
||||||
|
button:focus,
|
||||||
|
button:focus-visible {
|
||||||
|
outline: 4px auto -webkit-focus-ring-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
color: #213547;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #747bff;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
}
|
||||||
2238
streamcore-bootstrap/streamcore-bootstrap/package-lock.json
generated
Normal file
2238
streamcore-bootstrap/streamcore-bootstrap/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
22
streamcore-bootstrap/streamcore-bootstrap/package.json
Normal file
22
streamcore-bootstrap/streamcore-bootstrap/package.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "streamcore-bootstrap",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "vite build",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"eslint": "^9.27.0",
|
||||||
|
"eslint-config-prettier": "^10.1.5",
|
||||||
|
"eslint-plugin-prettier": "^5.4.0",
|
||||||
|
"prettier": "^3.5.3",
|
||||||
|
"vite": "^6.3.5"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"bootstrap": "^5.3.6",
|
||||||
|
"bootstrap-icons": "^1.13.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
9
streamcore-bootstrap/streamcore-bootstrap/src/counter.js
Normal file
9
streamcore-bootstrap/streamcore-bootstrap/src/counter.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export function setupCounter(element) {
|
||||||
|
let counter = 0
|
||||||
|
const setCounter = (count) => {
|
||||||
|
counter = count
|
||||||
|
element.innerHTML = `count is ${counter}`
|
||||||
|
}
|
||||||
|
element.addEventListener('click', () => setCounter(counter + 1))
|
||||||
|
setCounter(0)
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="32" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 256"><path fill="#F7DF1E" d="M0 0h256v256H0V0Z"></path><path d="m67.312 213.932l19.59-11.856c3.78 6.701 7.218 12.371 15.465 12.371c7.905 0 12.89-3.092 12.89-15.12v-81.798h24.057v82.138c0 24.917-14.606 36.259-35.916 36.259c-19.245 0-30.416-9.967-36.087-21.996m85.07-2.576l19.588-11.341c5.157 8.421 11.859 14.607 23.715 14.607c9.969 0 16.325-4.984 16.325-11.858c0-8.248-6.53-11.17-17.528-15.98l-6.013-2.58c-17.357-7.387-28.87-16.667-28.87-36.257c0-18.044 13.747-31.792 35.228-31.792c15.294 0 26.292 5.328 34.196 19.247l-18.732 12.03c-4.125-7.389-8.591-10.31-15.465-10.31c-7.046 0-11.514 4.468-11.514 10.31c0 7.217 4.468 10.14 14.778 14.608l6.014 2.577c20.45 8.765 31.963 17.7 31.963 37.804c0 21.654-17.012 33.51-39.867 33.51c-22.339 0-36.774-10.654-43.819-24.574"></path></svg>
|
||||||
|
After Width: | Height: | Size: 995 B |
24
streamcore-bootstrap/streamcore-bootstrap/src/main.js
Normal file
24
streamcore-bootstrap/streamcore-bootstrap/src/main.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
import './style.css'
|
||||||
|
import javascriptLogo from './javascript.svg'
|
||||||
|
import viteLogo from '/vite.svg'
|
||||||
|
import { setupCounter } from './counter.js'
|
||||||
|
|
||||||
|
document.querySelector('#app').innerHTML = `
|
||||||
|
<div>
|
||||||
|
<a href="https://vite.dev" target="_blank">
|
||||||
|
<img src="${viteLogo}" class="logo" alt="Vite logo" />
|
||||||
|
</a>
|
||||||
|
<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" target="_blank">
|
||||||
|
<img src="${javascriptLogo}" class="logo vanilla" alt="JavaScript logo" />
|
||||||
|
</a>
|
||||||
|
<h1>Hello Vite!</h1>
|
||||||
|
<div class="card">
|
||||||
|
<button id="counter" type="button"></button>
|
||||||
|
</div>
|
||||||
|
<p class="read-the-docs">
|
||||||
|
Click on the Vite logo to learn more
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
`
|
||||||
|
|
||||||
|
setupCounter(document.querySelector('#counter'))
|
||||||
96
streamcore-bootstrap/streamcore-bootstrap/src/style.css
Normal file
96
streamcore-bootstrap/streamcore-bootstrap/src/style.css
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
:root {
|
||||||
|
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
font-weight: 400;
|
||||||
|
|
||||||
|
color-scheme: light dark;
|
||||||
|
color: rgba(255, 255, 255, 0.87);
|
||||||
|
background-color: #242424;
|
||||||
|
|
||||||
|
font-synthesis: none;
|
||||||
|
text-rendering: optimizeLegibility;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #646cff;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #535bf2;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
display: flex;
|
||||||
|
place-items: center;
|
||||||
|
min-width: 320px;
|
||||||
|
min-height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 3.2em;
|
||||||
|
line-height: 1.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#app {
|
||||||
|
max-width: 1280px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo {
|
||||||
|
height: 6em;
|
||||||
|
padding: 1.5em;
|
||||||
|
will-change: filter;
|
||||||
|
transition: filter 300ms;
|
||||||
|
}
|
||||||
|
.logo:hover {
|
||||||
|
filter: drop-shadow(0 0 2em #646cffaa);
|
||||||
|
}
|
||||||
|
.logo.vanilla:hover {
|
||||||
|
filter: drop-shadow(0 0 2em #f7df1eaa);
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
padding: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.read-the-docs {
|
||||||
|
color: #888;
|
||||||
|
}
|
||||||
|
|
||||||
|
button {
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
padding: 0.6em 1.2em;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: 500;
|
||||||
|
font-family: inherit;
|
||||||
|
background-color: #1a1a1a;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: border-color 0.25s;
|
||||||
|
}
|
||||||
|
button:hover {
|
||||||
|
border-color: #646cff;
|
||||||
|
}
|
||||||
|
button:focus,
|
||||||
|
button:focus-visible {
|
||||||
|
outline: 4px auto -webkit-focus-ring-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-color-scheme: light) {
|
||||||
|
:root {
|
||||||
|
color: #213547;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
a:hover {
|
||||||
|
color: #747bff;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
vite.config.js
Normal file
29
vite.config.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: 'src/pages',
|
||||||
|
server: {
|
||||||
|
port: 5173
|
||||||
|
},
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
'@': path.resolve(__dirname, 'src')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
outDir: '../../dist',
|
||||||
|
rollupOptions: {
|
||||||
|
input: {
|
||||||
|
main: path.resolve(__dirname, 's/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/pages/index.html'),
|
||||||
|
catalog: path.resolve(__dirname, '/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/pages/catalog.html'),
|
||||||
|
streams: path.resolve(__dirname, '/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/pages/streams.html'),
|
||||||
|
profile: path.resolve(__dirname, '/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/pages/profile.html'),
|
||||||
|
about: path.resolve(__dirname, '/Users/marva/University/4 semestr/Internet programmer/StreamCore_IP/src/pages/about.html')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user