Compare commits

...

2 Commits

Author SHA1 Message Date
tylen
36a82a3789 frontend: init project with some basic invitation form 2025-08-31 22:35:47 +03:00
tylen
2bc48a6901 frontend: init project 2025-08-31 22:20:51 +03:00
16 changed files with 3790 additions and 0 deletions

24
frontend/.gitignore vendored Normal file
View 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?

69
frontend/README.md Normal file
View File

@ -0,0 +1,69 @@
# React + TypeScript + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
## Expanding the ESLint configuration
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
```js
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Remove tseslint.configs.recommended and replace with this
...tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
...tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
...tseslint.configs.stylisticTypeChecked,
// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```

23
frontend/eslint.config.js Normal file
View File

@ -0,0 +1,23 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { globalIgnores } from 'eslint/config'
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs['recommended-latest'],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])

13
frontend/index.html Normal file
View File

@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/tree-evergreen-svgrepo-com.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Приглашение для наших любимых друзей</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

3396
frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

29
frontend/package.json Normal file
View File

@ -0,0 +1,29 @@
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite --host",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^19.1.1",
"react-dom": "^19.1.1"
},
"devDependencies": {
"@eslint/js": "^9.33.0",
"@types/react": "^19.1.10",
"@types/react-dom": "^19.1.7",
"@vitejs/plugin-react": "^5.0.0",
"eslint": "^9.33.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.3.0",
"typescript": "~5.8.3",
"typescript-eslint": "^8.39.1",
"vite": "^7.1.2"
}
}

View File

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="800px" height="800px" viewBox="0 0 64 64" enable-background="new 0 0 64 64" xml:space="preserve">
<g>
<path fill="#394240" d="M56.414,48.586L47.828,40H51c0.809,0,1.538-0.486,1.848-1.234s0.139-1.607-0.434-2.18L43.828,28H47
c0.809,0,1.538-0.486,1.848-1.234s0.139-1.607-0.434-2.18L39.828,16H43c0.809,0,1.538-0.486,1.848-1.234s0.139-1.607-0.434-2.18
l-12-12C32.023,0.195,31.512,0,31,0s-1.023,0.195-1.414,0.586l-12,12c-0.572,0.572-0.743,1.432-0.434,2.18S18.191,16,19,16h3.172
l-8.586,8.586c-0.572,0.572-0.743,1.432-0.434,2.18S14.191,28,15,28h3.172l-8.586,8.586c-0.572,0.572-0.743,1.432-0.434,2.18
S10.191,40,11,40h3.172l-8.586,8.586c-0.572,0.572-0.743,1.432-0.434,2.18S6.191,52,7,52h20v11c0,0.553,0.447,1,1,1h6
c0.553,0,1-0.447,1-1V52h20c0.809,0,1.538-0.486,1.848-1.234S56.986,49.158,56.414,48.586z M20,14c-0.547,0-0.789-0.211,0-1
c0.641-0.641,9-9,10-10s1-1,2,0c0,0,9.303,9.305,9.999,10s0.61,1,0.001,1C41.679,14,20.127,14,20,14z M16,26
c-0.547,0-0.766-0.234,0-1c0.444-0.443,5.951-5.951,9-9h12c3.001,3,8.384,8.385,9,9c0.859,0.859,0.469,1,0,1
C45.75,26,16.127,26,16,26z M12,38c-0.609,0-0.773-0.227,0-1c0.461-0.461,5.956-5.955,9-9h20c3.07,3.07,8.634,8.635,9,9
c0.648,0.648,0.656,1,0,1C49.479,38,12.135,38,12,38z M33,62h-4V52h4V62z M54,50c-1,0-45.297,0-46,0c-0.484,0-0.797-0.203,0-1
c0.478-0.477,5.96-5.961,9-9h28c3.065,3.066,8.614,8.615,9.002,9.002C54.695,49.695,54.578,50,54,50z"/>
<g>
<path fill="#B4CCB9" d="M20,14c0.127,0,21.679,0,22,0c0.609,0,0.695-0.305-0.001-1S32,3,32,3c-1-1-1-1-2,0s-9.359,9.359-10,10
C19.211,13.789,19.453,14,20,14z"/>
<path fill="#B4CCB9" d="M16,26c0.127,0,29.75,0,30,0c0.469,0,0.859-0.141,0-1c-0.616-0.615-5.999-6-9-9H25
c-3.049,3.049-8.556,8.557-9,9C15.234,25.766,15.453,26,16,26z"/>
<path fill="#B4CCB9" d="M12,38c0.135,0,37.479,0,38,0c0.656,0,0.648-0.352,0-1c-0.366-0.365-5.93-5.93-9-9H21
c-3.044,3.045-8.539,8.539-9,9C11.227,37.773,11.391,38,12,38z"/>
<path fill="#B4CCB9" d="M54.002,49.002C53.614,48.615,48.065,43.066,45,40H17c-3.04,3.039-8.522,8.523-9,9
c-0.797,0.797-0.484,1,0,1c0.703,0,45,0,46,0C54.578,50,54.695,49.695,54.002,49.002z"/>
</g>
<rect x="29" y="52" fill="#506C7F" width="4" height="10"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

42
frontend/src/App.css Normal file
View File

@ -0,0 +1,42 @@
#root {
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.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card {
padding: 2em;
}
.mainText {
color: #5f5e5e;
}

18
frontend/src/App.tsx Normal file
View File

@ -0,0 +1,18 @@
import './App.css'
function App() {
return (
<>
<h1>Приглашение на Новый год 2025-2026 🎄</h1>
<p className="mainText">
Дорогие, Пятки! 🦶
Приглашаем вас отпраздновать предстоящий Новый Год 2025-2026 с нами в сосновой избе, в которой, ко всему прочему, будет праздноваться годовщина нашей жизни в ней!
Мы ожидаем вас с 30.12.2025. Праздник обычно длится до 01.01.2025, но если вам будет безумно плохо, то иожно остаться и до второго числа.
</p>
</>
)
}
export default App

68
frontend/src/index.css Normal file
View File

@ -0,0 +1,68 @@
: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;
}
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;
}
}

10
frontend/src/main.tsx Normal file
View File

@ -0,0 +1,10 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)

1
frontend/src/vite-env.d.ts vendored Normal file
View File

@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@ -0,0 +1,27 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

7
frontend/tsconfig.json Normal file
View File

@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

View File

@ -0,0 +1,25 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2023",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

7
frontend/vite.config.ts Normal file
View File

@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
})